小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

IIC詳解,包括原理、過程,最后一步步教你實(shí)現(xiàn)IIC

 用久智能 2021-05-10

IIC詳解

1、I2C總線具有兩根雙向信號線,一根是數(shù)據(jù)線SDA,另一根是時(shí)鐘線SCL  

2、IIC總線上可以掛很多設(shè)備:多個(gè)主設(shè)備,多個(gè)從設(shè)備(外圍 設(shè)備)。上圖中主設(shè)備是兩個(gè)單片機(jī),剩下的都是從設(shè)備。 

3、多主機(jī)會(huì)產(chǎn)生總線裁決問題。當(dāng)多個(gè)主機(jī)同時(shí)想占用總線時(shí),企圖啟動(dòng)總線傳輸數(shù)據(jù),就叫做總線競爭。I2C通過總線仲裁,以決定哪臺(tái)主機(jī)控制總線

4、上拉電阻一般在4.7k~10k之間

       

5、每個(gè)接到I2C總線上的器件都有唯一的地址。主機(jī)與其它器件間的數(shù)據(jù)傳輸可以是由主機(jī)發(fā)送數(shù)據(jù)到其它器件,這時(shí)主機(jī) 即為發(fā)送器,總線上收數(shù)據(jù)的器件則為接收器。

6、I2C總線的數(shù)據(jù)傳送:

     (1)、數(shù)據(jù)位的有效性規(guī)定:

         

      (2)、起始與終止信號:SCL為高期間,

             SDA : 由高到低,起始信號

             SDA:由低到高,終止信號

            

7、起始信號和終止信號都是由主機(jī)發(fā)送的。在起始信號產(chǎn)生之后,總線就處于被占用的狀態(tài),在終止信號產(chǎn)生之后,總線就處于空閑狀態(tài)。

8、連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測到起始和終止信號。

9、每當(dāng)發(fā)送器傳輸完一個(gè)字節(jié)的數(shù)據(jù)之后,發(fā)送端會(huì)等待一定的時(shí)間,等接收方的應(yīng)答信號。接收端通過拉低SDA數(shù)據(jù)線,給發(fā)送端發(fā)送一個(gè)應(yīng)答信號,以提醒發(fā)送端我這邊已經(jīng)接受完成,數(shù)據(jù)可以繼續(xù)傳輸,接下來,發(fā)送端就可以繼續(xù)發(fā)送數(shù)據(jù)了。

10、數(shù)據(jù)傳送格式:主機(jī)發(fā)送給從機(jī)

        

11、I2C模擬方式 的特殊情況:

      

12、總線尋址:

       (1)、主機(jī)向從機(jī)發(fā)送8位數(shù)據(jù),這8位數(shù)據(jù)是在起始信號之后發(fā)送的第一個(gè)字節(jié),后面的字節(jié)都是數(shù)據(jù),不再是尋址,除非又重新來一個(gè)起始信號。

         

     (2)、主機(jī)給從機(jī)發(fā)送第一個(gè)字節(jié)(總線尋址那個(gè)字節(jié)),若是讀命令,則從機(jī)接收到該 命令之后,主動(dòng)往主機(jī)發(fā)送數(shù)據(jù)。

     (3)、主機(jī)發(fā)送地址時(shí),總線上的每個(gè)從機(jī)都將這7位地址碼與自己的地址進(jìn)行比較,若相同,則認(rèn)為自己正在被主機(jī)尋址,根據(jù)R/T位將自己確定為發(fā)送器和接收器

     (4)、從機(jī)地址的確定:第0位是讀寫位。(如對于24C02這塊存儲(chǔ)器,它若作為從機(jī),那么它的地址中7~4位是固定的,更改不了,第3~1位是可以更改的,每一位根據(jù)硬件的管教連接來確定,連接高電平那就是1,低電平就是0)

            

13、在起始信號后必須傳送一個(gè)從機(jī)的地址(7位),第8位是數(shù)據(jù)的傳送方向位(R/T),用“0”表示主機(jī)發(fā)送數(shù)據(jù)(T),“1”表示主機(jī)接收數(shù)據(jù)(R)。

