色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > AVR TWI讀寫讀寫范例

          AVR TWI讀寫讀寫范例

          作者: 時間:2016-11-13 來源:網(wǎng)絡 收藏
          /***********************************************

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

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

          本文引用地址:http://cafeforensic.com/article/201611/316201.htm

          #include <avr/io.h>
          #include
          #include interrupt.h>
          #include
          //時鐘定為外部晶振7.3728MHz,F_CPU=7372800
          #include
          //定義了各種模式下的狀態(tài)碼列表(TWSR已屏蔽預分頻位),本文后面附上中文描述

          //管腳定義
          #define pinSCL0//PC0 SCL
          #define pinSDA1//PC1 SDA
          //為保險起見,最好在SCL/SDA接上1~10K的外部上拉電阻到VCC。

          #define fSCL100000//TWI時鐘為100KHz
          //預分頻系數(shù)=1(TWPS=0)
          #if F_CPU < fSCL*36
          #define TWBR_SET 10;//TWBR必須大于等于10
          #else
          #define TWBR_SET (F_CPU/fSCL-16)/2;//計算TWBR值
          #endif

          #define TW_ACT(1<//TWCR只能IN/OUT,直接賦值比邏輯運算(|= &=)更節(jié)省空間

          #define SLA_24CXX0xA0//24Cxx系列的廠商器件地址(高四位)
          #define ADDR_24C020x00
          // AT24C02的地址線A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01

          //TWI_操作狀態(tài)
          #define TW_BUSY0
          #define TW_OK1
          #define TW_FAIL2
          //TWI_讀寫命令狀態(tài)
          #define OP_BUSY0
          #define OP_RUN1


          //TWI讀寫操作公共步驟
          #define ST_FAIL0//出錯狀態(tài)
          #define ST_START1//START狀態(tài)檢查
          #define ST_SLAW2//SLAW狀態(tài)檢查
          #define ST_WADDR3//ADDR狀態(tài)檢查
          //TWI讀操作步驟
          #define ST_RESTART4//RESTART狀態(tài)檢查
          #define ST_SLAR5//SLAR狀態(tài)檢查
          #define ST_RDATA6//讀取數(shù)據(jù)狀態(tài)檢查,循環(huán)n字節(jié)
          //TWI寫操作步驟
          #define ST_WDATA7//寫數(shù)據(jù)狀態(tài)檢查,循環(huán)n字節(jié)

          #define FAIL_MAX20//重試次數(shù)最大值


          //定義全局變量
          unsigned char ORGDATA[8]=
          {0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04};//原始數(shù)據(jù)
          unsigned char CMPDATA[8];//比較數(shù)據(jù)
          unsigned char BUFFER[256];//緩沖區(qū),可以裝載整個AC24C02的數(shù)據(jù)

          struct str_TWI//TWI數(shù)據(jù)結(jié)構(gòu)
          {
          volatile unsigned charSTATUS;//TWI_操作狀態(tài)
          unsigned charSLA;//從設備的器件地址
          unsigned intADDR;//從設備的數(shù)據(jù)地址
          unsigned char*pBUF;//數(shù)據(jù)緩沖區(qū)指針
          unsigned intDATALEN;//數(shù)據(jù)長度
          unsigned charSTATE;//TWI讀寫操作步驟
          unsigned charFAILCNT;//失敗重試次數(shù)
          };

          struct str_TWI strTWI;//TWI的數(shù)據(jù)結(jié)構(gòu)變量

          //仿真時在watch窗口,監(jiān)控這些全局變量。


          //AT24C02的讀寫函數(shù)(包括隨機讀,連續(xù)讀,字節(jié)寫,頁寫)
          //根據(jù)sla的最低位決定(由中斷程序中判斷)
          //bit0=1 TW_READ 讀
          //bit0=0 TW_WRITE 寫
          // sla器件地址(不能搞錯)
          //addrEEPROM地址(0~1023)
          //*ptr讀寫數(shù)據(jù)緩沖區(qū)
          //len讀數(shù)據(jù)長度(1~1024),寫數(shù)據(jù)長度(1 or 8 or 16)
          // 返回值是否能執(zhí)行當前操作
          unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len)
          {
          unsigned char i;
          if (strTWI.STATUS==TW_BUSY)
          {//TWI忙,不能進行操作
          return OP_BUSY;
          }
          strTWI.STATUS=TW_BUSY;
          i=(addr>>8)<<1;
          i&=0x06;//考慮了24C04/08的EEPROM地址高位放在SLA里面
          strTWI.SLA=sla+i;
          strTWI.ADDR=addr;
          strTWI.pBUF=ptr;
          strTWI.DATALEN=len;
          strTWI.STATE=ST_START;
          strTWI.FAILCNT=0;
          TWCR=(1< return OP_RUN;
          }

          /*
          TWI中斷函數(shù)
          這個函數(shù)流程只是考慮了器件地址后有一個字節(jié)數(shù)據(jù)(命令)地址的IIC器件
          (大部分IIC接口器件都是這種類型,常見的例如AT24C01/02/04/08/16,DS1307,DS1721等)
          對于有兩個字節(jié)數(shù)據(jù)地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),請稍作改動

          //根據(jù)strTWI.SLA的最低位決定
          //bit0=1 TW_READ 讀
          //bit0=0 TW_WRITE 寫

          雖然中斷服務程序很長,但每次只執(zhí)行一個 case,所以耗時并不長。
          */
          SIGNAL(SIG_2WIRE_SERIAL)
          {//IIC中斷
          unsigned char action,state,status;
          action=strTWI.SLA&TW_READ;//取操作模式
          state=strTWI.STATE;
          status=TWSR&0xF8;//屏蔽預分頻位
          if ((status>=0x60)||(status==0x00))
          {//總線錯誤或從機模式引發(fā)的中斷,不予處理
          return;
          }
          switch(state)
          {
          case ST_START://START狀態(tài)檢查
          if(status==TW_START)
          {//發(fā)送start信號成功
          TWDR=strTWI.SLA&0xFE;//發(fā)送器件地址寫SLAW
          TWCR=TW_ACT; //觸發(fā)下一步動作,同時清start發(fā)送標志
          }
          else
          {//發(fā)送start信號出錯
          state=ST_FAIL;
          }
          break;
          case ST_SLAW://SLAW狀態(tài)檢查
          if(status==TW_MT_SLA_ACK)
          {//發(fā)送器件地址成功
          TWDR=strTWI.ADDR;//發(fā)送eeprom地址
          TWCR=TW_ACT; //觸發(fā)下一步動作
          }
          else
          {//發(fā)送器件地址出錯
          state=ST_FAIL;
          }
          break;
          case ST_WADDR://ADDR狀態(tài)檢查
          if(status==TW_MT_DATA_ACK)
          {//發(fā)送eeprom地址成功
          if (action==TW_READ)
          {//讀操作模式
          TWCR=(1< }
          else
          {//寫操作模式
          TWDR=*strTWI.pBUF++; //寫第一個字節(jié)
          strTWI.DATALEN--;
          state=ST_WDATA-1;//下一步將跳到WDATA分支
          TWCR=TW_ACT; //觸發(fā)下一步動作
          }
          }
          else
          {//發(fā)送eeprom地址出錯
          state=ST_FAIL;
          }
          break;
          case ST_RESTART://RESTART狀態(tài)檢查,只有讀操作模式才能跳到這里
          if(status==TW_REP_START)
          {//發(fā)送restart信號成功
          TWDR=strTWI.SLA;//發(fā)器件地址讀SLAR
          TWCR=TW_ACT; //觸發(fā)下一步動作,同時清start發(fā)送標志
          }
          else
          {//重發(fā)start信號出錯
          state=ST_FAIL;
          }
          break;
          case ST_SLAR://SLAR狀態(tài)檢查,只有讀操作模式才能跳到這里
          if(status==TW_MR_SLA_ACK)
          {//發(fā)送器件地址成功
          if (strTWI.DATALEN--)
          {//多個數(shù)據(jù)
          TWCR=(1< }
          else
          {//只有一個數(shù)據(jù)
          TWCR=TW_ACT;//設定NAK,觸發(fā)下一步動作
          }
          }
          else
          {//發(fā)送器件地址出錯
          state=ST_FAIL;
          }
          break;
          case ST_RDATA://讀取數(shù)據(jù)狀態(tài)檢查,只有讀操作模式才能跳到這里
          state--;//循環(huán),直到讀完指定長度數(shù)據(jù)
          if(status==TW_MR_DATA_ACK)
          {//讀取數(shù)據(jù)成功,但不是最后一個數(shù)據(jù)
          *strTWI.pBUF++=TWDR;
          if (strTWI.DATALEN--)
          {//還有多個數(shù)據(jù)
          TWCR=(1< }
          else
          {//準備讀最后一個數(shù)據(jù)
          TWCR=TW_ACT;//設定NAK,觸發(fā)下一步動作
          }
          }
          else if(status==TW_MR_DATA_NACK)
          {//已經(jīng)讀完最后一個數(shù)據(jù)
          *strTWI.pBUF++=TWDR;
          TWCR=(1< strTWI.STATUS=TW_OK;
          }
          else
          {//讀取數(shù)據(jù)出錯
          state=ST_FAIL;
          }
          break;
          case ST_WDATA://寫數(shù)據(jù)狀態(tài)檢查,只有寫操作模式才能跳到這里
          state--;//循環(huán),直到寫完指定長度數(shù)據(jù)
          if(status==TW_MT_DATA_ACK)
          {//寫數(shù)據(jù)成功
          if (strTWI.DATALEN)
          {//還要寫
          TWDR=*strTWI.pBUF++;
          strTWI.DATALEN--;
          TWCR=TW_ACT; //觸發(fā)下一步動作
          }
          else
          {//寫夠了
          TWCR=(1< strTWI.STATUS=TW_OK;
          //啟動寫命令后需要10ms(最大)的編程時間才能真正的把數(shù)據(jù)記錄下來
          //編程期間器件不響應任何命令
          }
          }
          else
          {//寫數(shù)據(jù)失敗
          state=ST_FAIL;
          }
          break;
          default:
          //錯誤狀態(tài)
          state=ST_FAIL;
          break;
          }

          if (state==ST_FAIL)
          {//錯誤處理
          strTWI.FAILCNT++;
          if (strTWI.FAILCNT {//重試次數(shù)未超出最大值,
          TWCR=(1< }
          else
          {//否則停止
          TWCR=(1< strTWI.STATUS=TW_FAIL;
          }
          }
          state++;
          strTWI.STATE=state;//保存狀態(tài)
          }

          int main(void)
          {
          unsigned char i;
          //上電默認DDRx=0x00,PORTx=0x00 輸入,無上拉電阻
          PORTA=0xFF;//不用的管腳使能內(nèi)部上拉電阻。
          PORTB=0xFF;
          PORTC=0xFF;//SCL,SDA使能了內(nèi)部的10K上拉電阻
          PORTD=0xFF;

          //TWI初始化
          TWSR=0x00;//預分頻=0^4=1
          TWBR=TWBR_SET;
          TWAR=0x00;//主機模式,該地址無效
          TWCR=0x00;//關(guān)閉TWI模塊
          sei();//使能全局中斷
          strTWI.STATUS=TW_OK;

          TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_WRITE,0x10,&ORGDATA[0],8);
          //從0x10地址開始寫入8個字節(jié)數(shù)據(jù)
          while(strTWI.STATUS==TW_BUSY);//等待操作完成
          if (strTWI.STATUS==TW_FAIL)
          {
          //操作失???
          }
          _delay_ms(10);//延時等待編程完成
          while(1)
          {
          i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x10,&CMPDATA[0],8);
          //從0x10地址開始讀出8個字節(jié)數(shù)據(jù)
          while(strTWI.STATUS==TW_BUSY);//等待操作完成
          //如果不加等待,則需要檢測返回值i才能知道當前操作是否執(zhí)行了
          // 0 OP_BUSY 之前的操作沒完成,沒執(zhí)行當前操作
          // 1 OP_RUN 當前操作執(zhí)行中
          if (strTWI.STATUS==TW_FAIL)
          {
          //操作失敗?
          }
          //讀取成功,對比ORGDATA和CMPDATA的數(shù)據(jù)

          i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x00,&BUFFER[0],256);
          //從0x00地址開始讀出256個字節(jié)數(shù)據(jù)(整個ATC24C02)
          while(strTWI.STATUS==TW_BUSY);//等待操作完成
          };
          }
          /*
          兩線串行接口總線定義
          兩線接口TWI很適合于典型的處理器應用。
          TWI協(xié)議允許系統(tǒng)設計者只用兩根雙向傳輸線就可以將128個不同的設備互連到一起。
          這兩根線一是時鐘SCL,一是數(shù)據(jù)SDA。外部硬件只需要兩個上拉電阻,每根線上一個。
          所有連接到總線上的設備都(必須)有自己的地址。
          注意:就是說不能有兩個相同地址的設備
          TWI協(xié)議解決了總線仲裁的問題。

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

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

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

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

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

          TWI 寄存器說明

          TWI 比特率寄存器- TWBR
          ? Bits 7..0 – TWI 比特率寄存器
          TWBR 為比特率發(fā)生器分頻因子。
          比特率發(fā)生器是一個分頻器,在主機模式下產(chǎn)生SCL時鐘頻率。
          比特率計算公式請見前面的[比特率發(fā)生器單元]

          TWI 控制寄存器- TWCR
          TWCR 用來控制TWI操作。
          它用來使能TWI,通過施加START到總線上來啟動主機訪問,產(chǎn)生接收器應答,產(chǎn)生STOP 狀態(tài),以及在寫入數(shù)據(jù)到TWDR 寄存器時控制總線的暫停等。
          這個寄存器還可以給出在TWDR 無法訪問期間,試圖將數(shù)據(jù)寫入到TWDR 而引起的寫入沖突信息。
          ? Bit 7 – TWINT: TWI 中斷標志
          當TWI 完成當前工作,希望應用程序介入時TWINT 置位。
          若SREG 的I 標志以及TWCR寄存器的TWIE 標志也置位,則MCU 執(zhí)行TWI 中斷例程。
          當TWINT 置位時, SCL信號的低電平被延長。
          TWINT 標志的清零必須通過軟件寫"1” 來完成。
          執(zhí)行中斷時硬件不會自動將其改寫為"0”。
          要注意的是,只要這一位被清零,TWI 立即開始工作。
          因此,在清零TWINT 之前一定要首先完成對地址寄存器TWAR,狀態(tài)寄存器TWSR,以及數(shù)據(jù)寄存器TWDR 的訪問。
          ? Bit 6 – TWEA: 使能TWI 應答
          TWEA 標志控制應答脈沖的產(chǎn)生。
          若TWEA 置位,出現(xiàn)如下條件時接口發(fā)出ACK 脈沖:
          1. 器件的從機地址與主機發(fā)出的地址相符合
          2. TWAR 的TWGCE 置位時接收到廣播呼叫
          3. 在主機/ 從機接收模式下接收到一個字節(jié)的數(shù)據(jù)
          將TWEA 清零可以使器件暫時脫離總線。
          置位后器件重新恢復地址識別。
          ? Bit 5 – TWSTA: TWI START 狀態(tài)標志
          當CPU 希望自己成為總線上的主機時需要置位TWSTA。
          TWI 硬件檢測總線是否可用。
          若總線空閑,接口就在總線上產(chǎn)生START 狀態(tài)。
          若總線忙,接口就一直等待,直到檢測到一個STOP 狀態(tài) ,然后產(chǎn)生START 以聲明自己希望成為主機。
          發(fā)送START之后軟件必須清零TWSTA。
          ? Bit 4 – TWSTO: TWI STOP 狀態(tài)標志
          在主機模式下,如果置位TWSTO,TWI 接口將在總線上產(chǎn)生STOP 狀態(tài),然后TWSTO自動清零。
          在從機模式下,置位TWSTO 可以使接口從錯誤狀態(tài)恢復到未被尋址的狀態(tài)。
          此時總線上不會有STOP 狀態(tài)產(chǎn)生,但TWI 返回一個定義好的未被尋址的從機模式且釋放SCL 與SDA 為高阻態(tài)。
          ? Bit 3 – TWWC: TWI 寫碰撞標志
          當TWINT 為低時寫數(shù)據(jù)寄存器TWDR 將置位TWWC。
          當TWINT 為高時,每一次對TWDR 的寫訪問都將更新此標志。
          ? Bit 2 – TWEN: TWI 使能
          TWEN 位用于使能TWI操作與激活TWI接口。
          當TWEN位被寫為"1”時,TWI引腳將I/O引腳切換到SCL 與SDA 引腳,使能波形斜率限制器與尖峰濾波器。
          如果該位清零, TWI接口模塊將被關(guān)閉,所有TWI 傳輸將被終止。
          ? Bit 0 – TWIE: 使能TWI 中斷
          當SREG 的I 以及TWIE 置位時,只要TWINT 為"1”, TWI 中斷就激活。

          TWI 狀態(tài)寄存器- TWSR
          ? Bits 7..3 – TWS: TWI 狀態(tài)
          這5位用來反映TWI 邏輯和總線的狀態(tài)。
          不同的狀態(tài)代碼將會在后面的部分描述。
          注意從TWSR 讀出的值包括5 位狀態(tài)值與2 位預分頻值。
          檢測狀態(tài)位時設計者應屏蔽預分頻位為"0”。這使狀態(tài)檢測獨立于預分頻器設置。
          ? Bits 1..0 – TWPS: TWI 預分頻位
          這兩位可讀/ 寫,用于控制比特率預分頻因子。
          預分頻系數(shù)為4的n次方
          計算比特率的公式見前面的[比特率發(fā)生器單元]

          TWI 數(shù)據(jù)寄存器- TWDR
          在發(fā)送模式, TWDR 包含了要發(fā)送的字節(jié);
          在接收模式, TWDR 包含了接收到的數(shù)據(jù)。
          當TWI 接口沒有進行移位工作(TWINT 置位) 時這個寄存器是可寫的。
          在第一次中斷發(fā)生之前用戶不能夠初始化數(shù)據(jù)寄存器。
          只要TWINT 置位,TWDR 的數(shù)據(jù)就是穩(wěn)定的。
          在數(shù)據(jù)移出時,總線上的數(shù)據(jù)同時移入寄存器。
          TWDR 總是包含了總線上出現(xiàn)的最后一個字節(jié),除非MCU 是從掉電或省電模式被TWI 中斷喚醒。此時TWDR 的內(nèi)容沒有定義。
          總線仲裁失敗時,主機將切換為從機,但總線上出現(xiàn)的數(shù)據(jù)不會丟失。
          ACK 的處理由 TWI邏輯自動管理, CPU 不能直接訪問ACK。
          ? Bits 7..0 – TWD: TWI 數(shù)據(jù)寄存器
          根據(jù)狀態(tài)的不同,其內(nèi)容為要發(fā)送的下一個字節(jié),或是接收到的數(shù)據(jù)。

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

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

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

          主機發(fā)送狀態(tài)碼
          #define TW_START0x08//START已發(fā)送
          #define TW_REP_START0x10//重復START已發(fā)送
          #define TW_MT_SLA_ACK0x18//SLA+W 已發(fā)送收到ACK
          #define TW_MT_SLA_NACK0x20//SLA+W 已發(fā)送接收到NOT ACK
          #define TW_MT_DATA_ACK0x28//數(shù)據(jù)已發(fā)送接收到ACK
          #define TW_MT_DATA_NACK0x30//數(shù)據(jù)已發(fā)送接收到NOT ACK
          #define TW_MT_ARB_LOST0x38//SLA+W 或數(shù)據(jù)的仲裁失敗


          主機接收狀態(tài)碼
          //#define TW_START0x08//START已發(fā)送
          //#define TW_REP_START0x10//重復START已發(fā)送
          #define TW_MR_ARB_LOST0x38//SLA+R 或NOT ACK 的仲裁失敗
          #define TW_MR_SLA_ACK0x40//SLA+R 已發(fā)送接收到ACK
          #define TW_MR_SLA_NACK0x48//SLA+R 已發(fā)送接收到NOT ACK
          #define TW_MR_DATA_ACK0x50//接收到數(shù)據(jù)ACK 已返回
          #define TW_MR_DATA_NACK0x58//接收到數(shù)據(jù)NOT ACK已返回

          從機接收狀態(tài)碼
          #define TW_SR_SLA_ACK0x60//自己的SLA+W 已經(jīng)被接收ACK已返回
          #define TW_SR_ARB_LOST_SLA_ACK0x68//SLA+R/W 作為主機的仲裁失??;自己的SLA+W 已經(jīng)被接收ACK 已返回
          #define TW_SR_GCALL_ACK0x70//接收到廣播地址ACK 已返回
          #define TW_SR_ARB_LOST_GCALL_ACK 0x78//SLA+R/W 作為主機的仲裁失??;接收到廣播地址ACK已返回
          #define TW_SR_DATA_ACK0x80//以前以自己的SLA+W被尋址;數(shù)據(jù)已經(jīng)被接收ACK已返回
          #define TW_SR_DATA_NACK0x88//以前以自己的SLA+W被尋址;數(shù)據(jù)已經(jīng)被接收NOT ACK已返回
          #define TW_SR_GCALL_DATA_ACK0x90//以前以廣播方式被尋址;數(shù)據(jù)已經(jīng)被接收ACK已返回
          #define TW_SR_GCALL_DATA_NACK0x98//以前以廣播方式被尋址;數(shù)據(jù)已經(jīng)被接收NOT ACK已返回
          #define TW_SR_STOP0xA0//在以從機工作時接收到STOP或重復START


          從發(fā)送狀態(tài)碼
          #define TW_ST_SLA_ACK0xA8//自己的SLA+R 已經(jīng)被接收ACK 已返回
          #define TW_ST_ARB_LOST_SLA_ACK0xB0//SLA+R/W 作為主機的仲裁失??;自己的SLA+R 已經(jīng)被接收ACK 已返回
          #define TW_ST_DATA_ACK0xB8//TWDR 里數(shù)據(jù)已經(jīng)發(fā)送接收到ACK
          #define TW_ST_DATA_NACK0xC0//TWDR 里數(shù)據(jù)已經(jīng)發(fā)送接收到NOT ACK
          #define TW_ST_LAST_DATA0xC8//TWDR 的一字節(jié)數(shù)據(jù)已經(jīng)發(fā)送(TWAE = “0”);接收到ACK


          其它狀態(tài)碼
          #define TW_NO_INFO0xF8//沒有相關(guān)的狀態(tài)信息;TWINT = “0”
          #define TW_BUS_ERROR0x00//由于非法的START 或STOP 引起的總線錯誤


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



          關(guān)鍵詞: AVRTWI讀

          評論


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

          關(guān)閉