新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51單片機 普通IO口模擬IIC(I2C)接口通訊的程序代碼

        51單片機 普通IO口模擬IIC(I2C)接口通訊的程序代碼

        作者: 時間:2018-08-06 來源:網絡 收藏

        I2C總線是Philips公司提出的一種集成電路IC器件之間相連接的總線協議,其目的是使電子系統(不只 限于單片機系統)各個IC器件之間的連線變得容易。因為使用傳統的并行總線在IC器件之間連接,往往會使得IC之間連線較多,顯得非常復雜。而I2C總線 則使IC器件之間只需SDA、SCL兩條連線就可以傳送數據,因而十分方便。由于I2C在印刷體中不容易書寫(需要上標),所以實際書寫時,還常見到 IIC、I2C等書寫方法,本文采用IIC的寫法,敬請注意。關于IIC總線的知識,請參閱相關書籍,此處不再做進一步介紹。

        本文引用地址:http://www.104case.com/article/201808/385451.htm

        下面我們用一個使用IIC總線連接器件的例子來簡單說明IIC總線的仿真。

        例.EEPROM24C02是采用IIC接口的一種常用2Kbit(256×8bit)的存儲器。編寫程序使用AT89C51的IO口模擬實現IIC總線協議進行通信,并向24C02存儲器內從字節0到字節FF寫入數字0到FF。

        51系列單片機本身沒有IIC接口,但一些本身具有IIC接口的單片機往往是高端產品,一方面價格不菲,另一方面我們的系統也沒有必要使用之。通常我們就使用軟件通過51系列單片機的IO口來模擬實現IIC總線通信。

        本例事實上比較簡單,但需要對IIC總線時序有較好的理解。源文件如下圖所示(采用C51語言編寫):




        在Keil中編輯好源文件以后,接下來就可以建立工程文件并生成相應的源代碼了,然后我們來繪制電路圖。

        此例的電路圖極其簡單。只需兩個IC,即AT89C51和24C02C,和兩個上拉電阻,而且上拉電阻還可以省略。至于連接,就更為簡單了。最后得到繪制好的電路圖如下圖所示:


        繪制好電路圖,我們就可以將前面剛剛生成的程序源代碼裝入單片機了,裝入以后,下面我們就可以來進行仿真了。

        首先點擊仿真按鈕,系統沒有什么反映,只有高低電平變化的顏色。我們要想查看結果,還要用前文中仿真擴展 RAM存儲器的方法,先點擊暫停,然后點擊“Debug”菜單下的“I2C Memory Internal Memory – U2”子菜單來打開U2即EEPROM存儲器24C02C的內容窗口“I2C Memory Internal Memory – U2”,然后我們就看到了其中的內容,也就是我們仿真程序的結果。如下圖所示:


        從圖中我們能清楚地看到我們的仿真結果,程序完全正確地執行了我們的命令。

        當然,如果你過早地點擊了暫停按鈕,那么你得到的結果可能和上圖略有不同,那可能是因為程序尚未執行完畢。此時你可以繼續點擊運行按鈕,或者點擊單步按鈕來仔細查看程序執行過程中24C02C存儲器內容的改變情況。

        完整代碼如下:

        /*----------------------------------------------------------------

        Acess the eeprom--24c04

        ----------------------------------------------------------------*/

        #include

        #ifndef INT8U

        #define INT8U unsigned char

        #endif

        #ifndef INT8S

        #define INT8S signed char

        #endif

        #ifndef INT16U

        #define INT16U unsigned int

        #endif

        #define I2C_DELAY; _nop_();_nop_();_nop_();_nop_();_nop_(); // >=4.7uS

        //----------------------------------------------------------------

        // delay 100us

        //----------------------------------------------------------------

        void mDelay(INT8U k)

        {

        INT16U i ;

        for(; k>0; k--)

        {

        for(i=0; i93; i++)

        ;

        }

        }

        //----------------------------------------------------------------

        //OK

        //----------------------------------------------------------------

        void I2C_Start(void)

        {

        SDA = 1;

        I2C_DELAY;

        SCL = 1;

        I2C_DELAY;

        SDA = 0;

        I2C_DELAY;

        I2C_DELAY;

        }

        //----------------------------------------------------------------

        //OK

        //----------------------------------------------------------------

        void I2C_Stop(void)

        {

        SDA = 0 ;

        I2C_DELAY;

        SCL = 1 ;

        I2C_DELAY;

        SDA = 1 ;

        I2C_DELAY;

        I2C_DELAY;

        }

        //----------------------------------------------------------------

        //

        //----------------------------------------------------------------

        void sendAck(void)

        {

        SCL = 0;

        I2C_DELAY;

        SDA = 0;

        I2C_DELAY;

        SCL = 1;

        I2C_DELAY;

        }

        //----------------------------------------------------------------

        //

        //----------------------------------------------------------------

        void sendNoAck(void)

        {

        SCL = 0;

        I2C_DELAY;

        SDA = 1;

        I2C_DELAY;

        SCL = 1;

        I2C_DELAY;

        }

        //----------------------------------------------------------------

        // 0 = noACK; 1 = ACK ;

        //----------------------------------------------------------------

        bit checkAck()

        {

        bit tempbit;

        /*發送完一個字節后檢驗設備的應答信號*/

        SDA = 1;

        I2C_DELAY;

        SCL = 0;

        I2C_DELAY;

        tempbit = SDA;

        SCL = 1;

        I2C_DELAY;

        if(tempbit==1)

        {

        return 0; //noACK

        }

        else

        {

        return 1; //ACK

        }

        }

        //----------------------------------------------------------------

        //OK

        // a positive clock edge clock a bit into the ROM

        //----------------------------------------------------------------

        void writeByte(INT8U datum)

        {

        INT8U bitCnt = 0 ;

        for(bitCnt=0; bitCnt8; bitCnt++)

        {

        SCL = 0 ;

        I2C_DELAY;

        if ((datum0x80) == 0x80) //if the MSb is 1

        SDA = 1 ;

        else

        SDA = 0 ;

        I2C_DELAY;

        SCL = 1 ;

        I2C_DELAY;

        datum=1 ;

        }

        }

        //----------------------------------------------------------------

        //OK

        //----------------------------------------------------------------

        INT8U readByte(void)

        {

        bit tempbit = 1 ;

        INT8U temp = 0 ;

        INT8U bitCnt ;

        SDA = 1 ; // release the bus,ready to receive byte??????????????

        I2C_DELAY;

        for(bitCnt=0; bitCnt8; bitCnt++)

        {

        SCL = 0; //?????????????????????????huan???????????????

        I2C_DELAY;

        tempbit = SDA ;

        if (tempbit)

        temp |= 0x01 ;

        else

        temp = 0xfe ;

        SCL = 1 ;

        I2C_DELAY;

        if(bitCnt7)

        temp = 1 ;

        }

        return(temp) ;

        }

        /*~~~~~~~~~~~~~~~~~~~~~~~ API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

        /*-----------------------------------------------------------------

        write some bytes to sequential address

        -----------------------------------------------------------------*/

        void writeToROM(INT8U datum[], INT8U address, INT8U num)

        {

        bit tempbit ;

        INT8U i ;

        INT8U *datum_P ;

        datum_P = datum ;

        I2C_Start() ;

        writeByte(0xa0) ;

        tempbit = checkAck();

        writeByte(address) ;

        tempbit = checkAck();

        for(i=0; i

        {

        writeByte(*(datum_P+i)) ;

        if(!checkAck())

        {

        I2C_Stop() ;

        mDelay(100) ;

        }

        }

        I2C_Stop() ;

        }

        /*-----------------------------------------------------------------

        read some bytes from ROM`s sequential address

        -----------------------------------------------------------------*/

        void readFromROM(INT8U datum[], INT8U address, INT8U num)

        {

        bit tempbit ;

        INT8U i ;

        INT8U *datum_P ;

        datum_P = datum;

        I2C_Start() ;

        writeByte(0xa0) ;

        tempbit = checkAck();

        writeByte(address) ;

        tempbit = checkAck();

        I2C_Start() ;

        writeByte(0xa1) ;

        tempbit = checkAck();

        for(i=0; i

        {

        *(datum_P+i) = readByte() ;

        if(i!=num-1)

        {

        sendAck() ;

        }

        else

        {

        sendNoAck() ;

        }

        }

        I2C_Stop() ;

        }

        /*-----------------------------------------------------------------

        wirte one byte to ROM --random write

        -----------------------------------------------------------------*/

        void writeOneByte(INT8U addr, INT8U datum)

        {

        bit tempbit ;

        /*write a byte to mem*/

        I2C_Start();

        writeByte(0xa0);

        tempbit = checkAck();

        writeByte(addr); /*address*/

        tempbit = checkAck();

        writeByte(datum); /*the data*/

        tempbit = checkAck();

        I2C_Stop();

        mDelay(100) ;

        }

        /*-----------------------------------------------------------------

        read one byte from rom --random read

        -----------------------------------------------------------------*/

        INT8U readOneByte(INT8U addr)

        {

        bit tempbit = 1;

        INT8U mydata;

        /*read a byte from mem*/

        I2C_Start();

        writeByte(0xa0);

        tempbit = checkAck();

        writeByte(addr); /*address*/

        tempbit = checkAck();

        I2C_Start();

        writeByte(0xa1);

        tempbit = checkAck();

        mydata = readByte();

        tempbit = checkAck();

        return (mydata) ;

        I2C_Stop();

        }

        『本文轉載自網絡,版權歸原作者所有,如有侵權請聯系刪除』



        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 岳阳市| 攀枝花市| 岱山县| 璧山县| 鹿邑县| 抚松县| 清远市| 大宁县| 孟州市| 苍溪县| 故城县| 上虞市| 达州市| 旬阳县| 中西区| 鲜城| 原平市| 牡丹江市| 德兴市| 邹平县| 宝山区| 民和| 紫金县| 连州市| 张家港市| 广河县| 曲阜市| 土默特左旗| 冕宁县| 忻州市| 陆良县| 安吉县| 丰原市| 东源县| 玛沁县| 铁力市| 黄石市| 江口县| 久治县| 温宿县| 深泽县|