|
AT24C02A, 2K SERIAL EEPROM:
Internally organized with 32 pages of 8 bytes each,
the 2K requires an 8-bit data word address for random word addressing.
24c02有32個(gè)頁(yè),每頁(yè)8字節(jié),本帖中不討論頁(yè)寫的方式
-------------------------------------------------------------------
22c6238a-d326-3475-96bc-e92ff575fc24.jpg (28.27 KB, 下載次數(shù): 106)
下載附件
2017-1-14 23:50 上傳
78707031-adbb-3bc9-8cf9-0084233de56b.jpg (75.73 KB, 下載次數(shù): 99)
下載附件
2017-1-14 23:50 上傳
AT24C02內(nèi)部設(shè)有一個(gè)8位控制寄存器,其每一位的含義如下:
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
1 0 1 0 A2 A1 A0 R/W
其中前4位數(shù)據(jù)是芯片固定的標(biāo)識(shí),
A2/A1/A0用于選擇總線上待訪問(wèn)的I2C器件,R/W=1讀操作,R/W=0寫操作;
I2C總線上最多可以擴(kuò)展8片同樣的2K容量EEPROM存儲(chǔ)器,
或者是4片4Kb的EEPROM,
或者是2片容量為8Kb的EEPROM存儲(chǔ)器。
或者是1片容量為16Kb的EEPROM存儲(chǔ)器(此時(shí)硬件就固定了,因?yàn)锳2/A1/A0已經(jīng)被P2P1P0占用),
如果擴(kuò)展8片2K以內(nèi)容量的EEPROM存儲(chǔ)器,每片存儲(chǔ)器將對(duì)應(yīng)一個(gè)地址,
我們的實(shí)驗(yàn)板上的AT24C02的A2/A1/A0引腳全部接地,
所以在實(shí)驗(yàn)中讀寫控制字分別為:0xa1/0xa0
主芯片stc89c52rc,晶振11.0592M
- #include<reg52.h>
- #include"MY51.H"
- sbit sda=P2^0; //總線連接口定義
- sbit scl=P2^1; //總線連接口定義
- void delayus() //需要4個(gè)機(jī)器周期,大概4.34us
- {
- ; //晶振頻率11.0592M,機(jī)器周期為1.085微秒
- }
- void iic_start() //啟動(dòng)信號(hào)
- {
- sda=1;
- scl=1;
- delayus(); //sda和scl同為高電平保持4.7us以上
- _nop_(); //1.085us,共5.78us,下面sda=0是下降沿,不能計(jì)算在延時(shí)時(shí)間中
- sda=0; //下降沿
- delayus(); //sda低電平保持4us以上 ,這里是4.34us滿足要求
- }
- void iic_stop() //停止信號(hào)
- {
- sda=0;_nop_(); //準(zhǔn)備狀態(tài)
- scl=1;
- delayus(); //該狀態(tài)穩(wěn)定時(shí)間要求保持4us以上
- sda=1; //scl高電平期間,sda來(lái)一個(gè)上升沿
- delayus(); //sda保持4.7us以上,4.34加上函數(shù)返回時(shí)間大于4.7us
- //注:此時(shí)scl和sda都為1
- }
- void iic_sendByte(uchar byteData) //mcu發(fā)送一個(gè)字節(jié)
- {
- uchar i;
- uchar temp=byteData;
- for(i=0;i<8;i++)
- {
- temp=temp<<1; //移動(dòng)后最高位到了PSW寄存器的CY位中
- scl=0; //準(zhǔn)備
- _nop_(); //穩(wěn)定一下
- sda=CY; //將待發(fā)送的數(shù)據(jù)一位位的放到sda上
- _nop_();
- scl=1; //每一個(gè)高電平期間,ic器件都會(huì)將數(shù)據(jù)取走
- _nop_();
- }
- scl=0; //如果寫成scl=1;sda=1就是停止信號(hào),不能這么寫
- _nop_();
- sda=1; //釋放總線,數(shù)據(jù)總線不用時(shí)要釋放
- _nop_();
- }
- uchar iic_readByte() //讀一個(gè)字節(jié)
- {
- uchar i,temp;
- scl=0; //準(zhǔn)備讀數(shù)據(jù)
- _nop_();
- sda=1; //釋放總線
- _nop_();
- for(i=0;i<8;i++)
- {
- scl=1; //mcu開始取數(shù)據(jù)
- delayus(); //scl為高電平后,ic器件就會(huì)將1位數(shù)據(jù)送到sda上
- //總共用時(shí)不會(huì)大于4.34us的,然后就可以讓mcu讀sda了
- temp=(temp<<1)|sda; //讀一位保存到temp中
- scl=0;
- delayus();
- }
- return temp;
- }
- bool iic_checkACK() //處理應(yīng)答信號(hào)
- {
- uchar errCounts=255; //定義超時(shí)量為255次
- scl=1;
- _nop_();
-
- while(sda)
- { //在一段時(shí)間內(nèi)檢測(cè)到sda=0的話認(rèn)為是應(yīng)答信號(hào)
- if(0==errCounts)
- {
- scl=0; //鉗住總線
- _nop_();
- return false; //沒(méi)有應(yīng)答信號(hào)
- }
- errCounts--;
- }
- scl=0; //鉗住總線,為下1次通信做準(zhǔn)備
- _nop_();
- return true; //成功處理應(yīng)答信號(hào)
- }
- void iic_init() //總線初始化
- {
- scl=1;
- sda=1;
- delayus();
- }
- void iic_sendACK(bool b_ACK) //發(fā)送應(yīng)答或非應(yīng)答信號(hào)
- {
- scl=0; //準(zhǔn)備
- _nop_();
- if(b_ACK) //ACK
- {
- sda=0;
- }
- else //unACK
- {
- sda=1;
- }
- _nop_();
- scl=1;
- delayus(); //大于4us的延時(shí)
- scl=0; //鉗住scl,以便繼續(xù)接收數(shù)據(jù)
- _nop_();
- }
- void AT24C02_writeByte(uchar address,uchar dataByte)//向24c02寫一字節(jié)數(shù)據(jù)
- {
- iic_start();
- iic_sendByte(0xa0);//mcu寫控制字,前4位固定1010,后三位地址0,末位0是寫
- iic_checkACK(); //mcu處理應(yīng)答信號(hào)
- iic_sendByte(address); //準(zhǔn)備在指定地址處寫入
- iic_checkACK();
- iic_sendByte(dataByte); //寫數(shù)據(jù)
- iic_checkACK();
- iic_stop();
- delayms(2);
- //按字節(jié)寫入時(shí),24c02在接收到停止信號(hào)后將數(shù)據(jù)擦寫到內(nèi)部,這需要時(shí)間
- //并且在這段時(shí)間內(nèi)不會(huì)響應(yīng)總線上的任何請(qǐng)求,故讓mcu有2毫秒以上的等待
- }
- void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//寫入任意長(zhǎng)度數(shù)據(jù)
- {
- while(numBytes--)
- {
- AT24C02_writeByte(address++,*buf++);
- }
- }
- void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//讀取任意長(zhǎng)度字節(jié)
- {
- iic_start(); //起始信號(hào)
- iic_sendByte(0xa0); //控制字,寫
- iic_checkACK(); //處理應(yīng)答信號(hào)
- iic_sendByte(beginAddr); //發(fā)送地址
- iic_checkACK(); //處理應(yīng)答信號(hào)
- iic_start(); //發(fā)送起始信號(hào)
- iic_sendByte(0xa1); //控制字,讀
- iic_checkACK(); //處理應(yīng)答信號(hào)
- while(dataSize--) //讀取dataSize個(gè)字節(jié)
- {
- *buf++=iic_readByte(); //讀取一個(gè)個(gè)字節(jié)并保存到緩沖區(qū)buf中
- iic_sendACK(dataSize); //發(fā)送應(yīng)答,當(dāng)dataSize為0時(shí)發(fā)送非應(yīng)答
- }
- iic_stop(); //發(fā)送停止信號(hào)
- }
- void main()
- {
- uchar buf[2]; //接受數(shù)據(jù)的緩沖區(qū)
- uchar arr[34]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, //0x00-0x0f
- 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,//0x10-0x1f
- 32,0x55}; //0x20-0x21
- iic_init(); //總線初始化
- //AT24C02_writeByte(0x08,0x11); //向指定地址處寫入一個(gè)字節(jié)數(shù)據(jù),代碼測(cè)試
- AT24C02_writeData(0x00,sizeof(arr),arr); //向指定地址處開始寫入34字節(jié)的數(shù)據(jù)
- AT24C02_readData(0x20,sizeof(buf),buf); //從指定地址開始讀2個(gè)字節(jié)
- P1=buf[1]; //buf中的第二個(gè)元素就是arr中的最后一個(gè)數(shù)據(jù)0x55
-
- while(1){P1=~P1;delayms(500);} //將這個(gè)0x55用led燈顯示出來(lái)10101010變化
- }
復(fù)制代碼
- my51.h頭文件中主要用到
- #include<intrins.h>
- typedef unsigned char uchar ;
- void delayms(uint16 ms) //軟延時(shí)函數(shù)
- {
- uint16 i,j;
- for(i=ms;i>0;i--)
- {
- for(j=113;j>0;j--)
- {}
- }
- }
復(fù)制代碼
|
評(píng)分
-
查看全部評(píng)分
|