新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 用Proteus學習51單片機之I2C(IIC)總線

        用Proteus學習51單片機之I2C(IIC)總線

        作者: 時間:2016-11-19 來源:網絡 收藏
        在學習單片機的過程中,我常有這樣的煩惱:隨隨便便一個芯片,少則占用三五個IO口,一般的就占用8個,稍微想用多一點芯片吧,老覺得IO口不夠用。學串口的時候覺得串口是個好東西,連兩條線就夠了,現在學到I2C,覺得這也是一個非常好的東西,也是兩條線,還能給每個總線上的設備設立地址,簡直就是一個小網絡了。

        I2C總線使用兩條線,一條是時鐘線,稱為SCL,一條是數據線,稱為SDA,各個設備就并在總線上,每一個總線上的設備都有一個自己的地址,主機在操作設備的時候,都會先發送一個地址碼,告訴被操作機,接下來的命令由它接收。

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

        接下來說一下I2C總線的數據有效性。I2C總線進行數據傳送時,要求SCL為高電平時,SDA上的數據必需保持穩定,換言之,當SCL為高電平時,SDA的電平不能變換,只有當SCL為低電平時,SDA的電平才能變。

        I2C總線通信時,需要遵照一定的協議,以下為一次通信過程:

        1. 由主機發送起始信號,啟動I2C總線。時序為,在SCL為高電平期間,SDA出現一個下降沿。
        2. 主機發送尋址信號,即告訴特定的設備,接下來的命令是發給它的。地址分為7位和10位,以7位為例,高7位為設備地址,最低位表示讀或寫,1表示讀,0表示寫。
        3. 應答信號,I2C協議規定,每傳送一個字節數據(包括地址及命令)后,都要有一個接收設備返回的應答信號,以確定信號是否被接收設備正確接收到了。其時序為,在SCL信號為高電平期間,接收設備把SDA電平拉低。
        4. 數據傳輸,當主機發送發址并收到應答后,就可以發送數據了,但是發送數據只能每次發送一位,并且每發送一位后都需要收到接收機的應答。或主機為接收設備時,主機對最后一個字節不應答,表示向發送設備說,數據傳送結束。
        5. 發送停止信號,在全部數據傳送完畢后,主機發送停止信號,時序為,在SCL為高電平期間,SDA上產生一個上升沿。

          前面講到,I2C協議要求數據的發送,要求SCL為低電平時,SDA才能變換,看一下上面的時序,可以看到,命令都是SCL為高電平時對SDA的操作,而發送數據則是SCL為低電平時對SDA操作。

          這次拿來做實驗的是AT24C02存儲芯片,在Proteus里面,它叫24C02C(或者24C02B),是一個2K bit的I2C總線的EEPROM存儲器,換成電腦上常用的KB也就是256KB,EEPROM表示它保存了以后不用加電池,也能保持數據完好。實驗的做法是,先把數據保存到芯片中,然后再讀出來,顯示到1602液晶上。

          上面介紹了I2C總線的協議格式,即發送一個命令的格式,但是對于每一個設備來說,要操作它,是需要很多命令的,AT24C02的操作則主要是讀和寫,它分為頁讀寫(即一次讀寫一大片)和字讀寫(一次讀寫一個字節)兩種方式,初學么,只使用字讀寫方式,下面記錄一下讀寫的時序。

          首先是寫數據,時序如下:

          1.發送啟動信號

          2.發送一個控制字(即芯片的地址)——等待應答

          3.發送要寫的芯片內存儲單元地址——等待應答

          4.發送要寫入的數據——等待應答

          5.停止信號

          接下來是讀數據的時序:

          1.發送啟動信號

          2.發送一個控制字(即芯片的地址,最低位為0即寫操作)——等待應答

          3.發送要讀取的芯片內存儲單元地址——等待應答

          4.再發送一個地址信號(同第2步,但是最低位為1,即讀操作)——等待應答

          5.按每次一位,讀取數據

          6.停止信號

          I2C協議看起來相對復雜,但是在單片機里面實現,其實就是用兩個IO口,來模擬SCL和SDA的電平變化。以啟動I2C為例(在SCL為高電平時,SDA發送一個下降沿),代碼如下:

          SDA = 1;//把SDA先置高電平,待會好出現下降沿

          delay();

          SCL = 1;//SCL要晚于SDA設置,否則容易和其他命令混淆

          delay();

          SDA=0;//電平從1到0,出現一個下降沿

          delay();

          ---------------------------------------------------------------------

          Proteus電路圖如下,記得要在總線的兩條線上,接上拉電阻(10K即可)

          結果如下:

          這里還得說一下I2C DEBUGGER這個虛擬儀器,真的是挺好用的,把它接在總線上后,它會把每一個命令都顯示出來,并把操作屬于哪一種操作都標識出來,以我往芯片存一個字符“H”為例:

          它把每一步都標的清清楚楚,特別說明一下的是,幾個字符是有特殊意義的,如:

          S表是I2C總線-“開始”
          A---應答
          p---停止
          Sr--重啟動

          所以第一行S A0 A 01 A 48 A p表示的意思是:啟動I2C總線,發送數據A0(其實是芯片的地址),芯片應答,發送數據01(就是寫入的地址),芯片應答,發送數據48(就是保存的數據),芯片應答,結束。看看,是否和前面說的流程一致?

          程序這里不貼了,下載里都有,里面有詳細的注釋。

          PS:在調試時遇到的一個問題,可能大家也會碰到,記錄一下。

          我本來是循環著往芯片里面寫數據,然后讀出來,顯示到液晶上,這時讀寫都正常,形式如下:

          for(i=0;i<字符串長度;i++)

          {

          save(‘a’)

          read(‘a’)

          }

          后來我為了試驗多顯示幾個字符,換了種方式,換成一次把所有數據都保存進去,再讀出來,變成下面的形式(偽代碼):

          save(‘a’)

          save(‘b’)

          save(‘c’)

          read(1)

          read(2)

          read(3)

          這時出現了一個問題,第一個能正常保存,第2個就不能保存,第3個又能保存,讓我很是頭疼。

          后來分析了一下,前后兩種代碼的區別,就在于,第一種形式,保存后,又進行讀取,相當于保存后進行了一定的延時,而第二種形式一直在保存,保存后沒有延時,后來在第二種形式的save后,加上了延時,就一切正常了。

          源代碼下載:點擊下載

          IIC總線技術

            IIC總線是微電子通信控制領域中被廣泛采用的一種總線標準,具有接口線少,控制方式簡單、器件封裝外形小、通信速率高等特點。它僅通過兩根線SDA和SCL即可實現完善的全雙工同步數據傳送,能夠十分方便地構成多主機系統和外同器件擴展系統。

            IIC總線數據傳輸只有任總線處于空閑狀態時(SCL和SDA必須保證為高電平)才啟動。IIC總線協議定義數據傳輸時序如圖2所示,起始條件為當SCL為高電平時,SDA由高電平向低電平跳變,數據開始傳輸;結束條件為當SCL為低電平時,SDA由低電平向高電平跳變,數據傳輸結束。傳輸過程中,當SCL高時,SDA必須始終保持穩定狀態,此時出現任何跳變都被認為是起始或停止條件,只有當SCL為低電平的時候才允許SDA上的數據改變。

           

            IIC總線上的數據格式如圖3所示,由起始位(S)、從機地址碼、讀寫控制位(R/W)、應答位(A)、數據和停止位(P)等組成。通信啟動時,主器件先發送啟動信號和從機地址,總線上每個器件都有自己的唯一地址,與地址與某一從器件相匹配時,該從器件發一應答位,主器件則認為尋址成功,然后根據R/W位確定的數據傳送方向進行數據傳輸。若主器件長時間收不到應答位,則認為超時,放棄本次數據傳輸。通信停止時,主機發送一個停止信號。

           



          關鍵詞: Proteus51單片機I2

          評論


          技術專區

          關閉
          主站蜘蛛池模板: 烟台市| 长沙县| 自治县| 新化县| 惠水县| 亳州市| 大同县| 呈贡县| 紫云| 鹿邑县| 小金县| 朝阳县| 宁阳县| 平塘县| 建水县| 晴隆县| 乌鲁木齐县| 长汀县| 靖西县| 安康市| 始兴县| 平昌县| 连州市| 阿克陶县| 威宁| 沂南县| 扎鲁特旗| 奈曼旗| 广元市| 汉源县| 北票市| 华蓥市| 新干县| 柳州市| 太保市| 黑龙江省| 蒙自县| 阿图什市| 长乐市| 丽水市| 聊城市|