Очень плотно искал готовые исходники под SC16IS740 (он же 750, он же 760) для связи с ARM7 под i2c, но нашел только SPI.
В итоге пришлось разбираться самому, за два дня я эту связь победил.
Основная проблема была в том, чтобы заметить что адреса регистра передаются на микруху SC16.. со сдвигом влево на 3 бита. Очень уж это неявно указано в документации было.
Может кому пригодится, выкладываю исходники.
Примеч.: написано под IAR компил., реализация без прерываний.
файл -------------------------i2c.h ------------------------------------
Код
typedef struct {
uchar err;
uchar tmp;
} Ti2c;
#define THR 0x00 // transmit FIFO, write only
#define RHR 0x00 // receive FIFO, read oly
#define IER 0x01 // interrup enable reg., R/W
#define FCR 0x02 // FIFO control, write only
#define IIR 0x02 // interrupt status, read only
#define LCR 0x03 // line control, R/W
#define MCR 0x04 // modem control, R/W
#define LSR 0x05 // Line status, R/W
#define MSR 0x06 // Modem status, R/W
#define SPR 0x07 // scratch pad, R/W
#define TXFIFO 0x08 // TX FIFO, R
#define RXFIFO 0x09 // RX FIFO, R
/* special registers, LCR.7 must be set to 1 to R/W to these registers */
#define DLL 0x00 // baud rate divisor, low R/W
#define DLH 0x01 // baud rate divisor, hi R/W
#define EFR 0x02 // enhanced register, R/W
#define XON1 0x04 // flow control
#define XON2 0x05 // flow control
#define XOFF1 0x06 // flow control
#define XOFF2 0x07 // flow control
#define I20CONSET_I2EN 0x00000040 /* I2C Control Set Register */
#define I20CONSET_AA 0x00000004
#define I20CONSET_SI 0x00000008
#define I20CONSET_STO 0x00000010
#define I20CONSET_STA 0x00000020
#define I20CONCLR_AAC 0x00000004 /* I2C Control clear Register */
#define I20CONCLR_SIC 0x00000008
#define I20CONCLR_STAC 0x00000020
#define I20CONCLR_I2ENC 0x00000040
#define SC16_ADR 0x9A
#define RD_BIT 0x01
#define WR_BIT 0x00
#define SC16_RESET_ON IO0CLR= 1<<21 // ~sc16_rst висит на ноге P0.21 (ACTIVE LOW)
#define SC16_RESET_OFF IO0SET= 1<<21
void i2c_init();
void i2c_isr ();
uchar sc16_wr (uchar adr, uchar value);
uchar sc16_rd (uchar adr);
файл ----------------------------- i2c.c --------------------------------------------------
Код
uchar sc16_wr (uchar adr, uchar value) // ЗАПИСЬ БАЙТА В РЕГИСТР
// возвращает 1 если удачно передано
// 0 если неудачно
{
I20CONCLR = I20CONCLR_STAC | I20CONCLR_SIC | I20CONCLR_AAC; // clear all bits, кроме I2EN
I20CONSET = I20CONSET_STA; // set START
while (I20STAT != 0x08); // ждем
I20DAT = SC16_ADR | WR_BIT; // адрес микрухи
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x18) { i2c_error (); return 0; }
I20DAT = adr<<3; // адрес регистра
I20CONCLR = I20CONCLR_STAC; // clear START
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x28) { i2c_error (); return 0; }
I20DAT = value; // значение регистра
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x28) { i2c_error (); return 0; }
I20CONSET = I20CONSET_STO; // после данных сразу передаем STOP
I20CONCLR = I20CONCLR_SIC; // передача байта
//while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0xF8) { i2c_error (); return 0; }
return 1;
}
// ------------------------------------------------------------------------------------
uchar sc16_rd (uchar adr) // ЧТЕНИЕ байта по I2c
// возвращает 1 если удачно передано
// 0 если неудачно
{
uchar tmp;
I20CONCLR = I20CONCLR_STAC | I20CONCLR_SIC | I20CONCLR_AAC; // clear all bits, кроме I2EN
I20CONSET = I20CONSET_STA; // set START
while (I20STAT != 0x08); // ждем
I20DAT = SC16_ADR | WR_BIT; // адрес микрухи
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x18) { i2c_error (); return 0; }
I20DAT = adr<<3; // адрес регистра
I20CONCLR = I20CONCLR_STAC; // clear START
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x28) { i2c_error (); return 0; }
I20CONSET = I20CONSET_STA; // repeated START
I20CONCLR = I20CONCLR_SIC; // передача байта
while (I20STAT != 0x10); // ждем
I20DAT = SC16_ADR | RD_BIT; // адрес микрухи
I20CONCLR = I20CONCLR_SIC; // передача байта
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x40) { i2c_error (); return 0; }
I20CONCLR = I20CONCLR_STAC | I20CONCLR_AAC; // clear START; про AA написано для наглядности, хотя он итак 0
I20CONCLR = I20CONCLR_SIC; // поехали на чтение
while ((I20CONSET & I20CONSET_SI) ==0); // ждем пока SI не установится в 1
if (I20STAT != 0x58) { i2c_error (); return 0; }
tmp = I20DAT;
I20CONSET = I20CONSET_STO;
I20CONCLR = I20CONCLR_SIC; // поехали
return tmp;
}
void i2c_init()
{
SC16_RESET_ON;
SC16_RESET_OFF;
// перед тем как юзать микруху SC16 по I2c необходимо выждать минимум 3 us.
uint i=0; while (i<65000) { i2c.tmp+= IO0PIN; i++; } // <<<<<< типа ПАУЗА
//PINSEL0 |= 0x50; // P0.3 = SDA, P0.2 = SCL
// Initialize I2C0
I20CONCLR = 0xFF;
I20CONSET = 0x40; // Master mode configuration, I2EN bit set
// частота CLK для I2c
I20SCLH = 0xFF; // I2c_FREQ = FPCLK / ( SCLH + SCLL), так что частоту считайте сами под свой кристалл
I20SCLL = 0xFF; //
}
Сообщение отредактировал buletz - Mar 21 2008, 14:25