在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 數(shù)據(jù)庫/ 14.6 單片機(jī)EEPROM的頁寫入
18. RS485 通信與 Modbus 協(xié)議
17.5 A/D 差分輸入信號
15.8 C 語言復(fù)合數(shù)據(jù)類型(結(jié)構(gòu)體,共用體,枚舉類型)
16.3 NEC 協(xié)議紅外遙控器
13.1 單片機(jī)通信時(shí)序解析
14.4 單片機(jī) EEPROM 單字節(jié)讀寫操作時(shí)序
13.3 多個(gè) .c 文件的初步認(rèn)識
18.2 Modbus 通信協(xié)議介紹
15.1 BCD 碼介紹
18.3 單片機(jī) Modbus 多機(jī)通信程序設(shè)計(jì)
18.1 單片機(jī) RS485 通信接口、控制線、原理圖及程序?qū)嵗?/span>
15. 實(shí)時(shí)時(shí)鐘 DS1302
14.7 單片機(jī) I2C 和 EEPROM 的綜合編程
17. 模數(shù)轉(zhuǎn)換與數(shù)模轉(zhuǎn)換
16.2 紅外遙控通信原理
13.2 1602 液晶整屏移動程序
17.6 D/A 輸出
17.7 單片機(jī)信號發(fā)生器程序
16.4 溫度傳感器 DS18B20
14.6 單片機(jī)EEPROM的頁寫入
13.4 單片機(jī)計(jì)算器程序設(shè)計(jì)[詳細(xì)]
17.2 A/D(模數(shù)轉(zhuǎn)換)的主要指標(biāo)
17.4 PCF8591 應(yīng)用程序
17.1 A/D 和 D/A 的基本概念
17.3 PCF8591硬件接口(電路圖引腳圖)
14.3 單片機(jī) EEPROM 簡介
13.5 單片機(jī)串口通信原理和控制程序
15.5 DS1302 寄存器介紹
15.2 單片機(jī) SPI 通信接口
15.6 DS1302 通信時(shí)序介紹
14.5 單片機(jī) EEPROM 多字節(jié)讀寫操作時(shí)序
16. 紅外通信與 DS18B20 溫度傳感器
14.1 單片機(jī) I2C 時(shí)序介紹
15.3 實(shí)時(shí)時(shí)鐘芯片 DS1302 介紹
15.9 單片機(jī)電子時(shí)鐘程序設(shè)計(jì)
16.1 紅外光的基本原理
15.4 DS1302 的硬件信息
15.7 DS1302 的 BURST 模式
14.2 單片機(jī) I2C 尋址模式
14. 單片機(jī) I2C 總線與 EEPROM
13. 單片機(jī) 1602 液晶與串口的應(yīng)用實(shí)例

14.6 單片機(jī)EEPROM的頁寫入

在向 EEPROM 連續(xù)寫入多個(gè)字節(jié)的數(shù)據(jù)時(shí),如果每寫一個(gè)字節(jié)都要等待幾 ms 的話,整體上的寫入效率就太低了。因此 EEPROM 的廠商就想了一個(gè)辦法,把 EEPROM 分頁管理。24C01、24C02 這兩個(gè)型號是8個(gè)字節(jié)一個(gè)頁,而 24C04、24C08、24C16 是16個(gè)字節(jié)一頁。我們開發(fā)板上用的型號是 24C02,一共是256個(gè)字節(jié),8個(gè)字節(jié)一頁,那么就一共有32頁。

分配好頁之后,如果我們在同一個(gè)頁內(nèi)連續(xù)寫入幾個(gè)字節(jié)后,最后再發(fā)送停止位的時(shí)序。EEPROM 檢測到這個(gè)停止位后,就會一次性把這一頁的數(shù)據(jù)寫到非易失區(qū)域,就不需要像上節(jié)課那樣寫一個(gè)字節(jié)檢測一次了,并且頁寫入的時(shí)間也不會超過 5 ms。如果我們寫入的數(shù)據(jù)跨頁了,那么寫完了一頁之后,我們要發(fā)送一個(gè)停止位,然后等待并且檢測 EEPROM 的空閑模式,一直等到把上一頁數(shù)據(jù)完全寫到非易失區(qū)域后,再進(jìn)行下一頁的寫入,這樣就可以在很大程度上提高數(shù)據(jù)的寫入效率。 /*I2C.c 文件程序源代碼***/ (此處省略,可參考之前章節(jié)的代碼) /*Lcd1602.c 文件程序源代碼***/ (此處省略,可參考之前章節(jié)的代碼)

/****************************eeprom.c 文件程序源代碼*****************************/
#include <reg52.h>

extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);

