AT24C1024是基于IIC的EEPROM,容量為1024/8=128k bytes。它的引腳如下:
其中A1,A2為硬件地址引腳
WP為寫保護引腳,一般我們需要讀寫,需要接低電平GND,接高的話則僅允許讀
SDA和SCL則為IIC通信引腳
芯片通信采用IIC,有關IIC的通信原理可參考:
https://blog.csdn.net/u011436603/article/details/136007075文章瀏覽閱讀293次,點贊5次,收藏8次。這樣看起來,區分起止信號與數據電平是不是就更加容易些了,但是嘛由于只有一根數據線了,缺點就是無法同時收發了,因此它是半雙工通信的。一般的IIC器件,比如EEPROM,此時會發送要寫入或讀取的地址,如往0x0000地址寫入數字1,那么會先發送0x0000,等到回碼后再發送0x01,之后在收到應答后結束通信。前面在講UART時提到過通信傳輸所需要的幾個必要條件,首先得知道什么時候通信開始,什么時候通信結束,然后就是如何去解析數據了,根據這幾點,我們來談談IIC是如何實現通信的。從圖上可以看到,IIC規定的。https://blog.csdn.net/u011436603/article/details/136007075接下來說下具體的操作流程
讀數據:
- 啟動總線
- 發送設備地址+寫...等待應答
- 發送數據存儲地址...等待應答
- 發送數據
- 結束總線
寫數據:
- 啟動總線
- 發送設備地址+寫...等待應答
- 發送數據存儲地址...等待應答
- 發送設備地址+讀...等待應答
- 讀數據
- 結束總線
本次采用模擬IIC的方式,便于移植,具體的代碼如下
void eeprom_start(void)
{IIC_SDA_ON;IIC_SCL_OFF;DELAY_US (10);IIC_SCL_ON;DELAY_US(1);IIC_SDA_OFF;DELAY_US(1);IIC_SCL_OFF;DELAY_US(2);IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);
}void eeprom_stop(void)
{IIC_SDA_OFF;IIC_SCL_OFF;DELAY_US(1);IIC_SCL_ON;DELAY_US(1);IIC_SDA_ON;DELAY_US(2);IIC_SCL_OFF;DELAY_US(2);IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);
}void eeprom_ack(void)
{IIC_SDA_ON;IIC_SCL_OFF;DELAY_US (10);IIC_SDA_OFF;DELAY_US(1);IIC_SCL_ON;DELAY_US(1);IIC_SCL_OFF;DELAY_US(2);IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);
}void eeprom_noack(void)
{IIC_SDA_ON;IIC_SCL_OFF;DELAY_US (10);IIC_SCL_ON;DELAY_US(1);IIC_SCL_OFF;DELAY_US(2);IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);
}void eeprom_checkack(void)
{IIC_SCL_ON;DELAY_US(10);IIC_SCL_OFF;
}void eeprom_write_byte(unsigned char ucChar)
{unsigned char i;IIC_SDA_ON;IIC_SCL_OFF;DELAY_US (10);for(i=0; i<8; i++){if(!(ucChar & BIT(7-i)) == 0) IIC_SDA_ON;else IIC_SDA_OFF;DELAY_US (1);IIC_SCL_ON;DELAY_US(1);IIC_SCL_OFF;DELAY_US(2);}IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);
}unsigned char eeprom_read_byte(void)
{unsigned char i;unsigned char ucChar = 0;for(i=0; i<8; i++){if(IIC_SDA_VALUE == 1){ucChar |= BIT(7 - i);}else{ucChar &= ~BIT(7 - i);}IIC_SCL_ON;DELAY_US(1);IIC_SCL_OFF;DELAY_US(2);}IIC_SCL_OFF;IIC_SDA_ON;DELAY_US(10);return ucChar;
}
void eeprom_write_char(unsigned int nAddress,unsigned char ucChar)
{eeprom_start();if(nAddress>=0x10000) eeprom_write_byte(0xa2);else eeprom_write_byte(0xa0);eeprom_checkack();eeprom_write_byte(nAddress/256); eeprom_checkack();eeprom_write_byte(nAddress%256); eeprom_checkack();eeprom_write_byte(ucChar);eeprom_checkack();eeprom_stop(); if(nAddress%256 == 0) DELAY_MS(100);else DELAY_MS(8);
}unsigned char eeprom_read_char(unsigned int nAddress)
{unsigned char ucChar;eeprom_start(); if(nAddress>=0x10000) eeprom_write_byte(0xa2);else eeprom_write_byte(0xa0);eeprom_checkack();eeprom_write_byte(nAddress/256); eeprom_checkack();eeprom_write_byte(nAddress%256); eeprom_checkack();eeprom_start(); if(nAddress>=0x10000) eeprom_write_byte(0xa3);else eeprom_write_byte(0xa1);eeprom_checkack();ucChar = eeprom_read_byte();eeprom_noack();eeprom_stop();DELAY_US(10);return ucChar;
}
其中IIC_SCL_ON和IIC_SCL_OFF表示SCL引腳電平拉高或拉低,
IIC_SDA_ON和IIC_SDA_OFF表示SDA引腳電平拉高或拉低,IIC_SDA_VALUE表示讀取SDA引腳電平。需要注意的是,模擬IIC時引腳需要設置為開漏輸出且需要上拉電阻。
有兩個需要注意的點,一個是器件地址指令,當寫存儲地址處于前一半時,發送A0指令,當寫存儲地址處于后一半時,發送A2指令。另一個則是跨頁寫,每256字節為一頁,當出現跨頁寫時,需要增大延時,否則有可能出錯。