两个吃奶一个添下面视频_人妻第一页香蕉网_欧美xxxx少妇_妺妺窝人体色www婷婷

1.淺釋E2Write函數(shù)

宋老師的例程lesson14_3和lesson14_4里的“E2Write(unsigned char *buf, unsigned char addr, unsigned char len)”書寫內(nèi)容是不一樣的,lesson14_4的E2Write函數(shù)比lesson14_3的E2Write函數(shù)運行高效,lesson14_3的E2Write函數(shù)是每寫入一個字節(jié)就要經(jīng)歷起始信號,停止信號,寫入下一個字節(jié)又要把這些步驟經(jīng)歷一遍。而lesson14_4的E2Write函數(shù)支持EEPROM頁寫入(參考《手把手教你學(xué)51單片機》文檔14.3.3節(jié)),所以在建立起文件時我們選用lesson14_4的E2Write函數(shù)。

大家新建兩個文件“iic.c”和“iic.h”,我們把IIC的相關(guān)函數(shù)和EEPROM的相關(guān)函數(shù)都合成在“iic.c”這個單獨文件里。

2.iic.c的代碼

#include <reg52.h>
#include <iic.h>
#include <intrins.h>
 
#define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}
 
/* 產(chǎn)生總線起始信號 */
void I2CStart()
{
    I2C_SDA = 1; //首先確保SDA、SCL都是高電平
    I2C_SCL = 1;
    I2CDelay();
    I2C_SDA = 0; //先拉低SDA
    I2CDelay();
    I2C_SCL = 0; //再拉低SCL
}

/* 產(chǎn)生總線停止信號 */
void I2CStop()
{
    I2C_SCL = 0; //首先確保SDA、SCL都是低電平
    I2C_SDA = 0;
    I2CDelay();
    I2C_SCL = 1; //先拉高SCL
    I2CDelay();
    I2C_SDA = 1; //再拉高SDA
    I2CDelay();
}

/* I2C總線寫操作,dat-待寫入字節(jié),返回值-從機應(yīng)答位的值 */
unsigned char I2CWrite(unsigned char dat)
{
    unsigned char ack;                 //用于暫存應(yīng)答位的值
    unsigned char mask;                //用于探測字節(jié)內(nèi)某一位值的掩碼變量
  
    for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進行
    {
        if ((mask&dat) == 0)  //該位的值輸出到SDA上
            I2C_SDA = 0;
        else
            I2C_SDA = 1;
        I2CDelay();
        I2C_SCL = 1;          //拉高SCL
        I2CDelay();
        I2C_SCL = 0;          //再拉低SCL,完成一個位周期
    }
    I2C_SDA = 1;   //8位數(shù)據(jù)發(fā)送完后,主機釋放SDA,以檢測從機應(yīng)答
    I2CDelay();
    I2C_SCL = 1;   //拉高SCL
    ack = I2C_SDA; //讀取此時的SDA值,即為從機的應(yīng)答值
    I2CDelay();
    I2C_SCL = 0;   //再拉低SCL完成應(yīng)答位,并保持住總線
  
    return (!ack); //應(yīng)答值取反以符合通常的邏輯:
                   //0=不存在或忙或?qū)懭胧。?=存在且空閑或?qū)懭氤晒?
}

/* I2C總線讀操作,并發(fā)送應(yīng)答或者非應(yīng)答信號,返回值-讀到的字節(jié) */
unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack)
{
    unsigned char mask;
    unsigned char dat;
  
    I2C_SDA = 1;                       //首先確保主機釋放SDA
    for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進行
    {
        I2CDelay();
        I2C_SCL = 1;      //拉高SCL
        if(I2C_SDA == 0)  //讀取SDA的值
            dat &= ~mask; //為0時,dat中對應(yīng)位清零
        else
            dat |= mask;  //為1時,dat中對應(yīng)位置1
        I2CDelay();
        I2C_SCL = 0;      //再拉低SCL,以使從機發(fā)送出下一位
    }
    I2C_SDA = nak_or_ack; //8位數(shù)據(jù)發(fā)送完后,傳入的參數(shù)NAK_OR_ACK決定是否應(yīng)答,為1不應(yīng)答,為0應(yīng)答
    I2CDelay();
    I2C_SCL = 1;   //拉高SCL
    I2CDelay();
    I2C_SCL = 0;   //再拉低SCL完成非應(yīng)答位,并保持住總線
  
    return dat;
}