14、每次數(shù)據(jù)傳送總是由主機(jī)產(chǎn)生的終止信號來結(jié)束。但是,若主機(jī)希望繼續(xù)占用總線進(jìn)行新的數(shù)據(jù)傳送,則可以不產(chǎn)生終止信號,馬上再次發(fā)出起始信號對另一從機(jī)進(jìn)行尋址。

15、在總線的一次數(shù)據(jù)傳輸中,可以有一下幾種組合方式:

       (1)、主機(jī)向從機(jī)發(fā)送數(shù)據(jù),數(shù)據(jù)傳送方向在整個(gè)傳遞過程中不變:

        

        (2)、主機(jī)在第一個(gè)字節(jié)后,立即從從機(jī)讀數(shù)據(jù)(傳輸方向不變):

               

         (3)、在傳送過程中,當(dāng)需要改變傳遞方向時(shí),起始信號和從機(jī)地址都被重復(fù)一次產(chǎn)生一次,但兩次讀/寫方向位正好相反

                

16、時(shí)序:

       

注:主機(jī)做的都是編程控制,從機(jī)做的都是自主控制,也可以說是硬件控制,如主機(jī)給應(yīng)答信號是編程控制,但是從機(jī)給應(yīng)答信號是硬件控制,我們只需要檢查在SDA為高期間,SCL保持低電平一些時(shí)間,即可判定從機(jī)給了主機(jī)應(yīng)答信號。

