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

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

14.5 單片機 EEPROM 多字節(jié)讀寫操作時序

我們讀取 EEPROM 的時候很簡單,EEPROM 根據(jù)我們所送的時序,直接就把數(shù)據(jù)送出來了,但是寫 EEPROM 卻沒有這么簡單了。給 EEPROM 發(fā)送數(shù)據(jù)后,先保存在了 EEPROM 的緩存,EEPROM 必須要把緩存中的數(shù)據(jù)搬移到“非易失”的區(qū)域,才能達到掉電不丟失的效果。而往非易失區(qū)域?qū)懶枰欢ǖ臅r間,每種器件不完全一樣,ATMEL 公司的 24C02 的這個寫入時間最高不超過 5 ms。在往非易失區(qū)域?qū)懙倪^程,EEPROM 是不會再響應(yīng)我們的訪問的,不僅接收不到我們的數(shù)據(jù),我們即使用 I2C 標(biāo)準(zhǔn)的尋址模式去尋址,EEPROM 都不會應(yīng)答,就如同這個總線上沒有這個器件一樣。數(shù)據(jù)寫入非易失區(qū)域完畢后,EEPROM 再次恢復(fù)正常,可以正常讀寫了。

細心的同學(xué),在看上一節(jié)程序的時候會發(fā)現(xiàn),我們寫數(shù)據(jù)的那段代碼,實際上我們有去讀應(yīng)答位 ACK,但是讀到了應(yīng)答位我們也沒有做任何處理。這是因為我們一次只寫一個字節(jié)的數(shù)據(jù)進去,等到下次重新上電再寫的時候,時間肯定遠遠超過了 5 ms,但是如果我們是連續(xù)寫入幾個字節(jié)的時候,就必須得考慮到應(yīng)答位的問題了。寫入一個字節(jié)后,再寫入下一個字節(jié)之前,我們必須要等待 EEPROM 再次響應(yīng)才可以,大家注意我們程序的寫法,可以學(xué)習(xí)一下。

之前我們知道編寫多 .c 文件移植的方便性了,本節(jié)程序和上一節(jié)的 Lcd1602.c 文件和 I2C.c 文件完全是一樣的,因此這次我們只把 main.c 文件給大家發(fā)出來,幫大家分析明白。

而同學(xué)們卻不能這樣,同學(xué)們是初學(xué),很多知識和技巧需要多練才能鞏固下來,因此每個程序還是建議大家在你的 Keil 軟件上一個代碼一個代碼的敲出來。 /*I2C.c 文件程序源代碼***/ (此處省略,可參考之前章節(jié)的代碼) /*Lcd1602.c 文件程序源代碼***/ (此處省略,可參考之前章節(jié)的代碼)

/*****************************main.c 文件程序源代碼******************************/
#include <reg52.h>
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len);
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, 0x90, sizeof(buf)); //從 E2 中讀取一段數(shù)據(jù)
    MemToStr(str, buf, sizeof(buf)); //轉(zhuǎ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, 0x90, sizeof(buf)); //再寫回到 E2 中
    while(1);
}
/* 將一段內(nèi)存數(shù)據(jù)轉(zhuǎ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)換完一個字節(jié)添加一個空格
        src++;
    }
}
/* E2 讀取函數(shù),buf-數(shù)據(jù)接收指針,addr-E2 中的起始地址,len-讀取長度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len){
    do { //用尋址操作查詢當(dāng)前是否可進行讀寫操作
        I2CStart();
        if (I2CWrite(0x50<<1)){ //應(yīng)答則跳出循環(huán),非應(yīng)答則進行下一次查詢
            break;
        }
        I2CStop();
    } while(1);
    I2CWrite(addr); //寫入起始地址
    I2CStart(); //發(fā)送重復(fù)啟動信號
    I2CWrite((0x50<<1)|0x01); //尋址器件,后續(xù)為讀操作
    while (len > 1){ //連續(xù)讀取 len-1 個字節(jié)
        *buf++ = I2CReadACK(); //最后字節(jié)之前為讀取操作+應(yīng)答
        len--;
    }
    *buf = I2CReadNAK(); //最后一個字節(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--){
        do { //用尋址操作查詢當(dāng)前是否可進行讀寫操作
            I2CStart();
            if (I2CWrite(0x50<<1)){ //應(yīng)答則跳出循環(huán),非應(yīng)答則進行下一次查詢
                break;
            }
            I2CStop();
        } while(1);
        I2CWrite(addr++); //寫入起始地址
        I2CWrite(*buf++); //寫入一個字節(jié)數(shù)據(jù)
        I2CStop(); //結(jié)束寫操作,以等待寫入完成
    }
}

函數(shù) MemToStr:可以把一段內(nèi)存數(shù)據(jù)轉(zhuǎn)換成十六進制字符串的形式。由于我們從 EEPROM 讀出來的是正常的數(shù)據(jù),而 1602 液晶接收的是 ASCII 碼字符,因此我們要通過液晶把數(shù)據(jù)顯示出來必須先通過一步轉(zhuǎn)換。算法倒是很簡單,就是把每一個字節(jié)的數(shù)據(jù)高4位和低4位分開,和9進行比較,如果小于等于9,則直接加?0?轉(zhuǎn)為0~9的 ASCII 碼;如果大于9,則先減掉10 再加?A?即可轉(zhuǎn)為 A~F 的 ASCII 碼。

函數(shù) E2Read:我們在讀之前,要查詢一下當(dāng)前是否可以進行讀寫操作,EEPROM 正常響應(yīng)才可以進行。進行后,讀最后一個字節(jié)之前的,全部給出 ACK,而讀完了最后一個字節(jié),我們要給出一個 NAK。

函數(shù) E2Write:每次寫操作之前,我們都要進行查詢判斷當(dāng)前 EEPROM 是否響應(yīng),正常響應(yīng)后才可以寫數(shù)據(jù)。