資料介紹
本程序簡單的示范了如何使用ATMEGA16的TWI 讀寫AT24C02 IIC EEPROM
??? TWI協(xié)議
???? ?(即IIC協(xié)議,請認(rèn)真參考IIC協(xié)議的內(nèi)容,否則根本就不能掌握)
??? 一主多從的應(yīng)用,M16作主機(jī)
???? ?(M16做從機(jī)和多主多從的應(yīng)用不多,請自行參考相關(guān)文檔)
?中斷模式
??? ?(因?yàn)锳VR的速度很高,而IIC的速度相對較低,
???? ?采用查詢模式會長時(shí)間獨(dú)占CPU,令CPU的利用率明顯下降。
???? ?特別是IIC速度受環(huán)境影響只能低速通訊時(shí),對系統(tǒng)的實(shí)時(shí)性產(chǎn)生嚴(yán)重的影響。
???? ?查詢模式可以參考其它文檔和軟件模擬IIC的文檔)
???? AT24C02/04/08的操作特點(diǎn)
出于簡化程序考慮,各種數(shù)據(jù)沒有對外輸出,學(xué)習(xí)時(shí)建議使用JTAG ICE硬件仿真器
*/
#include
#include
#include
#include
//時(shí)鐘定為外部晶振7.3728MHz,F_CPU=7372800
#include
//定義了各種模式下的狀態(tài)碼列表(TWSR已屏蔽預(yù)分頻位),本文后面附上中文描述
//管腳定義
#define? pinSCL????0?????//PC0 SCL
#define? pinSDA????1?????//PC1 SDA
//為保險(xiǎn)起見,最好在SCL/SDA接上1~10K的外部上拉電阻到VCC。
#define fSCL????100000????//TWI時(shí)鐘為100KHz
//預(yù)分頻系數(shù)=1(TWPS=0)
#if F_CPU < fSCL*36
? #define TWBR_SET ???10;?????//TWBR必須大于等于10
#else
? #define TWBR_SET? ??(F_CPU/fSCL-16)/2;?//計(jì)算TWBR值
#endif
#define TW_ACT????(1<
#define SLA_24CXX???0xA0????//24Cxx系列的廠商器件地址(高四位)
#define ADDR_24C02???0x00
// AT24C02的地址線A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01
//TWI_操作狀態(tài)
#define TW_BUSY????0
#define TW_OK????1
#define TW_FAIL????2
//TWI_讀寫命令狀態(tài)
#define OP_BUSY????0
#define OP_RUN????1
//TWI讀寫操作公共步驟
#define ST_FAIL????0?//出錯(cuò)狀態(tài)
#define ST_START???1?//START狀態(tài)檢查
#define ST_SLAW????2?//SLAW狀態(tài)檢查
#define ST_WADDR???3?//ADDR狀態(tài)檢查
//TWI讀操作步驟
#define ST_RESTART???4?//RESTART狀態(tài)檢查
#define ST_SLAR????5?//SLAR狀態(tài)檢查
#define ST_RDATA???6?//讀取數(shù)據(jù)狀態(tài)檢查,循環(huán)n字節(jié)
//TWI寫操作步驟
#define ST_WDATA???7?//寫數(shù)據(jù)狀態(tài)檢查,循環(huán)n字節(jié)
#define FAIL_MAX???20?//重試次數(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ū),可以裝載整個(gè)AC24C02的數(shù)據(jù)
struct str_TWI?????????//TWI數(shù)據(jù)結(jié)構(gòu)
{
??? volatile unsigned char?STATUS;????//TWI_操作狀態(tài)
??? unsigned char?SLA;??????//從設(shè)備的器件地址
??? unsigned int?ADDR;??????//從設(shè)備的數(shù)據(jù)地址
??? unsigned char?*pBUF;??????//數(shù)據(jù)緩沖區(qū)指針
??? unsigned int?DATALEN;?????//數(shù)據(jù)長度
??? unsigned char?STATE;??????//TWI讀寫操作步驟
??? unsigned char?FAILCNT;?????//失敗重試次數(shù)
};
struct str_TWI strTWI;???????//TWI的數(shù)據(jù)結(jié)構(gòu)變量
//仿真時(shí)在watch窗口,監(jiān)控這些全局變量。
//AT24C02的讀寫函數(shù)(包括隨機(jī)讀,連續(xù)讀,字節(jié)寫,頁寫)
//根據(jù)sla的最低位決定(由中斷程序中判斷)
//bit0=1 TW_READ? 讀
//bit0=0 TW_WRITE 寫
//? sla???器件地址(不能搞錯(cuò))
//?addr??EEPROM地址(0~1023)
//?*ptr??讀寫數(shù)據(jù)緩沖區(qū)
//?len???讀數(shù)據(jù)長度(1~1024),寫數(shù)據(jù)長度(1 or 8 or 16)
//? 返回值??是否能執(zhí)行當(dāng)前操作
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忙,不能進(jìn)行操作
??????? 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<
}
/*
TWI中斷函數(shù)
?這個(gè)函數(shù)流程只是考慮了器件地址后有一個(gè)字節(jié)數(shù)據(jù)(命令)地址的IIC器件
?(大部分IIC接口器件都是這種類型,常見的例如AT24C01/02/04/08/16,DS1307,DS1721等)
?對于有兩個(gè)字節(jié)數(shù)據(jù)地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),請稍作改動
?
//根據(jù)strTWI.SLA的最低位決定
//bit0=1 TW_READ? 讀
//bit0=0 TW_WRITE 寫
?雖然中斷服務(wù)程序很長,但每次只執(zhí)行一個(gè) case,所以耗時(shí)并不長。
*/
SIGNAL(SIG_2WIRE_SERIAL)
{//IIC中斷
??? unsigned char action,state,status;
??? action=strTWI.SLA&TW_READ;?????//取操作模式
??? state=strTWI.STATE;
??? status=TWSR&0xF8;???????//屏蔽預(yù)分頻位
??? if ((status>=0x60)||(status==0x00))
??? {//總線錯(cuò)誤或從機(jī)模式引發(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ā)下一步動作,同時(shí)清start發(fā)送標(biāo)志
??????? }
??????? else
??????? {//發(fā)送start信號出錯(cuò)
??????????? 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ā)送器件地址出錯(cuò)
??????????? 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++;???????? ?//寫第一個(gè)字節(jié)
??????????????? strTWI.DATALEN--;
??????????????? state=ST_WDATA-1;????//下一步將跳到WDATA分支
??????????????? TWCR=TW_ACT;???????? ???//觸發(fā)下一步動作
??????????? }
??????? }
??????? else
??????? {//發(fā)送eeprom地址出錯(cuò)
??????????? 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ā)下一步動作,同時(shí)清start發(fā)送標(biāo)志
??????? }
??????? else
??????? {//重發(fā)start信號出錯(cuò)
??????????? state=ST_FAIL;
??????? }
??????? break;
??? case ST_SLAR:?//SLAR狀態(tài)檢查,只有讀操作模式才能跳到這里
??????? if(status==TW_MR_SLA_ACK)
??????? {//發(fā)送器件地址成功
??????????? if (strTWI.DATALEN--)
??????????? {//多個(gè)數(shù)據(jù)
??????????????? TWCR=(1<
??????????? else
??????????? {//只有一個(gè)數(shù)據(jù)
??????????????? TWCR=TW_ACT;?????//設(shè)定NAK,觸發(fā)下一步動作
??????????? }
??????? }
??????? else
??????? {//發(fā)送器件地址出錯(cuò)
??????????? state=ST_FAIL;
??????? }
??????? break;
??? case ST_RDATA:?//讀取數(shù)據(jù)狀態(tài)檢查,只有讀操作模式才能跳到這里
??????? state--;????????//循環(huán),直到讀完指定長度數(shù)據(jù)
??????? if(status==TW_MR_DATA_ACK)
??????? {//讀取數(shù)據(jù)成功,但不是最后一個(gè)數(shù)據(jù)
??????????? *strTWI.pBUF++=TWDR;
??????????? if (strTWI.DATALEN--)
??????????? {//還有多個(gè)數(shù)據(jù)
??????????????? TWCR=(1<
??????????? else
??????????? {//準(zhǔn)備讀最后一個(gè)數(shù)據(jù)
??????????????? TWCR=TW_ACT;?????//設(shè)定NAK,觸發(fā)下一步動作
??????????? }
??????? }
??????? else if(status==TW_MR_DATA_NACK)
??????? {//已經(jīng)讀完最后一個(gè)數(shù)據(jù)
??????????? *strTWI.pBUF++=TWDR;
??????????? TWCR=(1<
??????? }
??????? else
??????? {//讀取數(shù)據(jù)出錯(cuò)
??????????? 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<
??????????????? //啟動寫命令后需要10ms(最大)的編程時(shí)間才能真正的把數(shù)據(jù)記錄下來
??????????????? //編程期間器件不響應(yīng)任何命令
??????????? }
??????? }
??????? else
??????? {//寫數(shù)據(jù)失敗
??????????? state=ST_FAIL;
??????? }
??????? break;
??? default:
??????? //錯(cuò)誤狀態(tài)
??????? state=ST_FAIL;
??????? break;
??? }
??? if (state==ST_FAIL)
??? {//錯(cuò)誤處理
??????? strTWI.FAILCNT++;
??????? if (strTWI.FAILCNT
??????????? TWCR=(1<
??????? else
??????? {//否則停止
??????????? TWCR=(1<
??????? }
??? }
??? state++;
??? strTWI.STATE=state;???????//保存狀態(tài)
}
int main(void)
{
??? unsigned char i;
??? //上電默認(rèn)DDRx=0x00,PORTx=0x00 輸入,無上拉電阻
??? PORTA=0xFF;?????????//不用的管腳使能內(nèi)部上拉電阻。
??? PORTB=0xFF;
??? PORTC=0xFF;?????????//SCL,SDA使能了內(nèi)部的10K上拉電阻
??? PORTD=0xFF;
??? //TWI初始化
??? TWSR=0x00;?????????//預(yù)分頻=0^4=1
??? TWBR=TWBR_SET;
??? TWAR=0x00;?????????//主機(jī)模式,該地址無效
??? 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個(gè)字節(jié)數(shù)據(jù)
??? while(strTWI.STATUS==TW_BUSY);????//等待操作完成
??? if (strTWI.STATUS==TW_FAIL)
??? {
??????? //操作失?。?BR>??? }
??? _delay_ms(10);????????//延時(shí)等待編程完成
??? while(1)
??? {
??????? i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x10,&CMPDATA[0],8);
??????? //從0x10地址開始讀出8個(gè)字節(jié)數(shù)據(jù)
??????? while(strTWI.STATUS==TW_BUSY);???//等待操作完成
??????? //如果不加等待,則需要檢測返回值i才能知道當(dāng)前操作是否執(zhí)行了
??????? // 0 OP_BUSY 之前的操作沒完成,沒執(zhí)行當(dāng)前操作
??????? // 1 OP_RUN? 當(dāng)前操作執(zhí)行中
??????? if (strTWI.STATUS==TW_FAIL)
??????? {
??????????? //操作失?。?BR>??????? }
??????? //讀取成功,對比ORGDATA和CMPDATA的數(shù)據(jù)
??????? i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x00,&BUFFER[0],256);
??????? //從0x00地址開始讀出256個(gè)字節(jié)數(shù)據(jù)(整個(gè)ATC24C02)
??????? while(strTWI.STATUS==TW_BUSY);???//等待操作完成
??? };
}
/*
兩線串行接口總線定義
?兩線接口TWI很適合于典型的處理器應(yīng)用。
?TWI協(xié)議允許系統(tǒng)設(shè)計(jì)者只用兩根雙向傳輸線就可以將128個(gè)不同的設(shè)備互連到一起。
?這兩根線一是時(shí)鐘SCL,一是數(shù)據(jù)SDA。外部硬件只需要兩個(gè)上拉電阻,每根線上一個(gè)。
?所有連接到總線上的設(shè)備都(必須)有自己的地址。
?注意:就是說不能有兩個(gè)相同地址的設(shè)備
?TWI協(xié)議解決了總線仲裁的問題。
?
?所有 TWI 兼容的器件的總線驅(qū)動都是漏極開路或集電極開路的。這樣就實(shí)現(xiàn)了對接口操作非常關(guān)鍵的線與功能。
?TWI器件輸出為"0”時(shí),TWI總線會產(chǎn)生低電平。
?當(dāng)所有的TWI器件輸出為三態(tài)時(shí),總線會輸出高電平,允許上拉電阻將電壓拉高。
?注意:為保證所有的總線操作,凡是與TWI 總線連接的AVR 器件必須上電。
?
?與總線連接的器件數(shù)目受如下條件限制:
?總線電容要低于400pF,而且可以用7 位從機(jī)地址進(jìn)行尋址。
?兩個(gè)不同的規(guī)范,一種是總線速度低于100 kHz,而另外一種是總線速度高達(dá)400 kHz。
?
SCL和SDA引腳
?SCL與SDA為MCU的 TWI接口引腳。
?引腳的輸出驅(qū)動器包含一個(gè)波形斜率限制器以滿足TWI 規(guī)范。
?引腳的輸入部分包括尖峰抑制單元以去除小于50ns 的毛刺。
?當(dāng)相應(yīng)的端口設(shè)置為SCL與SDA引腳時(shí),可以使能I/O口內(nèi)部的10K上拉電阻,這樣可省掉外部的上拉電阻
注意:如果要作高速通訊或者從機(jī)數(shù)量較多,最好還是外接合適的上拉電阻
?
比特率發(fā)生器單元
?TWI工作于主機(jī)模式時(shí),比特率發(fā)生器控制時(shí)鐘信號SCL的周期。
?具體由TWI狀態(tài)寄存器TWSR的預(yù)分頻系數(shù)以及比特率寄存器TWBR設(shè)定。
?當(dāng)TWI工作在從機(jī)模式時(shí),不需要對比特率或預(yù)分頻進(jìn)行設(shè)定,但從機(jī)的CPU時(shí)鐘頻率必須大于TWI時(shí)鐘線SCL頻率的16倍。
注意,從機(jī)可能會延長SCL 低電平的時(shí)間,從而降低TWI 總線的平均時(shí)鐘周期。
?SCL的頻率根據(jù)以下的公式產(chǎn)生:
??fSCL=fCPU/((16+2(TWBR)(4^TWPS))
?TWBR = TWI比特率寄存器的數(shù)值
?TWPS = TWI狀態(tài)寄存器預(yù)分頻的數(shù)值
Note:TWI 工作在主機(jī)模式時(shí),TWBR 值應(yīng)該不小于10,否則主機(jī)會在SDA 與 SCL 產(chǎn)生錯(cuò)誤輸出作為提示信號。
?問題出現(xiàn)于TWI 工作在主機(jī)模式下,向從機(jī)發(fā)送Start + SLA + R/W 的時(shí)候(不需要真的有從機(jī)與總線連接)。
?
控制單元
?控制單元監(jiān)聽TWI 總線,并根據(jù) TWI 控制寄存器TWCR 的設(shè)置作出相應(yīng)的響應(yīng)。
?當(dāng)TWI總線上產(chǎn)生需要應(yīng)用程序干預(yù)處理的事件時(shí),TWI 中斷標(biāo)志位TWINT 置位。
?在下一個(gè)時(shí)鐘周期, TWI 狀態(tài)寄存器TWSR 被表示這個(gè)事件的狀態(tài)碼字所更新。
?在其它時(shí)間里,TWSR 的內(nèi)容為一個(gè)表示無事件發(fā)生的特殊狀態(tài)字。
?一旦TWINT 標(biāo)志位置"1”,時(shí)鐘線SCL 即被拉低,暫停TWI 總線上的數(shù)據(jù)傳輸,讓用戶程序處理事件。
?在下列狀況出現(xiàn)時(shí), TWINT 標(biāo)志位置位:
?? 在TWI 傳送完START/REPEATED START 信號之后
?? 在TWI 傳送完SLA+R/W 數(shù)據(jù)之后
?? 在TWI 傳送完地址字節(jié)之后
?? 在TWI 總線仲裁失敗之后
?? 在TWI 被主機(jī)尋址之后( 廣播方式或從機(jī)地址匹配)
?? 在TWI 接收到一個(gè)數(shù)據(jù)字節(jié)之后
?? 作為從機(jī)工作時(shí), TWI 接收到STOP 或REPEATED START 信號之后
?? 由于非法的START 或STOP 信號造成總線錯(cuò)誤時(shí)
?
TWI 寄存器說明
?
TWI 比特率寄存器- TWBR
?? Bits 7..0 – TWI 比特率寄存器
??TWBR 為比特率發(fā)生器分頻因子。
??比特率發(fā)生器是一個(gè)分頻器,在主機(jī)模式下產(chǎn)生SCL時(shí)鐘頻率。
??比特率計(jì)算公式請見前面的[比特率發(fā)生器單元]
??
TWI 控制寄存器- TWCR
?TWCR 用來控制TWI操作。
?它用來使能TWI,通過施加START到總線上來啟動主機(jī)訪問,產(chǎn)生接收器應(yīng)答,產(chǎn)生STOP 狀態(tài),以及在寫入數(shù)據(jù)到TWDR 寄存器時(shí)控制總線的暫停等。
?這個(gè)寄存器還可以給出在TWDR 無法訪問期間,試圖將數(shù)據(jù)寫入到TWDR 而引起的寫入沖突信息。
?? Bit 7 – TWINT: TWI 中斷標(biāo)志
??當(dāng)TWI 完成當(dāng)前工作,希望應(yīng)用程序介入時(shí)TWINT 置位。
??若SREG 的I 標(biāo)志以及TWCR寄存器的TWIE 標(biāo)志也置位,則MCU 執(zhí)行TWI 中斷例程。
??當(dāng)TWINT 置位時(shí), SCL信號的低電平被延長。
??TWINT 標(biāo)志的清零必須通過軟件寫"1” 來完成。
??執(zhí)行中斷時(shí)硬件不會自動將其改寫為"0”。
??要注意的是,只要這一位被清零,TWI 立即開始工作。
??因此,在清零TWINT 之前一定要首先完成對地址寄存器TWAR,狀態(tài)寄存器TWSR,以及數(shù)據(jù)寄存器TWDR 的訪問。
?? Bit 6 – TWEA: 使能TWI 應(yīng)答
??TWEA 標(biāo)志控制應(yīng)答脈沖的產(chǎn)生。
??若TWEA 置位,出現(xiàn)如下條件時(shí)接口發(fā)出ACK 脈沖:
??1. 器件的從機(jī)地址與主機(jī)發(fā)出的地址相符合
??2. TWAR 的TWGCE 置位時(shí)接收到廣播呼叫
??3. 在主機(jī)/ 從機(jī)接收模式下接收到一個(gè)字節(jié)的數(shù)據(jù)
??將TWEA 清零可以使器件暫時(shí)脫離總線。
??置位后器件重新恢復(fù)地址識別。?
?? Bit 5 – TWSTA: TWI START 狀態(tài)標(biāo)志
??當(dāng)CPU 希望自己成為總線上的主機(jī)時(shí)需要置位TWSTA。
??TWI 硬件檢測總線是否可用。
??若總線空閑,接口就在總線上產(chǎn)生START 狀態(tài)。
??若總線忙,接口就一直等待,直到檢測到一個(gè)STOP 狀態(tài) ,然后產(chǎn)生START 以聲明自己希望成為主機(jī)。
??發(fā)送START之后軟件必須清零TWSTA。
?? Bit 4 – TWST TWI STOP 狀態(tài)標(biāo)志
??在主機(jī)模式下,如果置位TWSTO,TWI 接口將在總線上產(chǎn)生STOP 狀態(tài),然后TWSTO自動清零。
??在從機(jī)模式下,置位TWSTO 可以使接口從錯(cuò)誤狀態(tài)恢復(fù)到未被尋址的狀態(tài)。
??此時(shí)總線上不會有STOP 狀態(tài)產(chǎn)生,但TWI 返回一個(gè)定義好的未被尋址的從機(jī)模式且釋放SCL 與SDA 為高阻態(tài)。
?? Bit 3 – TWWC: TWI 寫碰撞標(biāo)志
??當(dāng)TWINT 為低時(shí)寫數(shù)據(jù)寄存器TWDR 將置位TWWC。
??當(dāng)TWINT 為高時(shí),每一次對TWDR 的寫訪問都將更新此標(biāo)志。
?? Bit 2 – TWEN: TWI 使能
??TWEN 位用于使能TWI操作與激活TWI接口。
??當(dāng)TWEN位被寫為"1”時(shí),TWI引腳將I/O引腳切換到SCL 與SDA 引腳,使能波形斜率限制器與尖峰濾波器。
??如果該位清零, TWI接口模塊將被關(guān)閉,所有TWI 傳輸將被終止。
?? Bit 0 – TWIE: 使能TWI 中斷
??當(dāng)SREG 的I 以及TWIE 置位時(shí),只要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 位預(yù)分頻值。
??檢測狀態(tài)位時(shí)設(shè)計(jì)者應(yīng)屏蔽預(yù)分頻位為"0”。這使?fàn)顟B(tài)檢測獨(dú)立于預(yù)分頻器設(shè)置。
?? Bits 1..0 – TWPS: TWI 預(yù)分頻位
??這兩位可讀/ 寫,用于控制比特率預(yù)分頻因子。
??預(yù)分頻系數(shù)為4的n次方
??計(jì)算比特率的公式見前面的[比特率發(fā)生器單元]
??
TWI 數(shù)據(jù)寄存器- TWDR
?在發(fā)送模式, TWDR 包含了要發(fā)送的字節(jié);
?在接收模式, TWDR 包含了接收到的數(shù)據(jù)。
?當(dāng)TWI 接口沒有進(jìn)行移位工作(TWINT 置位) 時(shí)這個(gè)寄存器是可寫的。
?在第一次中斷發(fā)生之前用戶不能夠初始化數(shù)據(jù)寄存器。
?只要TWINT 置位,TWDR 的數(shù)據(jù)就是穩(wěn)定的。
?在數(shù)據(jù)移出時(shí),總線上的數(shù)據(jù)同時(shí)移入寄存器。
?TWDR 總是包含了總線上出現(xiàn)的最后一個(gè)字節(jié),除非MCU 是從掉電或省電模式被TWI 中斷喚醒。此時(shí)TWDR 的內(nèi)容沒有定義。
?總線仲裁失敗時(shí),主機(jī)將切換為從機(jī),但總線上出現(xiàn)的數(shù)據(jù)不會丟失。
?ACK 的處理由 TWI邏輯自動管理, CPU 不能直接訪問ACK。
?? Bits 7..0 – TWD: TWI 數(shù)據(jù)寄存器
??根據(jù)狀態(tài)的不同,其內(nèi)容為要發(fā)送的下一個(gè)字節(jié),或是接收到的數(shù)據(jù)。
?
TWI(從機(jī)) 地址寄存器-TWAR
?TWAR 的高7 位為從機(jī)地址。
?工作于從機(jī)模式時(shí),TWI 將根據(jù)這個(gè)地址進(jìn)行響應(yīng)。
?主機(jī)模式不需要此地址。
?在多主機(jī)系統(tǒng)中, TWAR需要進(jìn)行設(shè)置以便其他主機(jī)訪問自己。
?TWAR 的LSB 用于識別廣播地址 (0x00)。
?器件內(nèi)有一個(gè)地址比較器。一旦接收到的地址和本機(jī)地址一致,芯片就請求中斷。
?? Bits 7..1 – TWA: TWI 從機(jī)地址寄存器
??其值為從機(jī)地址。
?? Bit 0 – TWGCE: 使能TWI 廣播識別
??置位后MCU 可以識別TWI 總線廣播。
?
使用TWI
?AVR的TWI接口是面向字節(jié)和基于中斷的。
?所有的總線事件,如接收到一個(gè)字節(jié)或發(fā)送了一個(gè)START 信號等,都會產(chǎn)生一個(gè)TWI 中斷。
?由于TWI 接口是基于中斷的,因此TWI接口在字節(jié)發(fā)送和接收過程中,不需要應(yīng)用程序的干預(yù)。
?TWCR寄存器的TWI中斷允許位[TWIE]和全局中斷允許位[I]一起決定了應(yīng)用程序是否響應(yīng)TWINT標(biāo)志位產(chǎn)生的中斷請求。
?如果TWIE 被清零,應(yīng)用程序只能采用輪詢TWINT 標(biāo)志位的方法來檢測TWI 總線狀態(tài)。
?當(dāng)TWINT 標(biāo)志位置"1” 時(shí),表示TWI 接口完成了當(dāng)前的操作,等待應(yīng)用程序的響應(yīng)。
?在這種情況下,TWI 狀態(tài)寄存器TWSR 包含了表明當(dāng)前TWI 總線狀態(tài)的值。
?應(yīng)用程序可以讀取TWCR 的狀態(tài)碼,判別此時(shí)的狀態(tài)是否正確,并通過設(shè)置TWCR 與TWDR 寄存器,決定在下一個(gè)TWI 總線周期TWI 接口應(yīng)該如何工作。?
?
各種模式下的狀態(tài)碼列表(TWSR已屏蔽預(yù)分頻位)
twi.h里面有定義,現(xiàn)附上中文描述
?
主機(jī)發(fā)送狀態(tài)碼
#define TW_START????0x08?//START已發(fā)送
#define TW_REP_START???0x10?//重復(fù)START已發(fā)送
#define TW_MT_SLA_ACK???0x18?//SLA+W 已發(fā)送收到ACK
#define TW_MT_SLA_NACK???0x20?//SLA+W 已發(fā)送接收到NOT ACK
#define TW_MT_DATA_ACK???0x28?//數(shù)據(jù)已發(fā)送接收到ACK
#define TW_MT_DATA_NACK???0x30?//數(shù)據(jù)已發(fā)送接收到NOT ACK
#define TW_MT_ARB_LOST???0x38?//SLA+W 或數(shù)據(jù)的仲裁失敗
?
從發(fā)送狀態(tài)碼
#define TW_ST_SLA_ACK???0xA8?//自己的SLA+R 已經(jīng)被接收ACK 已返回
#define TW_ST_ARB_LOST_SLA_ACK?0xB0?//SLA+R/W 作為主機(jī)的仲裁失敗;自己的SLA+R 已經(jīng)被接收ACK 已返回
#define TW_ST_DATA_ACK???0xB8?//TWDR 里數(shù)據(jù)已經(jīng)發(fā)送接收到ACK
#define TW_ST_DATA_NACK???0xC0?//TWDR 里數(shù)據(jù)已經(jīng)發(fā)送接收到NOT ACK
#define TW_ST_LAST_DATA???0xC8?//TWDR 的一字節(jié)數(shù)據(jù)已經(jīng)發(fā)送(TWAE = “0”);接收到ACK
?
AT24C02/04/08 IIC接口EEPROM的特點(diǎn)
(不同公司的24系列EEPROM特性有部分不同,請參考數(shù)據(jù)手冊)
?1 AT24C02/04/08 是一個(gè)2K/4K/8K位串行CMOS E2PROM 內(nèi)部含有256/512/1024 個(gè)8位字節(jié)
?2 AT24C02有一個(gè)8 字節(jié)頁寫緩沖器,AT24C04/08/16 有一個(gè)16字節(jié)頁寫緩沖器
?3 通過器件地址輸入端A0,A1,A2可以實(shí)現(xiàn)將最多
??8個(gè)24C02器件
??4個(gè)24C04器件
??2個(gè)24C08器件
- 基于51單片機(jī)的iic--24c02EEPROM讀寫程序 0次下載
- STM32f103系列i2c讀寫文件at24c02 22次下載
- K023 基于51/STM32 AT24C02模塊測試 OLED0.96顯示讀寫值
- AT24C02程序
- IIC及AT24C02的讀寫(單片機(jī)實(shí)驗(yàn))
- EEPROM存儲芯片AT24C02芯片手冊
- 使用單片機(jī)實(shí)現(xiàn)非零地址讀寫AT24C02的仿真設(shè)計(jì)實(shí)例文件免費(fèi)下載 17次下載
- 使用單片機(jī)讀寫IIC AT24C02的仿真設(shè)計(jì)實(shí)例文件免費(fèi)下載 30次下載
- 使用AT24C02設(shè)計(jì)密碼鎖1602顯示的程序免費(fèi)下載 35次下載
- 使用AT24C02設(shè)計(jì)密碼鎖的程序免費(fèi)下載 29次下載
- AT24C02資料 29次下載
- AT24C02 13次下載
- at24c02讀取程序頭文件 6次下載
- 讀寫AT24C02 并顯示 11次下載
- AT24C02/AT24C04/AT24C08/AT24C1
- 通過IIC總線讀寫AT24C512存儲器 1797次閱讀
- STM32基礎(chǔ)知識:IIC總線操作EEPROM存儲模塊AT24C02 1990次閱讀
- AT24C04芯片驅(qū)動程序原理 1827次閱讀
- 用OpenVINO? C++ API編寫YOLOv8-Seg實(shí)例分割模型推理程序 1257次閱讀
- 使用51單片機(jī)讀寫AT29C040的C語言程序免費(fèi)下載 4529次閱讀
- 51單片機(jī)讀寫AT29C040的C51程序 4738次閱讀
- 微雪電子EEPROM存儲模塊AT24C簡介 2242次閱讀
- AT89S52單片機(jī)并行端口模擬I2C總線協(xié)議讀寫AT24C04的設(shè)計(jì) 2583次閱讀
- AVR單片機(jī)讀寫CPLD程序實(shí)例(ATmega128程序案例) 8256次閱讀
- at24c04中文資料匯總(at24c04引腳圖及功能_工作原理及電路圖) 7.9w次閱讀
- C51讀寫AT24C04源代碼及AT24C04測試程序 1.6w次閱讀
- PIC12C508讀寫93LC46范例程式 2600次閱讀
- 單片機(jī)之IIC--AT24C256的讀寫程序 1.4w次閱讀
- 《振南電子STM32視頻教程》第八講:I2C總線 1077次閱讀
- 讀寫24LCxx系列的EEPROM的實(shí)例程序 2210次閱讀
下載排行
本周
- 1電子電路原理第七版PDF電子教材免費(fèi)下載
- 0.00 MB | 1490次下載 | 免費(fèi)
- 2單片機(jī)典型實(shí)例介紹
- 18.19 MB | 92次下載 | 1 積分
- 3S7-200PLC編程實(shí)例詳細(xì)資料
- 1.17 MB | 27次下載 | 1 積分
- 4筆記本電腦主板的元件識別和講解說明
- 4.28 MB | 18次下載 | 4 積分
- 5開關(guān)電源原理及各功能電路詳解
- 0.38 MB | 10次下載 | 免費(fèi)
- 6基于AT89C2051/4051單片機(jī)編程器的實(shí)驗(yàn)
- 0.11 MB | 4次下載 | 免費(fèi)
- 7藍(lán)牙設(shè)備在嵌入式領(lǐng)域的廣泛應(yīng)用
- 0.63 MB | 3次下載 | 免費(fèi)
- 89天練會電子電路識圖
- 5.91 MB | 3次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費(fèi)
- 2PADS 9.0 2009最新版 -下載
- 0.00 MB | 66304次下載 | 免費(fèi)
- 3protel99下載protel99軟件下載(中文版)
- 0.00 MB | 51209次下載 | 免費(fèi)
- 4LabView 8.0 專業(yè)版下載 (3CD完整版)
- 0.00 MB | 51043次下載 | 免費(fèi)
- 5555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33562次下載 | 免費(fèi)
- 6接口電路圖大全
- 未知 | 30320次下載 | 免費(fèi)
- 7Multisim 10下載Multisim 10 中文版
- 0.00 MB | 28588次下載 | 免費(fèi)
- 8開關(guān)電源設(shè)計(jì)實(shí)例指南
- 未知 | 21539次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935053次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537791次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420026次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233045次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191183次下載 | 免費(fèi)
- 7十天學(xué)會AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183277次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138039次下載 | 免費(fèi)
評論
查看更多