作為基礎(chǔ)入門(mén)級(jí)的TX-1C開(kāi)發(fā)板,里面有AT24C02芯片,在編寫(xiě)程序時(shí)很多童鞋無(wú)法順利使用該芯片。
我作為初學(xué)者也是搗鼓了兩天,在詳細(xì)閱讀了datasheet之后,終于明白癥結(jié)所在,在這里和大家分享一下。
TX-1C的開(kāi)發(fā)板,都已經(jīng)焊接好電路,需要我們做的只是寫(xiě)一下驅(qū)動(dòng)程序。
該芯片可以采用IIC總線進(jìn)行操作。時(shí)序圖請(qǐng)大家參照datasheet(附件),之前很多童鞋遇到時(shí)序圖寫(xiě)對(duì)但是數(shù)據(jù)讀寫(xiě)錯(cuò)誤的問(wèn)題。
我也遇到了,這里應(yīng)該注意芯片每次字節(jié)寫(xiě)操作(byte write opeartion)完成后,需要10ms的延時(shí),用于芯片內(nèi)部把數(shù)據(jù)轉(zhuǎn)化為不可擦除的。這段期間芯片對(duì)讀寫(xiě)信號(hào)是不響應(yīng)的。如果這段時(shí)間進(jìn)行讀數(shù)據(jù)操作,就會(huì)出現(xiàn)錯(cuò)誤。
另外,對(duì)于AT24C02芯片,2Kbit的EEPROM,也就是256Byte的大小,數(shù)據(jù)地址從0x00-0xff。需要注意的是,這個(gè)芯片是每8byte是一頁(yè),一共32頁(yè),這個(gè)在字節(jié)寫(xiě)操作(byte write opeartion)里面沒(méi)影響,但是如果你想連續(xù)進(jìn)字節(jié),就需要注意了(AT24C04及以上型號(hào)都是16byte一頁(yè))。在頁(yè)寫(xiě)操作里面(page write opeartion),一次連續(xù)寫(xiě)只能寫(xiě)一頁(yè)(8byte),只是因?yàn)樾酒瑑?nèi)部每寫(xiě)完一個(gè)字節(jié),數(shù)據(jù)地址就自加1,但是寫(xiě)到這一頁(yè)的結(jié)尾,指針就會(huì)調(diào)到這一頁(yè)的開(kāi)頭,而不是跳到下一頁(yè)的開(kāi)頭,如果繼續(xù)寫(xiě),就會(huì)覆蓋前面的數(shù)據(jù)。寫(xiě)完這一頁(yè)就要stop,在延時(shí)10ms,轉(zhuǎn)化為不可擦除數(shù)據(jù)。之后,重新開(kāi)始start,寫(xiě)下一頁(yè)。這是非常需要注意的。
讀操作沒(méi)有這個(gè)問(wèn)題,字節(jié)讀取不需要延時(shí)10ms(讀不需要不可擦除的轉(zhuǎn)化),如果連續(xù)讀也不存在頁(yè)的問(wèn)題,因?yàn)樽x完一個(gè)字節(jié),地址指針會(huì)跳到下一個(gè)字節(jié),從0x00一直到0xff(我想是因?yàn)樵趯?xiě)操作的時(shí)候芯片需要轉(zhuǎn)化為不可擦除的過(guò)程限制,芯片可能沒(méi)有辦法把0x00-0xff這么多字節(jié)一次性都轉(zhuǎn)化為不可擦除的,所以才需要分頁(yè)寫(xiě))。
好了,要點(diǎn)已經(jīng)講完(以上都是在datasheet,write/read operation上看到的,如果沒(méi)看明白可以參考原文),上代碼了。
代碼有點(diǎn)長(zhǎng),但是非常robust!!里面把ByteWrite,PageWrite,RandRead,SeqRead的代碼都寫(xiě)進(jìn)去,而且返回值是表示操作狀態(tài)
0表示操作錯(cuò)誤,1表示操作正確,Read出來(lái)的數(shù)據(jù)都存在了外部變量AT24C02_data[]數(shù)組里面,我定義的最大容量是30,大家可以根據(jù)需要自己更改。
經(jīng)過(guò)封裝以后可以直接作為AT24C02的驅(qū)動(dòng)函數(shù)。
main函數(shù)是我寫(xiě)的測(cè)試函數(shù),如果讀寫(xiě)過(guò)程有錯(cuò)誤會(huì)有很長(zhǎng)的蜂鳴器,如果正確,每個(gè)周期后會(huì)有短促的蜂鳴。希望對(duì)大家有啊幫助。
單片機(jī)源碼:
- #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;
- }
- }
復(fù)制代碼
資料下載:
00_AT24C02A.pdf
(184.52 KB, 下載次數(shù): 11)
2018-5-6 12:45 上傳
點(diǎn)擊文件名下載附件
|