|
本帖最后由 Vence 于 2019-9-26 12:51 編輯
以下這篇文章是自己折騰了三天存儲芯片后,并且能夠成功進(jìn)行字節(jié)操作、頁操作的一篇應(yīng)用型文章,不太想研究原理的可以直接采用本文的代碼和注意事項(xiàng)。
在對24C02或者24C16進(jìn)行字節(jié)、頁讀取、頁存取前,我們需要弄清楚I2C協(xié)議、24C02/24C16存儲空間、字節(jié)操作和頁操作的時(shí)序
————————————————
版權(quán)聲明:本文為CSDN博主「Pvence」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_40814407/article/details/101228190
I2C協(xié)議:I2C是什么協(xié)議網(wǎng)上進(jìn)行百度方可知道,以下只寫使用代碼
- void i2cStart(void) //開始時(shí)序
- {
- SDA=1;
- SCL=1;
- _delay(2); //延時(shí)2μs
- SDA=0;
- _delay(2);
- SCL=0;
- }
-
- void i2cStop(void) //結(jié)束時(shí)序
- {
- SDA=0;
- _delay(2);
- SCL=1;
- _delay(2);
- SDA=1;
- }
-
- void i2cAck_MCU(void) //應(yīng)答時(shí)序
- {
- SDA=0;
- _delay(2);
- SCL=1;
- _delay(2);
- SCL=0;
- _delay(2);
- SDA=1;
- _delay(4);
- }
-
-
- void i2cNoAck_MCU(void) //非應(yīng)答時(shí)序
- {
- SDA=1;
- _delay(2);
- SCL=1;
- _delay(2);
- SCL=0;
- _delay(2);
復(fù)制代碼 24C02/24C16存儲空間大小24C02就是有2Kbit = 2000/8 = 250個(gè)字節(jié),24C16就是有16kbit = 2000個(gè)字節(jié),24C02一頁最多可以寫入8個(gè)字節(jié),因此可以分成32頁,24C16一頁最多可以寫入16個(gè)字節(jié),因此可以分成128頁。
字節(jié)寫操作
- void WriteByte_24LC16B(unsigned char input)
- {
- unsigned char bit_count;
- for(bit_count=8;bit_count!=0;bit_count--)
- {
- _delay(2);
- SDA=(_Bool)(input&0x80);
- _delay(2);
- SCL=1;
- _delay(2);
- SCL=0;
- input=input<<1;
- _delay(2);
- }
- SDA=1;
- SDA_CTRL=1; //這里需要看自己使用的芯片設(shè)置SDA的IO口為輸入狀態(tài),我用的是HT45F67芯片,SDA端口設(shè)置為輸入狀態(tài),用于判斷SDA是否接到主機(jī)的應(yīng)答信號
- _delay(2);
- SCL=1;
- _delay(2);
- if(SDA == 1)
- ack = 0;
- else
- ack = 1;
- SCL=0;
- SDA_CTRL=0; //此處根據(jù)自己所使用的芯片將SDA所在的Io口設(shè)置為輸出狀態(tài)
- }
-
- void Write_24LC16B(unsigned char Wdata,unsigned int RomAddress)
- {
- unsigned char block;
- WriteDeviceAddress=0B10100000;
- block=RomAddress/256;
- RomAddress=RomAddress%256;
- WriteDeviceAddress=WriteDeviceAddress|(block<<1);
- i2cStart();
- WriteByte_24LC16B(WriteDeviceAddress);
- WriteByte_24LC16B((unsigned char)RomAddress);
- WriteByte_24LC16B(Wdata);
- i2cStop();
- _delay(5500);
- }
復(fù)制代碼
字節(jié)讀操作
- unsigned char ReadByte_24LC16B()
- {
- unsigned char bit_count,rbyte=0;
- SDA=1;
- SDA_CTRL=1;
- _delay(10);
- for(bit_count=8;bit_count!=0;bit_count--)
- {
- rbyte=rbyte<<1;
- _delay(2);
- SCL=1;
- rbyte=rbyte|((unsigned char)(SDA));
- _delay(2);
- SCL=0;
- _delay(2);
- }
- SDA_CTRL=0;
- return(rbyte);
- }
-
-
- unsigned char Read_24LC16B(unsigned int RomAddress)
- {
- unsigned char output,block;
- ReadDeviceAddress=0B10100001;
- WriteDeviceAddress=0B10100000;
- block=RomAddress/256;
- RomAddress=RomAddress%256;
- WriteDeviceAddress=WriteDeviceAddress|(block<<1);
- ReadDeviceAddress=ReadDeviceAddress|(block<<1);
- i2cStart();
- WriteByte_24LC16B(WriteDeviceAddress);
- WriteByte_24LC16B((unsigned char)RomAddress);
- i2cStart();
- WriteByte_24LC16B(ReadDeviceAddress);
- output=ReadByte_24LC16B();
- i2cNoAck_MCU();
- i2cStop();
- _delay(2000);
- return(output);
- }
復(fù)制代碼
頁寫操作
- Wdata為輸入數(shù)組的首地址,RomAddress為需要進(jìn)行存儲的地址,范圍在0~2047之間,cnt為一次需要寫入的字節(jié)個(gè)數(shù),建議采用8的倍數(shù)的cnt,因?yàn)楸竞瘮?shù)不采用自動(dòng)分頁,不是8的倍數(shù)會(huì)在超出頁寫入最多的字節(jié)數(shù)之后覆蓋掉原來的數(shù)。
- void WritePage_24LC16B(unsigned char *Wdata,unsigned int RomAddress,unsigned char cnt)
- {
- unsigned char block;
- WriteDeviceAddress=0B10100000;
- block=RomAddress/256;
- RomAddress=RomAddress%256;
- WriteDeviceAddress=WriteDeviceAddress|(block<<1);
- i2cStart();
- WriteByte_24LC16B(WriteDeviceAddress);
- WriteByte_24LC16B((unsigned char)RomAddress);
- while(cnt--)
- {
- WriteByte_24LC16B(*Wdata++);
- }
- i2cStop();
- }
-
- 注意:連續(xù)進(jìn)行多頁寫操作,需要在WritePage_24LC16B函數(shù)后添加150μs以上的延遲,這段時(shí)間,24C02內(nèi)部需要將數(shù)據(jù)存儲到芯片內(nèi)部。
- 例子:
- D_buffer[8] = {1,2,3,4,5,6,7,8};
- WritePage_24LC16B(D_buffer,0,8);
- _delay(150); //延遲150μs以及以上
- WritePage_24LC16B(D_buffer,8,8);
復(fù)制代碼
頁讀操作
- void ReadPage_24LC16B(unsigned char *Rdata,unsigned int RomAddress,unsigned char cnt)
- {
- unsigned char block;
- ReadDeviceAddress=0B10100001;
- WriteDeviceAddress=0B10100000;
- block=RomAddress/256;
- RomAddress=RomAddress%256;
- WriteDeviceAddress=WriteDeviceAddress|(block<<1);
- ReadDeviceAddress=ReadDeviceAddress|(block<<1);
- i2cStart();
- WriteByte_24LC16B(WriteDeviceAddress);
- WriteByte_24LC16B((unsigned char)RomAddress);
- i2cStart();
- WriteByte_24LC16B(ReadDeviceAddress);
- while(cnt>1)
- {
- *Rdata++ = ReadByte_24LC16B();
- cnt--;
- i2cAck_MCU(); //發(fā)送完讀地址后,需要應(yīng)答一下
- }
- *Rdata = ReadByte_24LC16B();
- i2cNoAck_MCU(); //讀取最后一個(gè)字節(jié)需要非應(yīng)答
- i2cStop();
- _delay(2000);
- }
復(fù)制代碼
|
|