找回密碼
         注冊會員
        搜索附件  
        MCU資訊論壇 附件中心 單片機論壇 AVR單片機論壇 TWI使用范例_AT24C02.rar

        熱門下載

        附件中心&附件聚合2.0
        For Discuz! X2.5 © hgcad.com

        TWI使用范例_AT24C02.rar

         

        TWI使用范例_AT24C02:
        本程序簡單的示范了如何使用ATMEGA16的TWI 讀寫AT24C02 IIC EEPROM
            TWI協議
              (即IIC協議,請認真參考IIC協議的內容,否則根本就不能掌握)
            一主多從的應用,M16作主機
              (M16做從機和多主多從的應用不多,請自行參考相關文檔)
        中斷模式
             (因為AVR的速度很高,而IIC的速度相對較低,
              采用查詢模式會長時間獨占CPU,令CPU的利用率明顯下降。
              特別是IIC速度受環境影響只能低速通訊時,對系統的實時性產生嚴重的影響。
              查詢模式可以參考其它文檔和軟件模擬IIC的文檔)
             AT24C02/04/08的操作特點

        出于簡化程序考慮,各種數據沒有對外輸出,學習時建議使用JTAG ICE硬件仿真器


        1. #include <avr/io.h>
        2. #include <avr/signal.h>
        3. #include <avr/interrupt.h>
        4. #include <avr/delay.h>
        5. //時鐘定為外部晶振7.3728MHz,F_CPU=7372800
        6. #include <compat/twi.h>
        7. //定義了各種模式下的狀態碼列表(TWSR已屏蔽預分頻位),本文后面附上中文描述
        8. //管腳定義
        9. #define  pinSCL    0     //PC0 SCL
        10. #define  pinSDA    1     //PC1 SDA
        11. //為保險起見,最好在SCL/SDA接上1~10K的外部上拉電阻到VCC。
        12. #define fSCL    100000    //TWI時鐘為100KHz
        13. //預分頻系數=1(TWPS=0)
        14. #if F_CPU < fSCL*36
        15.   #define TWBR_SET    10;     //TWBR必須大于等于10
        16. #else
        17.   #define TWBR_SET    (F_CPU/fSCL-16)/2; //計算TWBR值
        18. #endif
        19. #define TW_ACT    (1<<TWINT)|(1<<TWEN)|(1<<TWIE)
        20. //TWCR只能IN/OUT,直接賦值比邏輯運算(|= &=)更節省空間
        21. #define SLA_24CXX   0xA0    //24Cxx系列的廠商器件地址(高四位)
        22. #define ADDR_24C02   0x00
        23. // AT24C02的地址線A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01
        24. //TWI_操作狀態
        25. #define TW_BUSY    0
        26. #define TW_OK    1
        27. #define TW_FAIL    2
        28. //TWI_讀寫命令狀態
        29. #define OP_BUSY    0
        30. #define OP_RUN    1

        31. //TWI讀寫操作公共步驟
        32. #define ST_FAIL    0 //出錯狀態
        33. #define ST_START   1 //START狀態檢查
        34. #define ST_SLAW    2 //SLAW狀態檢查
        35. #define ST_WADDR   3 //ADDR狀態檢查
        36. //TWI讀操作步驟
        37. #define ST_RESTART   4 //RESTART狀態檢查
        38. #define ST_SLAR    5 //SLAR狀態檢查
        39. #define ST_RDATA   6 //讀取數據狀態檢查,循環n字節
        40. //TWI寫操作步驟
        41. #define ST_WDATA   7 //寫數據狀態檢查,循環n字節
        42. #define FAIL_MAX   20 //重試次數最大值

        43. //定義全局變量
        44. unsigned char ORGDATA[8]=
        45.     {0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04}; //原始數據
        46. unsigned char CMPDATA[8];      //比較數據
        47. unsigned char BUFFER[256];      //緩沖區,可以裝載整個AC24C02的數據
        48. struct str_TWI         //TWI數據結構
        49. {
        50.     volatile unsigned char STATUS;    //TWI_操作狀態
        51.     unsigned char SLA;      //從設備的器件地址
        52.     unsigned int ADDR;      //從設備的數據地址
        53.     unsigned char *pBUF;      //數據緩沖區指針
        54.     unsigned int DATALEN;     //數據長度
        55.     unsigned char STATE;      //TWI讀寫操作步驟
        56.     unsigned char FAILCNT;     //失敗重試次數
        57. };
        58. struct str_TWI strTWI;       //TWI的數據結構變量
        59. //仿真時在watch窗口,監控這些全局變量。

        60. //AT24C02的讀寫函數(包括隨機讀,連續讀,字節寫,頁寫)
        61. //根據sla的最低位決定(由中斷程序中判斷)
        62. //bit0=1 TW_READ  讀
        63. //bit0=0 TW_WRITE 寫
        64. //  sla   器件地址(不能搞錯)
        65. // addr  EEPROM地址(0~1023)
        66. // *ptr  讀寫數據緩沖區
        67. // len   讀數據長度(1~1024),寫數據長度(1 or 8 or 16)
        68. //  返回值  是否能執行當前操作
        69. unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len)
        70. {
        71.     unsigned char i;
        72.     if (strTWI.STATUS==TW_BUSY)
        73.     {//TWI忙,不能進行操作
        74.         return OP_BUSY;
        75.     }
        76.     strTWI.STATUS=TW_BUSY;
        77.     i=(addr>>8)<<1;
        78.     i&=0x06;         //考慮了24C04/08的EEPROM地址高位放在SLA里面
        79.     strTWI.SLA=sla+i;
        80.     strTWI.ADDR=addr;
        81.     strTWI.pBUF=ptr;
        82.     strTWI.DATALEN=len;
        83.     strTWI.STATE=ST_START;
        84.     strTWI.FAILCNT=0;
        85.     TWCR=(1<<TWSTA)|TW_ACT;      //啟動start信號
        86.     return OP_RUN;
        87. }
        88. /*
        89. TWI中斷函數
        90. 這個函數流程只是考慮了器件地址后有一個字節數據(命令)地址的IIC器件
        91. (大部分IIC接口器件都是這種類型,常見的例如AT24C01/02/04/08/16,DS1307,DS1721等)
        92. 對于有兩個字節數據地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),請稍作改動

        93. //根據strTWI.SLA的最低位決定
        94. //bit0=1 TW_READ  讀
        95. //bit0=0 TW_WRITE 寫
        96. 雖然中斷服務程序很長,但每次只執行一個 case,所以耗時并不長。
        97. */
        98. SIGNAL(SIG_2WIRE_SERIAL)
        99. {//IIC中斷
        100.     unsigned char action,state,status;
        101.     action=strTWI.SLA&TW_READ;     //取操作模式
        102.     state=strTWI.STATE;
        103.     status=TWSR&0xF8;       //屏蔽預分頻位
        104.     if ((status>=0x60)||(status==0x00))
        105.     {//總線錯誤或從機模式引發的中斷,不予處理
        106.         return;
        107.     }
        108.     switch(state)
        109.     {
        110.     case ST_START: //START狀態檢查
        111.         if(status==TW_START)
        112.         {//發送start信號成功
        113.             TWDR=strTWI.SLA&0xFE;    //發送器件地址寫SLAW
        114.             TWCR=TW_ACT;             //觸發下一步動作,同時清start發送標志
        115.         }
        116.         else
        117.         {//發送start信號出錯
        118.             state=ST_FAIL;
        119.         }
        120.         break;
        121.     case ST_SLAW: //SLAW狀態檢查
        122.         if(status==TW_MT_SLA_ACK)
        123.         {//發送器件地址成功
        124.             TWDR=strTWI.ADDR;     //發送eeprom地址
        125.             TWCR=TW_ACT;             //觸發下一步動作
        126.         }
        127.         else
        128.         {//發送器件地址出錯
        129.             state=ST_FAIL;
        130.         }
        131.         break;
        132.     case ST_WADDR: //ADDR狀態檢查
        133.         if(status==TW_MT_DATA_ACK)
        134.         {//發送eeprom地址成功
        135.             if (action==TW_READ)
        136.             {//讀操作模式
        137.                 TWCR=(1<<TWSTA)|TW_ACT;   //發送restart信號,下一步將跳到RESTART分支
        138.             }
        139.             else
        140.             {//寫操作模式
        141.                 TWDR=*strTWI.pBUF++;          //寫第一個字節
        142.                 strTWI.DATALEN--;
        143.                 state=ST_WDATA-1;    //下一步將跳到WDATA分支
        144.                 TWCR=TW_ACT;            //觸發下一步動作
        145.             }
        146.         }
        147.         else
        148.         {//發送eeprom地址出錯
        149.             state=ST_FAIL;
        150.         }
        151.         break;
        152.     case ST_RESTART: //RESTART狀態檢查,只有讀操作模式才能跳到這里
        153.         if(status==TW_REP_START)
        154.         {//發送restart信號成功
        155.             TWDR=strTWI.SLA;     //發器件地址讀SLAR
        156.             TWCR=TW_ACT;             //觸發下一步動作,同時清start發送標志
        157.         }
        158.         else
        159.         {//重發start信號出錯
        160.             state=ST_FAIL;
        161.         }
        162.         break;
        163.     case ST_SLAR: //SLAR狀態檢查,只有讀操作模式才能跳到這里
        164.         if(status==TW_MR_SLA_ACK)
        165.         {//發送器件地址成功
        166.             if (strTWI.DATALEN--)
        167.             {//多個數據
        168.                 TWCR=(1<<TWEA)|TW_ACT;   //設定ACK,觸發下一步動作
        169.             }
        170.             else
        171.             {//只有一個數據
        172.                 TWCR=TW_ACT;     //設定NAK,觸發下一步動作
        173.             }
        174.         }
        175.         else
        176.         {//發送器件地址出錯
        177.             state=ST_FAIL;
        178.         }
        179.         break;
        180.     case ST_RDATA: //讀取數據狀態檢查,只有讀操作模式才能跳到這里
        181.         state--;        //循環,直到讀完指定長度數據
        182.         if(status==TW_MR_DATA_ACK)
        183.         {//讀取數據成功,但不是最后一個數據
        184.             *strTWI.pBUF++=TWDR;
        185.             if (strTWI.DATALEN--)
        186.             {//還有多個數據
        187.                 TWCR=(1<<TWEA)|TW_ACT;   //設定ACK,觸發下一步動作
        188.             }
        189.             else
        190.             {//準備讀最后一個數據
        191.                 TWCR=TW_ACT;     //設定NAK,觸發下一步動作
        192.             }
        193.         }
        194.         else if(status==TW_MR_DATA_NACK)
        195.         {//已經讀完最后一個數據
        196.             *strTWI.pBUF++=TWDR;
        197.             TWCR=(1<<TWSTO)|TW_ACT;    //發送停止信號,不會再產生中斷了
        198.             strTWI.STATUS=TW_OK;
        199.         }
        200.         else
        201.         {//讀取數據出錯
        202.             state=ST_FAIL;
        203.         }
        204.         break;
        205.     case ST_WDATA: //寫數據狀態檢查,只有寫操作模式才能跳到這里
        206.         state--;        //循環,直到寫完指定長度數據
        207.         if(status==TW_MT_DATA_ACK)
        208.         {//寫數據成功
        209.             if (strTWI.DATALEN)
        210.             {//還要寫
        211.                 TWDR=*strTWI.pBUF++;
        212.                 strTWI.DATALEN--;
        213.                 TWCR=TW_ACT;            //觸發下一步動作
        214.             }
        215.             else
        216.             {//寫夠了
        217.                 TWCR=(1<<TWSTO)|TW_ACT;   //發送停止信號,不會再產生中斷了
        218.                 strTWI.STATUS=TW_OK;
        219.                 //啟動寫命令后需要10ms(最大)的編程時間才能真正的把數據記錄下來
        220.                 //編程期間器件不響應任何命令
        221.             }
        222.         }
        223.         else
        224.         {//寫數據失敗
        225.             state=ST_FAIL;
        226.         }
        227.         break;
        228.     default:
        229.         //錯誤狀態
        230.         state=ST_FAIL;
        231.         break;
        232.     }
        233.     if (state==ST_FAIL)
        234.     {//錯誤處理
        235.         strTWI.FAILCNT++;
        236.         if (strTWI.FAILCNT<FAIL_MAX)
        237.         {//重試次數未超出最大值,
        238.             TWCR=(1<<TWSTA)|TW_ACT;    //發生錯誤,啟動start信號
        239.         }
        240.         else
        241.         {//否則停止
        242.             TWCR=(1<<TWSTO)|TW_ACT;    //發送停止信號,不會再產生中斷了
        243.             strTWI.STATUS=TW_FAIL;
        244.         }
        245.     }
        246.     state++;
        247.     strTWI.STATE=state;       //保存狀態
        248. }

        249. int main(void)
        250. {
        251.     unsigned char i;
        252.     //上電默認DDRx=0x00,PORTx=0x00 輸入,無上拉電阻
        253.     PORTA=0xFF;         //不用的管腳使能內部上拉電阻。
        254.     PORTB=0xFF;
        255.     PORTC=0xFF;         //SCL,SDA使能了內部的10K上拉電阻
        256.     PORTD=0xFF;
        257.     //TWI初始化
        258.     TWSR=0x00;         //預分頻=0^4=1
        259.     TWBR=TWBR_SET;
        260.     TWAR=0x00;         //主機模式,該地址無效
        261.     TWCR=0x00;         //關閉TWI模塊
        262.     sei();          //使能全局中斷
        263.     strTWI.STATUS=TW_OK;
        264.     TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_WRITE,0x10,&ORGDATA[0],8);
        265.     //從0x10地址開始寫入8個字節數據
        266.     while(strTWI.STATUS==TW_BUSY);    //等待操作完成
        267.     if (strTWI.STATUS==TW_FAIL)
        268.     {
        269.         //操作失敗?
        270.     }
        271.     _delay_ms(10);        //延時等待編程完成
        272.     while(1)
        273.     {
        274.         i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x10,&CMPDATA[0],8);
        275.         //從0x10地址開始讀出8個字節數據
        276.         while(strTWI.STATUS==TW_BUSY);   //等待操作完成
        277.         //如果不加等待,則需要檢測返回值i才能知道當前操作是否執行了
        278.         // 0 OP_BUSY 之前的操作沒完成,沒執行當前操作
        279.         // 1 OP_RUN  當前操作執行中
        280.         if (strTWI.STATUS==TW_FAIL)
        281.         {
        282.             //操作失敗?
        283.         }
        284.         //讀取成功,對比ORGDATA和CMPDATA的數據
        285.         i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x00,&BUFFER[0],256);
        286.         //從0x00地址開始讀出256個字節數據(整個ATC24C02)
        287.         while(strTWI.STATUS==TW_BUSY);   //等待操作完成
        288.     };
        289. }
        復制代碼


        /*
        兩線串行接口總線定義
        兩線接口TWI很適合于典型的處理器應用。
        TWI協議允許系統設計者只用兩根雙向傳輸線就可以將128個不同的設備互連到一起。
        這兩根線一是時鐘SCL,一是數據SDA。外部硬件只需要兩個上拉電阻,每根線上一個。
        所有連接到總線上的設備都(必須)有自己的地址。
        注意:就是說不能有兩個相同地址的設備
        TWI協議解決了總線仲裁的問題。

        所有 TWI 兼容的器件的總線驅動都是漏極開路或集電極開路的。這樣就實現了對接口操作非常關鍵的線與功能。
        TWI器件輸出為"0”時,TWI總線會產生低電平。
        當所有的TWI器件輸出為三態時,總線會輸出高電平,允許上拉電阻將電壓拉高。
        注意:為保證所有的總線操作,凡是與TWI 總線連接的AVR 器件必須上電。

        與總線連接的器件數目受如下條件限制:
        總線電容要低于400pF,而且可以用7 位從機地址進行尋址。
        兩個不同的規范,一種是總線速度低于100 kHz,而另外一種是總線速度高達400 kHz。

        SCL和SDA引腳
        SCL與SDA為MCU的 TWI接口引腳。
        引腳的輸出驅動器包含一個波形斜率限制器以滿足TWI 規范。
        引腳的輸入部分包括尖峰抑制單元以去除小于50ns 的毛刺。
        當相應的端口設置為SCL與SDA引腳時,可以使能I/O口內部的10K上拉電阻,這樣可省掉外部的上拉電阻
        注意:如果要作高速通訊或者從機數量較多,最好還是外接合適的上拉電阻

        比特率發生器單元
        TWI工作于主機模式時,比特率發生器控制時鐘信號SCL的周期。
        具體由TWI狀態寄存器TWSR的預分頻系數以及比特率寄存器TWBR設定。
        當TWI工作在從機模式時,不需要對比特率或預分頻進行設定,但從機的CPU時鐘頻率必須大于TWI時鐘線SCL頻率的16倍。
        注意,從機可能會延長SCL 低電平的時間,從而降低TWI 總線的平均時鐘周期。
        SCL的頻率根據以下的公式產生:
          fSCL=fCPU/((16+2(TWBR)(4^TWPS))
        TWBR = TWI比特率寄存器的數值
        TWPS = TWI狀態寄存器預分頻的數值
        Note:TWI 工作在主機模式時,TWBR 值應該不小于10,否則主機會在SDA 與 SCL 產生錯誤輸出作為提示信號。
        問題出現于TWI 工作在主機模式下,向從機發送Start + SLA + R/W 的時候(不需要真的有從機與總線連接)。

        控制單元
        控制單元監聽TWI 總線,并根據 TWI 控制寄存器TWCR 的設置作出相應的響應。
        當TWI總線上產生需要應用程序干預處理的事件時,TWI 中斷標志位TWINT 置位。
        在下一個時鐘周期, TWI 狀態寄存器TWSR 被表示這個事件的狀態碼字所更新。
        在其它時間里,TWSR 的內容為一個表示無事件發生的特殊狀態字。
        一旦TWINT 標志位置"1”,時鐘線SCL 即被拉低,暫停TWI 總線上的數據傳輸,讓用戶程序處理事件。
        在下列狀況出現時, TWINT 標志位置位:
        ? 在TWI 傳送完START/REPEATED START 信號之后
        ? 在TWI 傳送完SLA+R/W 數據之后
        ? 在TWI 傳送完地址字節之后
        ? 在TWI 總線仲裁失敗之后
        ? 在TWI 被主機尋址之后( 廣播方式或從機地址匹配)
        ? 在TWI 接收到一個數據字節之后
        ? 作為從機工作時, TWI 接收到STOP 或REPEATED START 信號之后
        ? 由于非法的START 或STOP 信號造成總線錯誤時

        TWI 寄存器說明

        TWI 比特率寄存器- TWBR
        ? Bits 7..0 – TWI 比特率寄存器
          TWBR 為比特率發生器分頻因子。
          比特率發生器是一個分頻器,在主機模式下產生SCL時鐘頻率。
          比特率計算公式請見前面的[比特率發生器單元]
          
        TWI 控制寄存器- TWCR
        TWCR 用來控制TWI操作。
        它用來使能TWI,通過施加START到總線上來啟動主機訪問,產生接收器應答,產生STOP 狀態,以及在寫入數據到TWDR 寄存器時控制總線的暫停等。
        這個寄存器還可以給出在TWDR 無法訪問期間,試圖將數據寫入到TWDR 而引起的寫入沖突信息。
        ? Bit 7 – TWINT: TWI 中斷標志
          當TWI 完成當前工作,希望應用程序介入時TWINT 置位。
          若SREG 的I 標志以及TWCR寄存器的TWIE 標志也置位,則MCU 執行TWI 中斷例程。
          當TWINT 置位時, SCL信號的低電平被延長。
          TWINT 標志的清零必須通過軟件寫"1” 來完成。
          執行中斷時硬件不會自動將其改寫為"0”。
          要注意的是,只要這一位被清零,TWI 立即開始工作。
          因此,在清零TWINT 之前一定要首先完成對地址寄存器TWAR,狀態寄存器TWSR,以及數據寄存器TWDR 的訪問。
        ? Bit 6 – TWEA: 使能TWI 應答
          TWEA 標志控制應答脈沖的產生。
          若TWEA 置位,出現如下條件時接口發出ACK 脈沖:
          1. 器件的從機地址與主機發出的地址相符合
          2. TWAR 的TWGCE 置位時接收到廣播呼叫
          3. 在主機/ 從機接收模式下接收到一個字節的數據
          將TWEA 清零可以使器件暫時脫離總線。
          置位后器件重新恢復地址識別。
        ? Bit 5 – TWSTA: TWI START 狀態標志
          當CPU 希望自己成為總線上的主機時需要置位TWSTA。
          TWI 硬件檢測總線是否可用。
          若總線空閑,接口就在總線上產生START 狀態。
          若總線忙,接口就一直等待,直到檢測到一個STOP 狀態 ,然后產生START 以聲明自己希望成為主機。
          發送START之后軟件必須清零TWSTA。
        ? Bit 4 – TWSTO: TWI STOP 狀態標志
          在主機模式下,如果置位TWSTO,TWI 接口將在總線上產生STOP 狀態,然后TWSTO自動清零。
          在從機模式下,置位TWSTO 可以使接口從錯誤狀態恢復到未被尋址的狀態。
          此時總線上不會有STOP 狀態產生,但TWI 返回一個定義好的未被尋址的從機模式且釋放SCL 與SDA 為高阻態。
        ? Bit 3 – TWWC: TWI 寫碰撞標志
          當TWINT 為低時寫數據寄存器TWDR 將置位TWWC。
          當TWINT 為高時,每一次對TWDR 的寫訪問都將更新此標志。
        ? Bit 2 – TWEN: TWI 使能
          TWEN 位用于使能TWI操作與激活TWI接口。
          當TWEN位被寫為"1”時,TWI引腳將I/O引腳切換到SCL 與SDA 引腳,使能波形斜率限制器與尖峰濾波器。
          如果該位清零, TWI接口模塊將被關閉,所有TWI 傳輸將被終止。
        ? Bit 0 – TWIE: 使能TWI 中斷
          當SREG 的I 以及TWIE 置位時,只要TWINT 為"1”, TWI 中斷就激活。
          
        TWI 狀態寄存器- TWSR
        ? Bits 7..3 – TWS: TWI 狀態
          這5位用來反映TWI 邏輯和總線的狀態。
          不同的狀態代碼將會在后面的部分描述。
          注意從TWSR 讀出的值包括5 位狀態值與2 位預分頻值。
          檢測狀態位時設計者應屏蔽預分頻位為"0”。這使狀態檢測獨立于預分頻器設置。
        ? Bits 1..0 – TWPS: TWI 預分頻位
          這兩位可讀/ 寫,用于控制比特率預分頻因子。
          預分頻系數為4的n次方
          計算比特率的公式見前面的[比特率發生器單元]
          
        TWI 數據寄存器- TWDR
        在發送模式, TWDR 包含了要發送的字節;
        在接收模式, TWDR 包含了接收到的數據。
        當TWI 接口沒有進行移位工作(TWINT 置位) 時這個寄存器是可寫的。
        在第一次中斷發生之前用戶不能夠初始化數據寄存器。
        只要TWINT 置位,TWDR 的數據就是穩定的。
        在數據移出時,總線上的數據同時移入寄存器。
        TWDR 總是包含了總線上出現的最后一個字節,除非MCU 是從掉電或省電模式被TWI 中斷喚醒。此時TWDR 的內容沒有定義。
        總線仲裁失敗時,主機將切換為從機,但總線上出現的數據不會丟失。
        ACK 的處理由 TWI邏輯自動管理, CPU 不能直接訪問ACK。
        ? Bits 7..0 – TWD: TWI 數據寄存器
          根據狀態的不同,其內容為要發送的下一個字節,或是接收到的數據。

        TWI(從機) 地址寄存器-TWAR
        TWAR 的高7 位為從機地址。
        工作于從機模式時,TWI 將根據這個地址進行響應。
        主機模式不需要此地址。
        在多主機系統中, TWAR需要進行設置以便其他主機訪問自己。
        TWAR 的LSB 用于識別廣播地址 (0x00)。
        器件內有一個地址比較器。一旦接收到的地址和本機地址一致,芯片就請求中斷。
        ? Bits 7..1 – TWA: TWI 從機地址寄存器
          其值為從機地址。
        ? Bit 0 – TWGCE: 使能TWI 廣播識別
          置位后MCU 可以識別TWI 總線廣播。

        使用TWI
        AVR的TWI接口是面向字節和基于中斷的。
        所有的總線事件,如接收到一個字節或發送了一個START 信號等,都會產生一個TWI 中斷。
        由于TWI 接口是基于中斷的,因此TWI接口在字節發送和接收過程中,不需要應用程序的干預。
        TWCR寄存器的TWI中斷允許位[TWIE]和全局中斷允許位[I]一起決定了應用程序是否響應TWINT標志位產生的中斷請求。
        如果TWIE 被清零,應用程序只能采用輪詢TWINT 標志位的方法來檢測TWI 總線狀態。
        當TWINT 標志位置"1” 時,表示TWI 接口完成了當前的操作,等待應用程序的響應。
        在這種情況下,TWI 狀態寄存器TWSR 包含了表明當前TWI 總線狀態的值。
        應用程序可以讀取TWCR 的狀態碼,判別此時的狀態是否正確,并通過設置TWCR 與TWDR 寄存器,決定在下一個TWI 總線周期TWI 接口應該如何工作。

        各種模式下的狀態碼列表(TWSR已屏蔽預分頻位)
        twi.h里面有定義,現附上中文描述

        主機發送狀態碼
        #define TW_START    0x08 //START已發送
        #define TW_REP_START   0x10 //重復START已發送
        #define TW_MT_SLA_ACK   0x18 //SLA+W 已發送收到ACK
        #define TW_MT_SLA_NACK   0x20 //SLA+W 已發送接收到NOT ACK
        #define TW_MT_DATA_ACK   0x28 //數據已發送接收到ACK
        #define TW_MT_DATA_NACK   0x30 //數據已發送接收到NOT ACK
        #define TW_MT_ARB_LOST   0x38 //SLA+W 或數據的仲裁失敗


        主機接收狀態碼
        //#define TW_START    0x08 //START已發送
        //#define TW_REP_START   0x10 //重復START已發送
        #define TW_MR_ARB_LOST   0x38 //SLA+R 或NOT ACK 的仲裁失敗
        #define TW_MR_SLA_ACK   0x40 //SLA+R 已發送接收到ACK
        #define TW_MR_SLA_NACK   0x48 //SLA+R 已發送接收到NOT ACK
        #define TW_MR_DATA_ACK   0x50 //接收到數據ACK 已返回
        #define TW_MR_DATA_NACK   0x58 //接收到數據NOT ACK已返回

        從機接收狀態碼
        #define TW_SR_SLA_ACK   0x60 //自己的SLA+W 已經被接收ACK已返回
        #define TW_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W 作為主機的仲裁失敗;自己的SLA+W 已經被接收ACK 已返回
        #define TW_SR_GCALL_ACK   0x70 //接收到廣播地址ACK 已返回
        #define TW_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W 作為主機的仲裁失敗;接收到廣播地址ACK已返回
        #define TW_SR_DATA_ACK   0x80 //以前以自己的SLA+W被尋址;數據已經被接收ACK已返回
        #define TW_SR_DATA_NACK   0x88 //以前以自己的SLA+W被尋址;數據已經被接收NOT ACK已返回
        #define TW_SR_GCALL_DATA_ACK 0x90 //以前以廣播方式被尋址;數據已經被接收ACK已返回
        #define TW_SR_GCALL_DATA_NACK 0x98 //以前以廣播方式被尋址;數據已經被接收NOT ACK已返回
        #define TW_SR_STOP    0xA0 //在以從機工作時接收到STOP或重復START


        從發送狀態碼
        #define TW_ST_SLA_ACK   0xA8 //自己的SLA+R 已經被接收ACK 已返回
        #define TW_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W 作為主機的仲裁失敗;自己的SLA+R 已經被接收ACK 已返回
        #define TW_ST_DATA_ACK   0xB8 //TWDR 里數據已經發送接收到ACK
        #define TW_ST_DATA_NACK   0xC0 //TWDR 里數據已經發送接收到NOT ACK
        #define TW_ST_LAST_DATA   0xC8 //TWDR 的一字節數據已經發送(TWAE = “0”);接收到ACK


        其它狀態碼
        #define TW_NO_INFO    0xF8 //沒有相關的狀態信息;TWINT = “0”
        #define TW_BUS_ERROR   0x00 //由于非法的START 或STOP 引起的總線錯誤


        AT24C02/04/08 IIC接口EEPROM的特點
        (不同公司的24系列EEPROM特性有部分不同,請參考數據手冊)
        1 AT24C02/04/08 是一個2K/4K/8K位串行CMOS E2PROM 內部含有256/512/1024 個8位字節
        2 AT24C02有一個8 字節頁寫緩沖器,AT24C04/08/16 有一個16字節頁寫緩沖器
        3 通過器件地址輸入端A0,A1,A2可以實現將最多
          8個24C02器件
          4個24C04器件
          2個24C08器件
          同時連接到總線上
        4 寫操作
          1 字節寫
          2 頁寫  AT24C02是8字節/頁 AT24C04/08是16字節/頁
            注意:頁寫的地址只在當前頁自動累加,頁地址范圍內循環。
          啟動寫命令后需要10ms(最大)的編程時間才能真正的把數據記錄下來,編程期間器件不響應任何命令
        5 讀操作
          1 立即地址讀  地址自動累加,即為上次讀/寫操作地址+1(本程序不支持該操作)
          2 隨機讀     指定地址讀一個字節
          3 連續讀     連續讀操作可通過立即讀或隨機讀操作啟動,由主機發出NAK和STOP來停止讀操作
             讀操作時地址計數器在AT24C02/04/08整個地址內增加,這樣整個寄存器區域在可在一個讀操作內全部讀出
             循環讀取,讀到最后一個地址后,從第一個地址繼續開始讀
        6  寫保護功能,由WP引腳控制,WP=VCC時,24C02的高1K位,24C04的高2K位,24C08的全部8K位都變成只讀,不能寫入
        */

        QQ|手機版|MCU資訊論壇 ( 京ICP備18035221號-2 )|網站地圖

        GMT+8, 2025-3-16 21:38 , Processed in 0.024728 second(s), 8 queries , Redis On.

        Powered by Discuz! X3.5

        © 2001-2024 Discuz! Team.

        返回頂部
        精品国精品国产| 99在线热播精品免费99热| 日产欧美国产日韩精品| 欧洲精品色在线观看| 99精品人妻无码专区在线视频区| 久久亚洲国产欧洲精品一| 国产三级精品三级| 四虎在线网址入口2022| 国产精品久久久久久吹潮| 99久久99久久精品国产片果冻| 久久精品综合一区二区三区| 亚洲欧美精品AAAAAA片| 91老司机深夜福利精品视频在线观看 | 精品亚洲综合在线第一区| 国产麻豆精品入口在线观看| 最好韩国日本高清免费| 国产成人精品高清在线观看93| 国产精品一香蕉国产线看观看| www.国产自拍| 在线精品国产一区二区| 亚洲欧美日韩精品久久亚洲区 | 无码精品人妻一区二区三区免费看 | 中文字幕久久精品无码| 精品国产欧美另类一区| 日本精品视频在线观看| 久久亚洲精品无码AV红樱桃| 国产L精品国产亚洲区久久| 日本一区二区精品| 欧美成人精品一区二区三区| 日本精品视频在线观看| 国产三级精品三级在线专区1| 精品第一国产综合精品蜜芽| 久久久久久国产精品无码超碰| 国产精品va久久久久久久| 亚洲日韩精品一区二区三区| 99精品国产成人一区二区| 亚洲精品乱码久久久久66| 国产成人精品亚洲精品| 亚洲国产精品高清久久久| 国产欧美日韩精品专区| 精品视频一区二区三三区四区|