(5-1)、AT24C02掉電不丟失寫入與讀取
??????? AT24C02就是將數據寫入E2PROM,保證寫入數據掉電不丟失。考頻低,一般不考,頂天考幾個數據E2PROM,上電立馬讀取。AT24C02數據讀取一定放在主程序最前面,否則會出現一些問題。通信方式也是I2C,因此底層代碼跟AD、DA基本一樣。存在下面我們來講一下寫入與讀取的時序。
?
寫入時序:(如圖 二十二)
①初始化(通信起始信號)
②發送I2C設備地址(高七位是設備地址,最后一位是讀寫位,寫為0,讀取為1,A2、A1、A0置0,開始寫操作0xa0,如圖 二十一)
③從機發送反饋應答(從機發送0表明接收成功)
④寫入從機設備地址(一般為8的倍數,如0、8、16、24…)
⑤從機發送反饋應答
⑥逐個寫入數據、從機發送反饋應答、延時200再寫(while循環)
⑦停止信號
? ? ? ? ? ? ? ?圖 二十一 AT24C02設備地址
?
讀取時序:(如圖 二十三)
①初始化(通信起始信號)
②發送I2C設備地址(高七位是設備地址,最后一位是讀寫位,寫為0,讀取為1,A2、A1、A0置0,開始寫操作0xa0,如圖 二十一)
③從機發送反饋應答(從機發送0表明接收成功)
④寫入從機設備地址(一般為8的倍數,如0、8、16、24…)
⑤從機發送反饋應答
⑥重新初始化
⑦發送開始讀取信號0xa1
⑧從機發送反饋應答(從機發送0表明接收成功)
⑨開始讀取數據(無需延時)、讀取完成主機發送反饋1、還有數據發送0
⑩停止信號
? ? ? ? ? ? ? ? ? ?圖 二十二 AT24C02寫入
? ? ? ? ? ? ? ? ? 圖 二十三 AT24C02讀取
?
(5-2)AT24C02寫入與讀取代碼解讀
? ? 如圖 二十四,我們按照寫入的時序一步步分析,*String表示指針,傳入數組名,就可以需要寫入的 數據全部寫入,Number就是數組里面有幾個數據。
? ? 首先發送開始信號,再發送從機地址并反饋(0xA0)
? ? 再選擇需要寫入的寄存器地址(8的倍數),從該位置開始寫,寫入一次后地址會自增,數據自動放在下一位地址。
? ? 此時開始寫入數據,每次寫入后需要延時200,循環Number次后,數組數據全部寫完,停止。
?
? ? ? ? ? ? ? ? 圖 二十四 AT24C02寫入數據代碼
?
? ? 如圖 二十五,我們按照讀取的時序一步步分析,*String表示指針,傳入數組名,就可以將指定地址Address開始的數據全部讀取,Number就是讀取數據的個數。
? ?首先發送開始信號,再發送從機地址+讀寫位(讀為0、寫為1),并反饋(0xA0)
? ?再選擇需要讀取的寄存器地址(8的倍數),從該位置開始讀取,與寫入原理相同,讀取一次后地址會自增,第二次讀取時是第一次地址自加后的位置下的數據。
? ?重新初始化,發送寄存器地址+讀寫位置(讀為0、寫為1),反饋。
? ?此時開始讀取數據,循環Number次后,數組數據全部讀取完。此時注意只有當Number==0時也就是數據已經讀取完了,發送反饋1,不在讀取;Number!=0說明還有數據,發送反饋0,繼續讀取。最后停止時序。最后,請一定記得把讀取的代碼放在main函數最前面!
?
? ? ? ? ? ? ?圖 二十五 AT24C02讀取數據代碼
提供參考代碼,希望對讀者有幫助
#include <STC15F2K60S2.H>
#include <INTRINS.H>sbit sda = P2^1;
sbit scl = P2^0;
/* # I2C代碼片段說明1. 本文件夾中提供的驅動代碼供參賽選手完成程序設計參考。2. 參賽選手可以自行編寫相關代碼或以該代碼為基礎,根據所選單片機類型、運行速度和試題中對單片機時鐘頻率的要求,進行代碼調試和修改。
*/#define DELAY_TIME 5//
static void I2C_Delay(unsigned char n)
{do{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); }while(n--);
}//
void I2CStart(void)
{sda = 1;scl = 1;I2C_Delay(DELAY_TIME);sda = 0;I2C_Delay(DELAY_TIME);scl = 0;
}//
void I2CStop(void)
{sda = 0;scl = 1;I2C_Delay(DELAY_TIME);sda = 1;I2C_Delay(DELAY_TIME);
}//
void I2CSendByte(unsigned char byt)
{unsigned char i;for(i=0; i<8; i++){scl = 0;I2C_Delay(DELAY_TIME);if(byt & 0x80){sda = 1;}else{sda = 0;}I2C_Delay(DELAY_TIME);scl = 1;byt <<= 1;I2C_Delay(DELAY_TIME);}scl = 0;
}//
unsigned char I2CReceiveByte(void)
{unsigned char da;unsigned char i;for(i=0;i<8;i++){ scl = 1;I2C_Delay(DELAY_TIME);da <<= 1;if(sda) da |= 0x01;scl = 0;I2C_Delay(DELAY_TIME);}return da;
}//
unsigned char I2CWaitAck(void)
{unsigned char ackbit;scl = 1;I2C_Delay(DELAY_TIME);ackbit = sda; scl = 0;I2C_Delay(DELAY_TIME);return ackbit;
}//
void I2CSendAck(unsigned char ackbit)
{scl = 0;sda = ackbit; I2C_Delay(DELAY_TIME);scl = 1;I2C_Delay(DELAY_TIME);scl = 0; sda = 1;I2C_Delay(DELAY_TIME);
}/*IIC通信過程1、AT24C02寫入起始信號-開始寫操作(0xa0)--反饋---寫入從機地址--反饋---寫入數據反饋--延時200--停止2、AT24C02讀取起始信號-開始寫操作(0xa0)--反饋--寫入從機地址--反饋--重新開始--開始讀操作(0xa1)--反饋--開始讀取并反饋(不再接收發送1)---停止/**
* @brief AT24C02_Write往AT24C02中寫入數據保證掉電不丟失* @param *String--傳入數組名* @param Address寄存器地址(8的倍數,如0、8、16、24...)* @param Number--需要發送的數據總共幾位
*/void AT24C02_Write(unsigned char *String,unsigned char Address,unsigned char Number)
{I2CStart();I2CSendByte(0xa0); //寫入從機地址I2CWaitAck();I2CSendByte(Address); //開始寫入的寄存器地址I2CWaitAck();while(Number--){I2CSendByte(*String++); //寫入數據I2CWaitAck();I2C_Delay(200); //延時}I2CStop();I2C_Delay(255); I2C_Delay(255);I2C_Delay(255);I2C_Delay(255);//保證時序
}//從地址Address開始讀取Number個數據,并放入*String數組中(指針)
void AT24C02_Read(unsigned char *String,unsigned char Address,unsigned char Number)
{I2CStart();I2CSendByte(0xa0); //寫入從機地址I2CWaitAck(); //反饋I2CSendByte(Address); //開始寫入的寄存器地址I2CWaitAck();I2CStart(); //重新開始I2CSendByte(0xa1); //開始讀操作I2CWaitAck();while(Number--) //讀取Number數據{*String++ = I2CReceiveByte();if(Number) //如何Number!=0表示還有數據需要讀取,發送反饋0,繼續讀取I2CSendAck(0);elseI2CSendAck(1); //如何Number==0表示讀取完畢,不再接收,發送反饋1}I2CStop();
}
?
?
?