日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写

發(fā)布時(shí)間:2023/12/9 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 硬知識(shí)
    • AT24Cxx 介紹
      • 引腳排列
      • 引腳說(shuō)明
      • 存儲(chǔ)結(jié)構(gòu)
      • 器件尋址
      • 器件操作
        • 待機(jī)模式
        • 存儲(chǔ)復(fù)位
        • 寫(xiě)操作
          • 字節(jié)寫(xiě)
          • 頁(yè)寫(xiě)
          • 應(yīng)答查詢
        • 讀操作
          • 當(dāng)前地址讀
          • 隨機(jī)讀
          • 順序讀
  • 示例程序
    • 24C02.c
    • 24C02.h
    • 測(cè)試程序
      • main.c
      • 實(shí)驗(yàn)現(xiàn)象
      • 通訊波形
        • 寫(xiě)入部分
        • 讀取部分

普中51-單核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


硬知識(shí)

???????摘自《普中 51 單片機(jī)開(kāi)發(fā)攻略》、《24C02/24C04/24C08/24C16/24C32/24C64芯片手冊(cè)》

AT24Cxx 介紹

???????AT24C01/02/04/08/16…是一個(gè)1K/2K/4K/8K/16K 位串行 CMOS,內(nèi)部含有 128/256/512/1024/2048 個(gè) 8 位字節(jié),AT24C01 有一個(gè) 8 字節(jié)頁(yè)寫(xiě)緩沖器, AT24C02/04/08/16 有一個(gè) 16 字節(jié)頁(yè)寫(xiě)緩沖器。該器件通過(guò) I2C 總線接口進(jìn)行操作,它有一個(gè)專(zhuān)門(mén)的寫(xiě)保護(hù)功能。開(kāi)發(fā)板上使用的是 AT24C02(EEPROM)芯片,此芯片具有 I2C 通信接口,芯片內(nèi)保存的數(shù)據(jù)在掉電情況下都不丟失, 所以通常用于存放一些比較重要的數(shù)據(jù)等。

引腳排列

AT24Cxx 芯片管腳如下圖所示:

引腳說(shuō)明

存儲(chǔ)結(jié)構(gòu)

器件尋址

???????起始條件使能芯片讀寫(xiě)操作后,EEPROM都要求有8位的器件地址信息。
???????器件地址信息由"1"、“0"序列組成,前4位如圖中所示,對(duì)于所有串行EEPROM都是一樣的。對(duì)于24C02/32/64,隨后3位A2,A1和A0為器件地址位,必須與硬件輸入引腳保持一致。
???????對(duì)于24C04,隨后2位A2和A1為器件地址位,另1位為頁(yè)地址位。A2和A1必須與硬件輸入引腳保持一致,而A0是空腳。
???????對(duì)于24C08,隨后1位A2為器件地址位,另2位為頁(yè)地址位。A2必須與硬件輸入引腳保持一致,而A1和A0是空腳。
???????對(duì)于24C16,無(wú)器件地址位,3位都為頁(yè)地址位,而A2,A1和A0是空腳。
???????器件地址信息的LSB為讀/寫(xiě)操作選擇位,高為讀操作,低為寫(xiě)操作。
???????若比較器件地址一致,EEPROM將輸出應(yīng)答"0”,如果不一致,則返回到待機(jī)狀態(tài)。

器件操作

待機(jī)模式

