1024手机基地看电影,午夜福利视频导航,国产精品福利在线一区,亚洲欧美日韩另类成人,在线观看午夜日本理论片,成年超爽免费网站,国产精品成人免费,精品动作一级毛片,成人免费观看网站,97精品伊人久久大香蕉

標題: 單片機IIC通信時序的詳細解釋 [打印本頁]

作者: xzf586    時間: 2018-8-16 17:09
標題: 單片機IIC通信時序的詳細解釋
/*---------------------------------------------------------------------
                         IIC.C文件  
  作者:xzf586                                創建日期:2018.8.16   
----------------------------------------------------------------------*/

#include <reg52.h>
#include <intrins.h>
#include"IIC.H"

#define NOP4  {_nop_();_nop_();_nop_();_nop_();_nop_();}

/***********************************************************************
                                                IIC起始信號
時 序:     1        SDA SCL高電平期間,持續時間>4.7us(實際上是總線空閑)
                2        SDA下降沿后,持續時間>4us(線與,總線占用)
************************************************************************/
void I2CStart()
{
    I2C_SDA = 1;         //首先確保SDA、SCL都是高電平,總線空閑
    I2C_SCL = 1;
    NOP4
    I2C_SDA = 0;         //先拉低SDA
    NOP4                        //起始信號結束
        
    I2C_SCL = 0;         //再拉低SCL,為后續SDA數據變化做準備
}
/***********************************************************************
                                                IIC結束通信信號
時 序:     1        SCL高電平期間,持續時間>4.7us
                2        SDA上升沿后,持續時間>4.7us(總線釋放)
************************************************************************/
void I2CStop()
{
    I2C_SDA = 0;
    I2C_SCL = 1; //先拉高SCL
    NOP4
    I2C_SDA = 1; //再拉高SDA,釋放總線
    NOP4
}

/***********************************************************************
                                        IIC主機向從機寫一個字節
時  序:    1        SCL=0;上面起始信號已準備好
                2        SDA=待傳輸位的值0或1
                3        等待一段時間,數據穩定
                4        SCL=1,此時SDA上數據不可以變化,因為從機要讀取這個SDA值
                5         等待一段時間,從機讀取這個SDA值
                6        SCL=0,進行下一次SDA數據變化,再傳輸出去
返回值        從機應答位的值
************************************************************************/
bit I2CWrite(unsigned char dat)
{
    bit ack;                                  //用于暫存應答位的值
    unsigned char temp;          //用于探測字節內某一位值的掩碼變量

    for (temp=0x80; temp!=0; temp>>=1) //從高位到低位依次進行
    {
        if ((temp&dat) == 0) //該位的值輸出到SDA上
            I2C_SDA = 0;
        else
            I2C_SDA = 1;
        NOP4
        I2C_SCL = 1;          //拉高SCL
        NOP4
        I2C_SCL = 0;         //再拉低SCL,完成一個位周期
    }                                                //8位數據發送完畢,
        
    I2C_SDA = 1;   //8位數據發送完后,主機釋放SDA,以檢測從機應答
    NOP4
    I2C_SCL = 1;   //拉高SCL,目的讓主機讀取應答值
    ack = I2C_SDA; //讀取此時的SDA值,即為從機的應答值
    NOP4
    I2C_SCL = 0;   //再拉低SCL完成應答位,并保持住總線

    return (~ack); //應答值取反以符合通常的邏輯:
                   //0=不存在或忙或寫入失敗,1=存在且空閑或寫入成功,注意ack取反
}

/***********************************************************************
                                主機從從機讀取最后一個字節,發送非應答信號
時 序:    1        SDA=1;余下SDA信號由從機控制
                2        SCL=1;拉高SCL,此時SDA上已由從機寫上一位0或1,主機開始讀取
                3        等待一段時間,讀取完畢
                4        SCL=0,拉低SCL,以使從機發送出下一位到SDA上
************************************************************************/
unsigned char I2CReadNAK()
{
    unsigned char temp;
    unsigned char dat;

    I2C_SDA = 1;  //首先確保主機釋放SDA,即將SDA控制權交由從機
    for (temp=0x80; temp!=0; temp>>=1) //從高位到低位依次進行
    {
        NOP4
        I2C_SCL = 1;      //拉高SCL
        if(I2C_SDA == 0)  //讀取SDA的值,此時SDA已由從機寫上一位0或1,
            dat &= ~temp; //為0時,dat中對應位清零
        else
            dat |= temp;  //為1時,dat中對應位置1
        NOP4
        I2C_SCL = 0;      //再拉低SCL,以使從機發送出下一位
    }
        
    I2C_SDA = 1;   //從機8位數據發送完后,主機拉高SDA,發送非應答信號,這樣從機將SDA控制權轉交主機
    NOP4
    I2C_SCL = 1;   //拉高SCL,讓從機讀到這個1,知道停止向主機發送數據
    NOP4
    I2C_SCL = 0;   //再拉低SCL完成非應答位,并保持住總線,因為停止信號還沒有發出,所以要保持總線

    return dat;
}

/***********************************************************************
                        主機從從機讀取一個字節(非最后一個字節),發送應答信號
時 序:     1        SDA=1;余下SDA信號由從機控制
                2        SCL=1;拉高SCL,此時SDA上已由從機寫上一位0或1,主機開始讀取
                3        等待一段時間,讀取完畢
                4        SCL=0,拉低SCL,以使從機發送出下一位到SDA上
************************************************************************/
unsigned char I2CReadACK()
{
    unsigned char temp;
    unsigned char dat;

    I2C_SDA = 1;                                                  //首先確保主機釋放SDA
    for (temp=0x80; temp!=0; temp>>=1) //從高位到低位依次進行
    {
        NOP4
        I2C_SCL = 1;                                      //拉高SCL
        if(I2C_SDA == 0)                                  //讀取SDA的值
            dat &= ~temp;                                 //為0時,dat中對應位清零
        else
            dat |= temp;                                  //為1時,dat中對應位置1
        NOP4
        I2C_SCL = 0;                                      //再拉低SCL,以使從機發送出下一位
    }
        
    I2C_SDA = 0;   //從機8位數據發送完后,主機拉低SDA,發送應答信號,SDA控制權仍然在從機手里
    NOP4
    I2C_SCL = 1;   //拉高SCL,讓從機讀到這個0,繼續向主機發送數據
    NOP4
    I2C_SCL = 0;   //再拉低SCL完成應答位,并保持住總線,SDA由從機確定

    return dat;
}


作者: lyMarvin    時間: 2018-8-17 06:21
謝謝分享!
后面若是有應用示例就更好了
作者: renzaijiangnan    時間: 2020-11-3 07:33
從編程上看,是宋師傅的忠實粉絲,一起學了。有應用實例嗎




歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1