17、模擬IIC編程

       (1)、開引腳的時(shí)鐘:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

       (2)、宏定義: 

    • #define I2C_SCL    GPIO_Pin_6
    • #define I2C_SDA   GPIO_Pin_7
    • #define GPIO_I2C  GPIOB
    • #define I2C_SCL_H GPIO_SetBits(GPIO_I2C, I2C_SCL)  //把PB6置高
    • #define I2C_SCL_L  GPIO_ResetBits(GPIO_I2C, I2C_SCL)  //把PB6置低
    • #define I2C_SDA_H  GPIO_ResetBits(GPIO_I2C, I2C_SDA)  //把PB7置高
    • #define I2C_SDA_L  GPIO_ResetBits(GPIO_I2C, I2C_SDA)  //把PB7置低

        (3)、配置函數(shù)

               void I2C_Init(void)

               {

                    GPIO_InitTypeDef GPIO_InitStructure;

                    GPIO_InitStructure.GPIO_Pin=I2C_SCL | I2C_SDA;

                    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

                    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //推挽輸出模式

                    GPIO_Init(GPIOB,&GPIO_InitStructure);

               }

       (4)、SDA有輸出方向和輸入方向,配置SDA的這兩個(gè)模式:

               void I2C_OUT(void)    //SDA是輸出方向

               {

                    GPIO_InitTypeDef GPIO_InitStructure;

                    GPIO_InitStructure.GPIO_Pin=I2C_SDA;

                    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

                    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //推挽輸出模式

                    GPIO_Init(GPIOB,&GPIO_InitStructure);

                    I2C_SCL_H;

                    I2C_SDA_H;   //把兩條線都變成高電平

                }

                void I2C_IN(void)    //SDA是輸入方向

                {

                    GPIO_InitTypeDef GPIO_InitStructure;

                    GPIO_InitStructure.GPIO_Pin=I2C_SDA;

                    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

                    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_IPU;  //輸入上拉模式

                    GPIO_Init(GPIOB,&GPIO_InitStructure);

                }

          (5)、產(chǎn)生起始信號:  看上面的時(shí)序圖寫

                 void I2C_Start(void)  //在SCL高電平,SDA由高到低,在此之前,SDA的高電平必須保持>4.7us,起始信號變成低電平之后,還要延時(shí)>4us

               {

                    I2C_SDA_OUT();    //SDA是輸出方向,即由主機(jī)發(fā)送的

                    I2C_SDA_H;

                    I2C_SCL_H;

                    delay_us(5);    //延時(shí)5個(gè)微妙

                    I2C_SDA_L;  //起始信號

                    delay_us(5);

                    I2C_SCL_L;

               }

          (6)、主機(jī)產(chǎn)生停止信號:

                void I2C_Stop(void)

               {

                    I2C_SDA_OUT(); 

                    I2C_SCL_L;

                    I2C_SDA_L;

                    I2C_SCL_H;                   

                    delay_us(5);

                    I2C_SDA_H;

                    delay_us(5);

               }

          (7)、主機(jī)產(chǎn)生應(yīng)答信號:

                 void I2C_ACK(void)

                 {

                     I2C_SDA_OUT();

                     I2C_SCL_L;

                     I2C_SDA_L;

                     delay_us(2);

                     I2C_SCL_H;

                     delay_us(5);

                     I2C_SCL_L;

       //           I2C_SDA_H;

                 }

          (8)、主機(jī)不發(fā)送應(yīng)答信號:

                void I2C_NACK(void)

               {

                    I2C_SDA_OUT();

                    I2C_SCL_L;

                    I2C_SDA_H;

                    delay_us(2);

                    I2C_SCL_H;

                    delay_us(5);

                    I2C_SCL_L;

               }

          (9)、等待信號,當(dāng)發(fā)送器發(fā)送一個(gè)數(shù)據(jù)之后,需要等待從接收端發(fā)過來的應(yīng)答信號,主機(jī)等待從機(jī)應(yīng)答

                 u8 I2C_Wait_ACK(void)    //SDA為低電平時(shí),表明從機(jī)給了應(yīng)答

                {

                    int time=0;   //計(jì)數(shù)器

                    I2C_SDA_IN();  //表明是從機(jī)的SDA

                    I2C_SDA_H;

                    delay_us((1);

                    I2C_SCL_H;

                    delay_us(1);

                    while(GPIO_ReadInputDataBit(GPIO_I2C,I2CC_SDA))   //等待應(yīng)答信號

                    {

                         time++;

                         if(time>250)  //等待時(shí)間過長,產(chǎn)生停止信號,返回1,表示接收應(yīng)答失敗

                         {

                              I2C_Stop();

                              return 1;

                         }

                         //應(yīng)答成功,則SCL變低

                         I2C_SCL_L;

                         return 0;                       

                    }

                }

          (10)、主機(jī)發(fā)送一個(gè)字節(jié)的數(shù)據(jù),從高位開始發(fā)送。SCL位高電平的時(shí)候,數(shù)據(jù)必須保持穩(wěn)定,所以可以在SCL為低電平時(shí)組織數(shù)據(jù),SCL為高電平時(shí)發(fā)送或者接收數(shù)據(jù)

                    void send_Byte(u8 data)

                    {

                          I2C_SDA_OUT();

                         //數(shù)據(jù)準(zhǔn)備

                         I2C_SCL_L;

                         delay_us(2);

                         for(int i=0;i<8;i++)   //從高位開始一位一位地傳送

                         {

                              //發(fā)數(shù)據(jù)放到數(shù)據(jù)線上

                              if((data & 0x80)>0)  //當(dāng)前的最高位為1

                                   I2C_SDA_H;   //拉高數(shù)據(jù)線

                              else

                                   I2C_SDA_L;

                              data<<1;   //數(shù)據(jù)左移一位

                              //開始發(fā)送數(shù)據(jù)

                              I2C_SCL_H;

                              delay_us(2);

                              //上一個(gè)數(shù)據(jù)發(fā)送完畢,為下一個(gè)數(shù)據(jù)發(fā)送準(zhǔn)備

                              I2C_SCL_L;

                              delay_us(2);

                        }

                    }

          (11)、主機(jī)接收一個(gè)字節(jié)數(shù)據(jù)

                    u8 rev_Byte(u8 ack)

                    {

                         u8 rev_Data;  //接收到的數(shù)據(jù)

                         I2C_SDA_IN();

                         for(int i=0;i<8;i++)

                         {

                              //數(shù)據(jù)準(zhǔn)備 

                              I2C_SCL_L;

                              delay_us(2);

                              I2C_SCL_H;   //主機(jī)開始讀數(shù)據(jù),從機(jī)不能再改變數(shù)據(jù)了,即改變SDA的電平

                              if(GPIO_ReadInputDataBit(GPIO_I2C,I2CC_SDA) )  //接收到的是1

                                   rev_Data++;

                              rev_Data<<1;

                              delay_us(1);

                          }

                         if(ack==0)  //說明主機(jī)不需要給從機(jī)應(yīng)答

                              I2C_NACK();

                         else                 //主機(jī)需要給應(yīng)答

                              I2C_ACK();  

                         return rec_Data;

                     }

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多