EEPROM具有低功耗待機(jī)的特點(diǎn),條件為:

  • 電源上電;
  • 接收停止條件及完成任何內(nèi)部操作后。
  • 存儲(chǔ)復(fù)位

    當(dāng)協(xié)議中產(chǎn)生中斷、掉電或系統(tǒng)復(fù)位后,I2C總線可通過(guò)以下步驟復(fù)位:

  • 產(chǎn)生9個(gè)時(shí)鐘周期。
  • 當(dāng)SCL為高時(shí),SDA也為高。
  • 產(chǎn)生一個(gè)起始條件。
  • 寫(xiě)操作

    字節(jié)寫(xiě)

    ???????寫(xiě)操作要求在接收器件地址和ACK應(yīng)答后,接收8位的字地址。接收到這個(gè)地址后EEPROM應(yīng)答"0",然后是一個(gè)8位數(shù)據(jù)。在接收8位數(shù)據(jù)后,EEPROM應(yīng)答"0",接著必須由主器件發(fā)送停止條件來(lái)終止寫(xiě)序列。
    ???????此時(shí)EEPROM進(jìn)入內(nèi)部寫(xiě)周期tWRt_{WR}tWR?,數(shù)據(jù)寫(xiě)入非易失性存儲(chǔ)器中,在此期間所有輸入都無(wú)效。
    ???????直到寫(xiě)周期完成,EEPROM才會(huì)有應(yīng)答。

    頁(yè)寫(xiě)

    ???????24C02器件按8字節(jié)/頁(yè)執(zhí)行頁(yè)寫(xiě),24C04/08/16器件按16字節(jié)/頁(yè)執(zhí)行頁(yè)寫(xiě),24C32/64器件按32字節(jié)/頁(yè)執(zhí)行頁(yè)寫(xiě)。
    ???????頁(yè)寫(xiě)初始化與字節(jié)寫(xiě)相同,只是主器件不會(huì)在第一個(gè)數(shù)據(jù)后發(fā)送停止條件,而是在EEPROM的ACK以后,接著發(fā)送7個(gè)(24C02)或15個(gè)(24C04/08/16)或31個(gè)(24C32/64)數(shù)據(jù)。
    ???????EEPROM收到每個(gè)數(shù)據(jù)后都應(yīng)答"0",最后仍需由主器件發(fā)送停止條件,終止寫(xiě)序列接收到每個(gè)數(shù)據(jù)后,字地址的低3位(24C02)或4位(24C04/08/16)或5位(24C32/64)內(nèi)部自動(dòng)加1,高位地址位不變,維持在當(dāng)前頁(yè)內(nèi)。當(dāng)內(nèi)部產(chǎn)生的字地址達(dá)到該頁(yè)邊界地址時(shí),隨后的數(shù)據(jù)將寫(xiě)入該頁(yè)的頁(yè)首。如果超過(guò)8個(gè)(24C02)或16個(gè)(24C04/08/16)或32個(gè)24C32/64)數(shù)據(jù)傳送給了EEPROM,字地址將回轉(zhuǎn)到該頁(yè)的首字節(jié),先前的字節(jié)將會(huì)被覆蓋。

    應(yīng)答查詢

    ???????一旦內(nèi)部寫(xiě)周期啟動(dòng),EEPROM輸入無(wú)效,此時(shí)即可啟動(dòng)應(yīng)答查詢:發(fā)送起始條件和器件地址(讀/寫(xiě)位為期望的操作)。只有內(nèi)部寫(xiě)周期完成,EEPROM才應(yīng)答"0",之后可繼續(xù)讀/寫(xiě)操作。

    讀操作

    ???????讀操作與寫(xiě)操作初始化相同,只是器件地址中的讀/寫(xiě)選擇位應(yīng)為"1",有三種不同的讀操作方式:當(dāng)前地址讀,隨機(jī)讀和順序讀。

    當(dāng)前地址讀

    ???????內(nèi)部地址計(jì)數(shù)器保存著上次訪問(wèn)時(shí)最后一個(gè)地址加1的值。只要芯片有電,該地址就一直保存。當(dāng)讀到最后頁(yè)的最后字節(jié),地址會(huì)回轉(zhuǎn)到0;當(dāng)寫(xiě)到某頁(yè)尾的最后一個(gè)字節(jié),地址會(huì)回轉(zhuǎn)到該頁(yè)的首字節(jié)。
    ???????接收器件地址(讀/寫(xiě)選擇位為"1")、EEPROM應(yīng)答ACK后,當(dāng)前地址的數(shù)據(jù)就隨時(shí)鐘送出。
    ???????主器件無(wú)需應(yīng)答"0",但需發(fā)送停止條件。

    隨機(jī)讀

    ???????隨機(jī)讀需先寫(xiě)一個(gè)目標(biāo)字地址,一旦EEPROM接收器件地址和字地址并應(yīng)答了ACK,主器件就產(chǎn)生一個(gè)重復(fù)的起始條件。
    ???????然后,主器件發(fā)送器件地址(讀/寫(xiě)選擇位為"1"),EEPROM應(yīng)答ACK,并隨時(shí)鐘送出數(shù)據(jù)。主器件無(wú)需應(yīng)答"0",但需發(fā)送停止條件。

    順序讀

    ???????順序讀可以通過(guò)“當(dāng)前地址讀”或"隨機(jī)讀”啟動(dòng)。主器件接收到一個(gè)數(shù)據(jù)后,應(yīng)答ACK,只要EEPROM接收到ACK,將自動(dòng)增加字地址并繼續(xù)隨時(shí)鐘發(fā)送后面的數(shù)據(jù)。若達(dá)到存儲(chǔ)器地址末尾,地址自動(dòng)回轉(zhuǎn)到0,仍可繼續(xù)順序讀取數(shù)據(jù)。
    ???????主器件不應(yīng)答"0",而發(fā)送停止條件,即可結(jié)束順序讀操作。

    示例程序

    ???????stdint.h見(jiàn)【51單片機(jī)快速入門(mén)指南】1:基礎(chǔ)知識(shí)和工程創(chuàng)建
    ???????軟件I2C程序見(jiàn)【51單片機(jī)快速入門(mén)指南】4: 軟件 I2C

    ???????由原理圖,此24C02的地址為1010 000,即 0x50

    24C02.c

    #include "24C02.h"/******************************************************************************* * 函 數(shù) 名 : at24c02_delay_1ms 移植時(shí)需修改 * 函數(shù)功能 : 延時(shí)1ms * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_delay_1ms() //@11.0592MHz {unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i); }void at24c02_delay_ms(int i) {while(i--)at24c02_delay_1ms(); }/******************************************************************************* * 函 數(shù) 名 : at24c02_write_one_byte * 函數(shù)功能 : 在AT24CXX指定地址寫(xiě)入一個(gè)數(shù)據(jù) * 輸 入 : addr:寫(xiě)入數(shù)據(jù)的目的地址 dat:要寫(xiě)入的數(shù)據(jù) * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_write_one_byte(uint8_t addr,uint8_t dat) { i2c_mem_write(ADDR_24C02, addr, &dat, 1);at24c02_delay_ms(10); }/******************************************************************************* * 函 數(shù) 名 : at24c02_read_one_byte * 函數(shù)功能 : 在AT24CXX指定地址讀出一個(gè)數(shù)據(jù) * 輸 入 : addr:開(kāi)始讀數(shù)的地址 * 輸 出 : 讀到的數(shù)據(jù) *******************************************************************************/ uint8_t at24c02_read_one_byte(uint8_t addr) { uint8_t temp = 0; i2c_mem_read(ADDR_24C02, addr, &temp, 1);return temp; //返回讀取的數(shù)據(jù) }/******************************************************************************* * 函 數(shù) 名 : at24c02_read_one_page * 函數(shù)功能 : 在AT24CXX指定地址讀出一頁(yè)數(shù)據(jù) * 輸 入 : addr:寫(xiě)入數(shù)據(jù)的目的地址 pbuffer:要寫(xiě)入的緩沖區(qū)首地址Len:數(shù)據(jù)長(zhǎng)度 * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_read_one_page(uint8_t addr, uint8_t *pbuffer) { i2c_mem_read(ADDR_24C02, addr, pbuffer, 8); }/******************************************************************************* * 函 數(shù) 名 : at24c02_write_one_page * 函數(shù)功能 : 在AT24CXX指定頁(yè)寫(xiě)入一頁(yè)數(shù)據(jù) * 輸 入 : addr:寫(xiě)入數(shù)據(jù)的目的地址 dat:要寫(xiě)入的數(shù)據(jù) * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_write_one_page(uint8_t addr, uint8_t *dat) { i2c_mem_write(ADDR_24C02, addr, dat, 8);at24c02_delay_ms(10); }/******************************************************************************* * 函 數(shù) 名 : at24c02_read_bytes * 函數(shù)功能 : 在AT24CXX指定地址讀出一段數(shù)據(jù) * 輸 入 : addr:寫(xiě)入數(shù)據(jù)的目的地址 pbuffer:要寫(xiě)入的緩沖區(qū)首地址Len:數(shù)據(jù)長(zhǎng)度 * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_read_bytes(uint8_t addr, uint8_t* pbuffer, uint8_t Len) { uint8_t pdat_id_S = addr % 8;uint8_t i, pages;if(pdat_id_S){for(i = pdat_id_S; i < 8; ++i){*pbuffer++ = at24c02_read_one_byte(addr++);--Len;if(!Len)return;}}pages = Len / 8;for (i = 0; i < pages; ++i){at24c02_read_one_page(addr, pbuffer);addr += 8;pbuffer += 8;Len -= 8;}if(!Len)return;i2c_mem_read(ADDR_24C02, addr, pbuffer, Len);pbuffer += Len;*pbuffer = '\0'; }/******************************************************************************* * 函 數(shù) 名 : at24c02_write_bytes * 函數(shù)功能 : 在AT24CXX指定地址寫(xiě)入一段數(shù)據(jù) * 輸 入 : addr:寫(xiě)入數(shù)據(jù)的目的地址 pdat:要寫(xiě)入的數(shù)據(jù)首地址Len:數(shù)據(jù)長(zhǎng)度 * 輸 出 : 無(wú) *******************************************************************************/ void at24c02_write_bytes(uint8_t addr, uint8_t* pdat, uint8_t Len) { uint8_t Temp[8];uint8_t pdat_id_S = addr % 8;uint8_t i, pages;if(pdat_id_S){for(i = 0; i < pdat_id_S; ++i)Temp[i] = at24c02_read_one_byte(addr - pdat_id_S + i);for (; i < 8; ++i){Temp[i] = *pdat;++pdat;--Len;if(!Len){at24c02_write_one_page(addr - pdat_id_S, Temp);return;}}at24c02_write_one_page(addr - pdat_id_S, Temp);addr = addr + 8 - pdat_id_S;}pages = Len / 8;for (i = 0; i < pages; ++i){at24c02_write_one_page(addr, pdat);addr += 8;pdat += 8;Len -= 8;}if(!Len)return;for (i = 0; i < Len; ++i){Temp[i] = *pdat;++pdat;}for(; i < 8; ++i){Temp[i] = at24c02_read_one_byte(addr + i);}at24c02_write_one_page(addr, Temp); }

    24C02.h

    #ifndef _24C02_H_ #define _24C02_H_#include "stdint.h" #include "intrins.h" #include "Software_I2C.h"#define ADDR_24C02 0x50 //24C02的7位地址void at24c02_write_one_byte(uint8_t addr,uint8_t dat); uint8_t at24c02_read_one_byte(uint8_t addr); void at24c02_write_one_page(uint8_t addr,uint8_t *dat); void at24c02_read_one_page(uint8_t addr, uint8_t *pbuffer);void at24c02_write_bytes(uint8_t addr, uint8_t *pdat, uint8_t Len); void at24c02_read_bytes(uint8_t addr, uint8_t *pbuffer, uint8_t Len);#endif

    測(cè)試程序

    串口程序見(jiàn)【51單片機(jī)快速入門(mén)指南】3.3:USART 串口通信

    main.c

    ???????在地址0x06處連續(xù)寫(xiě)入
    ???????“123456789098765432123456789012345678909876543212345678901234567890987654321234567890”
    ???????讀取后通過(guò)串口返回,波特率為57600,晶振頻率為11.0592MHz。

    #include <STC89C5xRC.H> #include "intrins.h" #include "stdint.h" #include "USART.h" #include "24C02.h"void Delay1ms() //@11.0592MHz {unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i); }void Delay_ms(int i) {while(i--)Delay1ms(); }void main(void) {char Input[] = "123456789098765432123456789012345678909876543212345678901234567890987654321234567890";char Str[sizeof(Input)];USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 11059200, 57600, DOUBLE_BAUD_ENABLE, USART_TIMER_1);at24c02_write_bytes(6, Input, sizeof(Input)-1);while(1){Delay_ms(500);at24c02_read_bytes(6, Str, sizeof(Input)-1);printf("%s\r\n", Str);} }

    實(shí)驗(yàn)現(xiàn)象

    如圖,成功讀取

    通訊波形

    寫(xiě)入部分

    未對(duì)齊部分先讀取之前的字節(jié),在對(duì)齊順序?qū)懭?#xff0c;并自動(dòng)換頁(yè)



    末尾未對(duì)齊部分先讀取后面的字節(jié),再連同要寫(xiě)入的數(shù)據(jù)順序?qū)懭?br />

    讀取部分

    未8位對(duì)齊部分為隨機(jī)單字節(jié)讀取

    對(duì)齊后進(jìn)行順序讀取,并自動(dòng)換頁(yè)

    末尾未對(duì)齊部分也進(jìn)行順序讀取

    總結(jié)

    以上是生活随笔為你收集整理的【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。