如何通過(guò)MAX2990 I2C接口向標(biāo)準(zhǔn)EEPROM (24C04)連接
引言
本文介紹了如何通過(guò)MAX2990電力線(xiàn)通信調(diào)制解調(diào)器的I2C接口與外部EEPROM 24C04連接,并給出了相應(yīng)的固件例程。I²C總線(xiàn)受控于MAX2990 (主機(jī)),24C04 EEPROM為從機(jī)器件。以下框圖給出了本文示例的硬件配置。
固件說(shuō)明
I²C接口初始化
一旦使能I²C模塊,SCL和SDA必須配置成漏極開(kāi)路狀態(tài),以確保I²C總線(xiàn)通信正常。由于I²C是GPIO端口的一個(gè)替代功能,固件必須確保SCL和SDA輸入在初始化期間禁止上拉(通過(guò)對(duì)端口控制器的輸出位寫(xiě)零實(shí)現(xiàn))。
示例中,時(shí)鐘頻率為250kHz。首先需要配置MAX2990的I²C接口:
PO1_bit.Bit2 = 0; // Disables the GPIO function of the PO1_bit.Bit3 = 0; // I2C pins I2CCN_bit.I2CEN = 0; // Makes sure that I2C is disabled // to allow the changing of the I2C settings I2CCN_bit.I2CMST = 1; // Sets the I2C engine to master mode I2CCN_bit.I2CEA = 0; // 7-bit address mode I2CCK_bit.I2CCKL = 0x40; // 2µs CLK-low, to define I2C frequency I2CCK_bit.I2CCKH = 0x40; // 2µs CLK-high, to define I2C frequency I2CTO = 200; // I2C_TIMEOUT I2CST = 0x400; // Resets I2C status register I2CCN_bit.I2CEN = 1; // Enables the I2C engine
寫(xiě)模式
寫(xiě)入24C04 EEPROM時(shí),必須通過(guò)I²C接口寫(xiě)入以下字節(jié):
- EEPROM的I²C總線(xiàn)地址(這里為0xA0)
- EEPROM存儲(chǔ)器的地址
- 數(shù)據(jù)字節(jié)(地址將自動(dòng)遞增)
示例中試圖寫(xiě)入以下字節(jié),從0x00地址開(kāi)始,向EEPROM寫(xiě)入:0x12、0x34、0x56、0x78和0x90。
i2c_init_write(); // Sets the MAX2990 I2C Engine into write mode i2c_write(0x50); // 24C04 write (adr = 0b1010 000 0) = 0xA0 // The MAX2990 I2C engine shifts the I2C address by // 1 bit, because it will generate the R/W bit // automatically i2c_write(0x00); // word address location i2c_write(0x12); // data1 i2c_write(0x34); // data2 i2c_write(0x56); // data3 i2c_write(0x78); // data4 i2c_write(0x90); // data5 I2C_STOP; // Sends I2C stop-condition
讀模式
讀取我們寫(xiě)入EEPROM的數(shù)據(jù)時(shí),為24C04留出足夠的寫(xiě)時(shí)間非常關(guān)鍵。通常在“停止條件”后留出幾個(gè)毫秒的時(shí)間,請(qǐng)參考數(shù)據(jù)資料,確認(rèn)您的時(shí)間設(shè)置符合IC的要求。
i2c_init_write(); // Sets the MAX2990 I2C engine into write mode i2c_write(0x50); // 24C04 write (adr = 0b1010 000 0) = 0xA0 // The MAX2990 I2C engine shifts the I2C address by // 1 bit, because it will generate the R/W bit // automatically i2c_write(0x00); // word address location i2c_init_read(); // Sets the MAX2990 I2C engine into read mode i2c_write(0x50); // 24C04 read (adr = 0b1010 000 1) = 0xA1 // The MAX2990 I2C engine shifts the I2C address by // 1 bit, because it will generate the R/W bit // automatically unsigned char data[5]; // Array to store the received data i2c_read(data[0]); // Reads 1 byte from I2C and writes it to the array i2c_read(data[1]); // Reads 1 byte from I2C and writes it to the array i2c_read(data[2]); // Reads 1 byte from I2C and writes it to the array i2c_read(data[3]); // Reads 1 byte from I2C and writes it to the array i2c_read(data[4]); // Reads 1 byte from I2C and writes it to the array I2C_STOP; // Sends I2C stop-condition
現(xiàn)在,我們可以驗(yàn)證一下用于EEPROM讀、寫(xiě)操作的功能。
i2c_init_write(void) i2c_init_read(void) i2c_write(UINT8 data) i2c_read(UINT8 *data)
void i2c_init_write(void) { I2CCN_bit.I2CMODE = 0; // I2C transmit mode I2CCN_bit.I2CACK = 1; // Creates I2C NACK so that slave can create ACK I2C_START; // Generates I2C START condition while( I2CCN_bit.I2CSTART == 1 ); // Waits until the START condition // was put to the I2C bus I2CST_bit.I2CSRI = 0; // Resets the I2C interrupt flag } int i2c_init_read(void) { I2CCN_bit.I2CMODE = 1; // I2C read-mode I2CCN_bit.I2CACK = 0; // Creates I2C ACK after receive I2C_START; // Generates I2C START condition while( I2CCN_bit.I2CSTART == 1 ); // Waits until the START condition I2CST_bit.I2CSRI = 0; // Resets the I2C interrupt flag } void i2c_write(UINT8 data) { I2CBUF = data; // Puts the data on the I2C bus while( I2CST_bit.I2CTXI == 0 ); // Waits for transfer complete I2CST_bit.I2CTXI = 0; // Resets the I2C transmit complete // interrupt flag } void i2c_read(UINT8 *data) { I2CBUF = 0xff; // Puts "all ones" on the I2C bus so that slave can pull // the bus down to generate zeros while( !I2CST_bit.I2CRXI ); // Waits for receive complete I2CST_bit.I2CRXI=0; // Resets the I2C receive complete // interrupt flag *data = I2CBUF; // Writes the data to the pointer }