作為基礎入門級的TX-1C開發板,里面有AT24C02芯片,在編寫程序時很多童鞋無法順利使用該芯片。
我作為初學者也是搗鼓了兩天,在詳細閱讀了datasheet之后,終于明白癥結所在,在這里和大家分享一下。
TX-1C的開發板,都已經焊接好電路,需要我們做的只是寫一下驅動程序。
該芯片可以采用IIC總線進行操作。時序圖請大家參照datasheet(附件),之前很多童鞋遇到時序圖寫對但是數據讀寫錯誤的問題。
我也遇到了,這里應該注意芯片每次字節寫操作(byte write opeartion)完成后,需要10ms的延時,用于芯片內部把數據轉化為不可擦除的。這段期間芯片對讀寫信號是不響應的。如果這段時間進行讀數據操作,就會出現錯誤。
另外,對于AT24C02芯片,2Kbit的EEPROM,也就是256Byte的大小,數據地址從0x00-0xff。需要注意的是,這個芯片是每8byte是一頁,一共32頁,這個在字節寫操作(byte write opeartion)里面沒影響,但是如果你想連續進字節,就需要注意了(AT24C04及以上型號都是16byte一頁)。在頁寫操作里面(page write opeartion),一次連續寫只能寫一頁(8byte),只是因為芯片內部每寫完一個字節,數據地址就自加1,但是寫到這一頁的結尾,指針就會調到這一頁的開頭,而不是跳到下一頁的開頭,如果繼續寫,就會覆蓋前面的數據。寫完這一頁就要stop,在延時10ms,轉化為不可擦除數據。之后,重新開始start,寫下一頁。這是非常需要注意的。
讀操作沒有這個問題,字節讀取不需要延時10ms(讀不需要不可擦除的轉化),如果連續讀也不存在頁的問題,因為讀完一個字節,地址指針會跳到下一個字節,從0x00一直到0xff(我想是因為在寫操作的時候芯片需要轉化為不可擦除的過程限制,芯片可能沒有辦法把0x00-0xff這么多字節一次性都轉化為不可擦除的,所以才需要分頁寫)。
好了,要點已經講完(以上都是在datasheet,write/read operation上看到的,如果沒看明白可以參考原文),上代碼了。
代碼有點長,但是非常robust!!里面把ByteWrite,PageWrite,RandRead,SeqRead的代碼都寫進去,而且返回值是表示操作狀態
0表示操作錯誤,1表示操作正確,Read出來的數據都存在了外部變量AT24C02_data[]數組里面,我定義的最大容量是30,大家可以根據需要自己更改。
經過封裝以后可以直接作為AT24C02的驅動函數。
main函數是我寫的測試函數,如果讀寫過程有錯誤會有很長的蜂鳴器,如果正確,每個周期后會有短促的蜂鳴。希望對大家有啊幫助。
單片機源碼:
- #include <reg52.h>
- #include <intrins.h>
- #define MAXIUM 30
- #define uint unsigned int
- #define uchar unsigned char
-
- sbit SDA=P2^0;
- sbit SCL=P2^1;
- sbit beep=P2^3;
- uchar AT24C02_data[MAXIUM];
- void delay(uint ms){
- uint j,k;
- for(j=ms;j>0;j--)
- for(k=110;k>0;k--);
- }
- void nop(){
- _nop_();
- _nop_();
- }
- void AT24C02_Start(){
- SDA=1;
- nop();
- SCL=1;
- nop();
- SDA=0;
- nop();
- SCL=0;
- nop();
- }
- void AT24C02_Stop(){
- SDA=0;
- nop();
- SCL=1;
- nop();
- SDA=1;
- nop();
- SCL=0;
- nop();
- }
- void AT24C02_SendAck(){
- SDA=0;
- nop();
- SCL=1;
- nop();
- SCL=0;
- nop();
- SDA=1;
- nop();
- }
- uchar AT24C02_RecAck(){
- uchar i,flag;
- flag=0;
- i=0;
- SCL=1;
- nop();
- while((SDA==1)&&(i<255)) i++;
- if(i==255) flag=1;
- SCL=0;
- nop();
- return flag;
- }
- void AT24C02_Write(uchar dat){
- uchar i,temp;
- temp=dat;
- for(i=0;i<8;i++){
- temp=temp<<1;
- SDA=CY;
- nop();
- SCL=1;
- nop();
- SCL=0;
- nop();
- }
- SDA=1; nop();
- }
- uchar AT24C02_Read(){
- uchar i,temp;
- for(i=0;i<8;i++){
- SCL=1;
- nop();
- temp=(temp<<1)|SDA;
- SCL=0;
- nop();
- }
- return temp;
- }
- //Return data is the state(0 means fault, 1 means success);
- uchar AT24C02_ByteWrite(uchar add, uchar dat){
- uchar flag;
- flag=0;
- AT24C02_Start();
- AT24C02_Write(0xa0);
- if(!AT24C02_RecAck()){
- AT24C02_Write(add);
- if(!AT24C02_RecAck()){
- AT24C02_Write(dat);
- if(!AT24C02_RecAck()) flag=1;
- }
- }
- AT24C02_Stop();
- delay(10);
- return flag;
- }
- //data word add(0x00-0xff) must be divided by 8(32 in total);
- //*p points to 8 uchar array;
- //Return data is the state(0 means fault, 1 means success);
- uchar AT24C02_PageWrite(uchar add, uchar *dat){
- uchar flag;
- uchar i, *p;
- flag=0;
- p=dat;
- AT24C02_Start();
- AT24C02_Write(0xa0);
- if(!AT24C02_RecAck()){
- AT24C02_Write(add);
- if(!AT24C02_RecAck()){
- for(i=0;i<8;i++){
- AT24C02_Write(*(p+i));
- if(AT24C02_RecAck()) break;
- }
- if(i==8) flag=1;
- }
- }
- AT24C02_Stop();
- delay(10);
- return flag;
- }
- //Data is saved in external variable AT24C02_data[0];
- //Return data is the state(0 means fault, 1 means success);
- uchar AT24C02_RandRead(uchar add){
- uchar flag;
- flag=0;
- AT24C02_Start();
- AT24C02_Write(0xa0);
- if(!AT24C02_RecAck()){
- AT24C02_Write(add);
- if(!AT24C02_RecAck()){
- AT24C02_Start();
- AT24C02_Write(0xa1);
- if(!AT24C02_RecAck()){
- AT24C02_data[0]=AT24C02_Read();
- AT24C02_Stop();
- flag=1;
- }
- }
- }
- return flag;
- }
- //Data is saved in external variable AT24C02_data[0],maxium num is 30;
- //Return data is the state(0 means fault, 1 means success;
- uchar AT24C02_SeqRead(uchar add,uchar num){
- uchar i,flag;
- flag=0;
- AT24C02_Start();
- AT24C02_Write(0xa0);
- if(!AT24C02_RecAck()){
- AT24C02_Write(add);
- if(!AT24C02_RecAck()){
- AT24C02_Start();
- AT24C02_Write(0xa1);
- if(!AT24C02_RecAck()){
- for(i=0;i<num-1;i++){
- AT24C02_data[ i]=AT24C02_Read();
- AT24C02_SendAck();
- }
- AT24C02_data[ i]=AT24C02_Read();
- AT24C02_Stop();
- flag=1;
- }
- }
- }
- return flag;
- }
- void main(){
- uchar i;
- uchar array[8]={1,2,3,4,5,6,7,8};
-
- for(i=0;i<MAXIUM;i++) AT24C02_data[ i]=0;
- P1=0x00;
- delay(1000);
-
- if(AT24C02_ByteWrite(0x00,0xff)){
- if(!AT24C02_RandRead(0x00)){
- beep=0;
- delay(2000);
- beep=1;
- }
- }
- else{
- beep=0;
- delay(1000);
- beep=1;
- }
- P1=AT24C02_data[0];
- delay(1000);
-
- if(AT24C02_PageWrite(0x00,array)){
- if(!AT24C02_SeqRead(0x00,8)){
- beep=0;
- delay(2000);
- beep=1;
- }
- }
- else{
- beep=0;
- delay(1000);
- beep=1;
- }
- while(1){
- for(i=0;i<8;i++){
- P1=AT24C02_data[ i];
- delay(1000);
- }
- beep=0;
- delay(100);
- beep=1;
- }
- }
復制代碼
|