/* E2 讀取函數(shù),buf-數(shù)據(jù)接收指針,addr-E2 中的起始地址,len-讀取長度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len){
do { //用尋址操作查詢當(dāng)前是否可進(jìn)行讀寫操作
    I2CStart();
    if (I2CWrite(0x50<<1)){ //應(yīng)答則跳出循環(huán),非應(yīng)答則進(jìn)行下一次查詢
        break;
    }
    I2CStop();
}while(1);

    I2CWrite(addr); //寫入起始地址
    I2CStart();//發(fā)送重復(fù)啟動信號
    I2CWrite((0x50<<1)|0x01); //尋址器件,后續(xù)為讀操作
    while (len > 1){//連續(xù)讀取 len-1 個(gè)字節(jié)
        *buf++ = I2CReadACK(); //最后字節(jié)之前為讀取操作+應(yīng)答
        len--;
    }
    *buf = I2CReadNAK(); //最后一個(gè)字節(jié)為讀取操作+非應(yīng)答
    I2CStop();
}
/* E2 寫入函數(shù),buf-源數(shù)據(jù)指針,addr-E2 中的起始地址,len-寫入長度 */
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len){
    while (len > 0){ //等待上次寫入操作完成
        do { //用尋址操作查詢當(dāng)前是否可進(jìn)行讀寫操作
            I2CStart();
            if (I2CWrite(0x50<<1)){ //應(yīng)答則跳出循環(huán),非應(yīng)答則進(jìn)行下一次查詢
                break;
            }
            I2CStop();
        } while(1);
    //按頁寫模式連續(xù)寫入字節(jié)

        I2CWrite(addr); //寫入起始地址
        while (len > 0){
            I2CWrite(*buf++); //寫入一個(gè)字節(jié)數(shù)據(jù)
            len--; //待寫入長度計(jì)數(shù)遞減
            addr++; //E2 地址遞增
            //檢查地址是否到達(dá)頁邊界,24C02 每頁 8 字節(jié),
            //所以檢測低 3 位是否為零即可
            if ((addr&0x07) == 0){
                break; //到達(dá)頁邊界時(shí),跳出循環(huán),結(jié)束本次寫操作
            }
        }
        I2CStop();
    }
}

遵循模塊化的原則,我們把 EEPROM 的讀寫函數(shù)也單獨(dú)寫成一個(gè) eeprom.c 文件。其中 E2Read 函數(shù)和上一節(jié)是一樣的,因?yàn)樽x操作與分頁無關(guān)。重點(diǎn)是 E2Write 函數(shù),我們在寫入數(shù)據(jù)的時(shí)候,要計(jì)算下一個(gè)要寫的數(shù)據(jù)的地址是否是一個(gè)頁的起始地址,如果是的話,則必須跳出循環(huán),等待 EEPROM 把當(dāng)前這一頁寫入到非易失區(qū)域后,再進(jìn)行后續(xù)頁的寫入。

/*****************************main.c 文件程序源代碼******************************/
#include <reg52.h>

extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void E2Read(unsigned char *buf, unsigned char addr, unsigned char len);
extern void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);
void MemToStr(unsigned char *str, unsigned char *src, unsigned char len);

void main(){
    unsigned char i;
    unsigned char buf[5];
    unsigned char str[20];

    InitLcd1602(); //初始化液晶
    E2Read(buf, 0x8E, sizeof(buf)); //從 E2 中讀取一段數(shù)據(jù)
    MemToStr(str, buf, sizeof(buf)); //轉(zhuǎn)換為十六進(jìn)制字符串
    LcdShowStr(0, 0, str); //顯示到液晶上
    for (i=0; i<sizeof(buf); i++){ //數(shù)據(jù)依次+1,+2,+3...
        buf[i] = buf[i] + 1 + i;
    }
    E2Write(buf, 0x8E, sizeof(buf)); //再寫回到 E2 中
    while(1);
}
/* 將一段內(nèi)存數(shù)據(jù)轉(zhuǎn)換為十六進(jìn)制格式的字符串,
str-字符串指針,src-源數(shù)據(jù)地址,len-數(shù)據(jù)長度 */
void MemToStr(unsigned char *str, unsigned char *src, unsigned char len){
    unsigned char tmp;
    while (len--){
        tmp = *src >> 4; //先取高 4 位
        if (tmp <= 9){ //轉(zhuǎn)換為 0-9 或 A-F
            *str++ = tmp + '0';
        }else{
            *str++ = tmp - 10 + 'A';
        }
        tmp = *src & 0x0F; //再取低 4 位
        if (tmp <= 9){  //轉(zhuǎn)換為 0-9 或 A-F
            *str++ = tmp + '0';
        }else{
            *str++ = tmp - 10 + 'A';
        }
        *str++ = ' '; //轉(zhuǎn)換完一個(gè)字節(jié)添加一個(gè)空格
        src++;
    }
}

多字節(jié)寫入和頁寫入程序都編寫出來了,而且頁寫入的程序我們還特地跨頁寫的數(shù)據(jù),它們的寫入時(shí)間到底差別多大呢。我們用一些工具可以測量一下,比如示波器,邏輯分析儀等工具。我現(xiàn)在把兩次寫入時(shí)間用邏輯分析儀給抓了出來,并且用時(shí)間標(biāo)簽 T1 和 T2 標(biāo)注了開始位置和結(jié)束位置,如圖14-5和圖14-6所示,右側(cè)顯示的|T1-T2|就是最終寫入5個(gè)字節(jié)所耗費(fèi)的時(shí)間。多字節(jié)一個(gè)一個(gè)寫入,每次寫入后都需要再次通信檢測 EEPROM 是否在“忙”,因此耗費(fèi)了大量的時(shí)間,同樣的寫入5個(gè)字節(jié)的數(shù)據(jù),一個(gè)一個(gè)寫入用了 8.4 ms 左右的時(shí)間,而使用頁寫入,只用了 3.5 ms 左右的時(shí)間。

http://wiki.jikexueyuan.com/project/mcu-tutorial-three/images/8.png" alt="" />

圖14-5 多字節(jié)寫入時(shí)間

http://wiki.jikexueyuan.com/project/mcu-tutorial-three/images/9.png" alt="" />

圖14-6 跨頁寫入時(shí)間