<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 用Proteus學(xué)習(xí)51單片機(jī)之I2C(IIC)總線

          用Proteus學(xué)習(xí)51單片機(jī)之I2C(IIC)總線

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

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

          本文引用地址:http://www.ex-cimer.com/article/201611/318160.htm

          接下來說一下I2C總線的數(shù)據(jù)有效性。I2C總線進(jìn)行數(shù)據(jù)傳送時(shí),要求SCL為高電平時(shí),SDA上的數(shù)據(jù)必需保持穩(wěn)定,換言之,當(dāng)SCL為高電平時(shí),SDA的電平不能變換,只有當(dāng)SCL為低電平時(shí),SDA的電平才能變。

          I2C總線通信時(shí),需要遵照一定的協(xié)議,以下為一次通信過程:

          1. 由主機(jī)發(fā)送起始信號(hào),啟動(dòng)I2C總線。時(shí)序?yàn)?,在SCL為高電平期間,SDA出現(xiàn)一個(gè)下降沿。
          2. 主機(jī)發(fā)送尋址信號(hào),即告訴特定的設(shè)備,接下來的命令是發(fā)給它的。地址分為7位和10位,以7位為例,高7位為設(shè)備地址,最低位表示讀或?qū)懀?表示讀,0表示寫。
          3. 應(yīng)答信號(hào),I2C協(xié)議規(guī)定,每傳送一個(gè)字節(jié)數(shù)據(jù)(包括地址及命令)后,都要有一個(gè)接收設(shè)備返回的應(yīng)答信號(hào),以確定信號(hào)是否被接收設(shè)備正確接收到了。其時(shí)序?yàn)椋赟CL信號(hào)為高電平期間,接收設(shè)備把SDA電平拉低。
          4. 數(shù)據(jù)傳輸,當(dāng)主機(jī)發(fā)送發(fā)址并收到應(yīng)答后,就可以發(fā)送數(shù)據(jù)了,但是發(fā)送數(shù)據(jù)只能每次發(fā)送一位,并且每發(fā)送一位后都需要收到接收機(jī)的應(yīng)答?;蛑鳈C(jī)為接收設(shè)備時(shí),主機(jī)對(duì)最后一個(gè)字節(jié)不應(yīng)答,表示向發(fā)送設(shè)備說,數(shù)據(jù)傳送結(jié)束。
          5. 發(fā)送停止信號(hào),在全部數(shù)據(jù)傳送完畢后,主機(jī)發(fā)送停止信號(hào),時(shí)序?yàn)?,在SCL為高電平期間,SDA上產(chǎn)生一個(gè)上升沿。

            前面講到,I2C協(xié)議要求數(shù)據(jù)的發(fā)送,要求SCL為低電平時(shí),SDA才能變換,看一下上面的時(shí)序,可以看到,命令都是SCL為高電平時(shí)對(duì)SDA的操作,而發(fā)送數(shù)據(jù)則是SCL為低電平時(shí)對(duì)SDA操作。

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

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

            首先是寫數(shù)據(jù),時(shí)序如下:

            1.發(fā)送啟動(dòng)信號(hào)

            2.發(fā)送一個(gè)控制字(即芯片的地址)——等待應(yīng)答

            3.發(fā)送要寫的芯片內(nèi)存儲(chǔ)單元地址——等待應(yīng)答

            4.發(fā)送要寫入的數(shù)據(jù)——等待應(yīng)答

            5.停止信號(hào)

            接下來是讀數(shù)據(jù)的時(shí)序:

            1.發(fā)送啟動(dòng)信號(hào)

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

            3.發(fā)送要讀取的芯片內(nèi)存儲(chǔ)單元地址——等待應(yīng)答

            4.再發(fā)送一個(gè)地址信號(hào)(同第2步,但是最低位為1,即讀操作)——等待應(yīng)答

            5.按每次一位,讀取數(shù)據(jù)

            6.停止信號(hào)

            I2C協(xié)議看起來相對(duì)復(fù)雜,但是在單片機(jī)里面實(shí)現(xiàn),其實(shí)就是用兩個(gè)IO口,來模擬SCL和SDA的電平變化。以啟動(dòng)I2C為例(在SCL為高電平時(shí),SDA發(fā)送一個(gè)下降沿),代碼如下:

            SDA = 1;//把SDA先置高電平,待會(huì)好出現(xiàn)下降沿

            delay();

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

            delay();

            SDA=0;//電平從1到0,出現(xiàn)一個(gè)下降沿

            delay();

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

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

            結(jié)果如下:

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

            它把每一步都標(biāo)的清清楚楚,特別說明一下的是,幾個(gè)字符是有特殊意義的,如:

            S表是I2C總線-“開始”
            A---應(yīng)答
            p---停止
            Sr--重啟動(dòng)

            所以第一行S A0 A 01 A 48 A p表示的意思是:啟動(dòng)I2C總線,發(fā)送數(shù)據(jù)A0(其實(shí)是芯片的地址),芯片應(yīng)答,發(fā)送數(shù)據(jù)01(就是寫入的地址),芯片應(yīng)答,發(fā)送數(shù)據(jù)48(就是保存的數(shù)據(jù)),芯片應(yīng)答,結(jié)束??纯矗欠窈颓懊嬲f的流程一致?

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

            PS:在調(diào)試時(shí)遇到的一個(gè)問題,可能大家也會(huì)碰到,記錄一下。

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

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

            {

            save(‘a’)

            read(‘a’)

            }

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

            save(‘a’)

            save(‘b’)

            save(‘c’)

            read(1)

            read(2)

            read(3)

            這時(shí)出現(xiàn)了一個(gè)問題,第一個(gè)能正常保存,第2個(gè)就不能保存,第3個(gè)又能保存,讓我很是頭疼。

            后來分析了一下,前后兩種代碼的區(qū)別,就在于,第一種形式,保存后,又進(jìn)行讀取,相當(dāng)于保存后進(jìn)行了一定的延時(shí),而第二種形式一直在保存,保存后沒有延時(shí),后來在第二種形式的save后,加上了延時(shí),就一切正常了。

            源代碼下載:點(diǎn)擊下載

            IIC總線技術(shù)

              IIC總線是微電子通信控制領(lǐng)域中被廣泛采用的一種總線標(biāo)準(zhǔn),具有接口線少,控制方式簡單、器件封裝外形小、通信速率高等特點(diǎn)。它僅通過兩根線SDA和SCL即可實(shí)現(xiàn)完善的全雙工同步數(shù)據(jù)傳送,能夠十分方便地構(gòu)成多主機(jī)系統(tǒng)和外同器件擴(kuò)展系統(tǒng)。

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

             

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

             



            關(guān)鍵詞: Proteus51單片機(jī)I2

            評(píng)論


            技術(shù)專區(qū)

            關(guān)閉
            看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();