/* E2讀取函數(shù),buf-數(shù)據(jù)接收指針,addr-E2中的起始地址,len-讀取長度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{
    do {                               //用尋址操作查詢當前是否可進行讀寫操作
           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++ = I2CReadNAK_OR_ACK(0); //最后字節(jié)之前為讀取操作+應(yīng)答
        len--;
    }
    *buf = I2CReadNAK_OR_ACK(1);       //最后一個字節(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 {                          //用尋址操作查詢當前是否可進行讀寫操作
               I2CStart();
               if (I2CWrite(0x50<<1)) //應(yīng)答則跳出循環(huán),非應(yīng)答則進行下一次查詢
               {
                   break;
               }
               I2CStop();
        } while(1);
        //按頁寫模式連續(xù)寫入字節(jié)
        I2CWrite(addr);           //寫入起始地址
        while (len > 0)
        {
            I2CWrite(*buf++);     //寫入一個字節(jié)數(shù)據(jù)
            len--;                //待寫入長度計數(shù)遞減
            addr++;               //E2地址遞增
            if ((addr&0x07) == 0) //檢查地址是否到達頁邊界,24C02每頁8字節(jié),
            {                     //所以檢測低3位是否為零即可
                break;            //到達頁邊界時,跳出循環(huán),結(jié)束本次寫操作
            }
        }
        I2CStop();
    }
}


3.iic.h的代碼

#ifndef __IIC_H__
#define __IIC_H__
 
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
void I2CStart();//產(chǎn)生總線起始信號
void I2CStop(); //產(chǎn)生總線停止信號
unsigned char I2CWrite(unsigned char dat);//I2C總線寫操作,dat-待寫入字節(jié),返回值-從機應(yīng)答位的值
unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack);//I2C總線讀操作,并發(fā)送應(yīng)答或者非應(yīng)答信號,返回值-讀到的字節(jié)
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len); //E2讀取函數(shù),buf-數(shù)據(jù)接收指針,addr-E2中的起始地址,len-讀取長度
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);//E2寫入函數(shù),buf-源數(shù)據(jù)指針,addr-E2中的起始地址,len-寫入長度
 
#endif


4.部分代碼的修改

“unsigned char I2CReadACK()”和“unsigned char I2CReadNAK()”這里我們合成了一個函數(shù)為

“unsigned char I2CReadNAK_OR_ACK(unsigned char nak_or_ack)”,利用參數(shù)的傳遞決定是否產(chǎn)生應(yīng)答。

那么在main.c中,幾乎也是只需要出現(xiàn)EEPROM的寫函數(shù)“E2Write()”和讀函數(shù)“E2Read()”而已了。

記得把“iic”添加到工程文件中

iic7


5.main.c測試代碼

#include <reg52.h>
#include <function.h>//詳見第六章第8講
#include <lcd.h>     //詳見第十一章第3講
#include <iic.h>
 
void main()
{
    unsigned char buf[]={"We can learn SCM well!"};//我們可以學(xué)好單片機
    unsigned char str[sizeof(buf)];                //數(shù)組長度與buf的一樣
  
    InitLcd1602();                //初始化液晶
    E2Write(buf,0x8E,sizeof(buf));//把buf數(shù)組里面的內(nèi)容在EEPROM中從地址0x8E開始寫,直到把數(shù)組里的內(nèi)容全部寫完進去,在EEPROM中保存起來
  
    delay_ms(1000);               //過1秒之后再讀出里面的內(nèi)容顯示在液晶屏上
  
    E2Read(str,0x8E,sizeof(buf)); //用另一個數(shù)組存取從EEPROM中讀出的內(nèi)容
    LcdShowStr_len(0, 0,str, 16);
    LcdShowStr(0, 1, str+16+1);
    while(1);
}
點贊(0)

C語言網(wǎng)提供由在職研發(fā)工程師或ACM藍橋杯競賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點擊了解:

一點編程也不會寫的:零基礎(chǔ)C語言學(xué)練課程

解決困擾你多年的C語言疑難雜癥特性的C語言進階課程

從零到寫出一個爬蟲的Python編程課程

只會語法寫不出代碼?手把手帶你寫100個編程真題的編程百練課程

信息學(xué)奧賽或C++選手的 必學(xué)C++課程

藍橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競賽課入門課程

手把手講解近五年真題的藍橋杯輔導(dǎo)課程

Dotcpp在線編譯      (登錄可減少運行等待時間)