久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

AVR TWI讀寫(xiě)范例程序(AT24C02)

作者:蕭文   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年04月01日   【字體:

 

本程序簡(jiǎn)單的示范了如何使用ATMEGA16的TWI 讀寫(xiě)AT24C02 IIC EEPROM
    TWI協(xié)議
      (即IIC協(xié)議,請(qǐng)認(rèn)真參考IIC協(xié)議的內(nèi)容,否則根本就不能掌握)
    一主多從的應(yīng)用,M16作主機(jī)
      (M16做從機(jī)和多主多從的應(yīng)用不多,請(qǐng)自行參考相關(guān)文檔)
 中斷模式
     (因?yàn)锳VR的速度很高,而IIC的速度相對(duì)較低,
      采用查詢模式會(huì)長(zhǎng)時(shí)間獨(dú)占CPU,令CPU的利用率明顯下降。
      特別是IIC速度受環(huán)境影響只能低速通訊時(shí),對(duì)系統(tǒng)的實(shí)時(shí)性產(chǎn)生嚴(yán)重的影響。
      查詢模式可以參考其它文檔和軟件模擬IIC的文檔)
     AT24C02/04/08的操作特點(diǎn)
出于簡(jiǎn)化程序考慮,各種數(shù)據(jù)沒(méi)有對(duì)外輸出,學(xué)習(xí)時(shí)建議使用JTAG ICE硬件仿真器
*/

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

//管腳定義
#define  pinSCL    0     //PC0 SCL
#define  pinSDA    1     //PC1 SDA
//為保險(xiǎn)起見(jià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<<TWINT)|(1<<TWEN)|(1<<TWIE)
//TWCR只能IN/OUT,直接賦值比邏輯運(yùn)算(|= &=)更節(jié)省空間

#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_讀寫(xiě)命令狀態(tài)
#define OP_BUSY    0
#define OP_RUN    1


//TWI讀寫(xiě)操作公共步驟
#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寫(xiě)操作步驟
#define ST_WDATA   7 //寫(xiě)數(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ù)長(zhǎng)度
    unsigned char STATE;      //TWI讀寫(xiě)操作步驟
    unsigned char FAILCNT;     //失敗重試次數(shù)
};

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

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


//AT24C02的讀寫(xiě)函數(shù)(包括隨機(jī)讀,連續(xù)讀,字節(jié)寫(xiě),頁(yè)寫(xiě))
//根據(jù)sla的最低位決定(由中斷程序中判斷)
//bit0=1 TW_READ  讀
//bit0=0 TW_WRITE 寫(xiě)
//  sla   器件地址(不能搞錯(cuò))
// addr  EEPROM地址(0~1023)
// *ptr  讀寫(xiě)數(shù)據(jù)緩沖區(qū)
// len   讀數(shù)據(jù)長(zhǎng)度(1~1024),寫(xiě)數(shù)據(jù)長(zhǎng)度(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<<TWSTA)|TW_ACT;      //啟動(dòng)start信號(hào)
    return OP_RUN;
}

/*
TWI中斷函數(shù)
 這個(gè)函數(shù)流程只是考慮了器件地址后有一個(gè)字節(jié)數(shù)據(jù)(命令)地址的IIC器件
 (大部分IIC接口器件都是這種類型,常見(jiàn)的例如AT24C01/02/04/08/16,DS1307,DS1721等)
 對(duì)于有兩個(gè)字節(jié)數(shù)據(jù)地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),請(qǐng)稍作改動(dòng)
 
//根據(jù)strTWI.SLA的最低位決定
//bit0=1 TW_READ  讀
//bit0=0 TW_WRITE 寫(xiě)

 雖然中斷服務(wù)程序很長(zhǎng),但每次只執(zhí)行一個(gè) case,所以耗時(shí)并不長(zhǎng)。
*/
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信號(hào)成功
            TWDR=strTWI.SLA&0xFE;    //發(fā)送器件地址寫(xiě)SLAW
            TWCR=TW_ACT;             //觸發(fā)下一步動(dòng)作,同時(shí)清start發(fā)送標(biāo)志
        }
        else
        {//發(fā)送start信號(hào)出錯(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ā)下一步動(dòng)作
        }
        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<<TWSTA)|TW_ACT;   //發(fā)送restart信號(hào),下一步將跳到RESTART分支
            }
            else
            {//寫(xiě)操作模式
                TWDR=*strTWI.pBUF++;          //寫(xiě)第一個(gè)字節(jié)
                strTWI.DATALEN--;
                state=ST_WDATA-1;    //下一步將跳到WDATA分支
                TWCR=TW_ACT;            //觸發(fā)下一步動(dòng)作
            }
        }
        else
        {//發(fā)送eeprom地址出錯(cuò)
            state=ST_FAIL;
        }
        break;
    case ST_RESTART: //RESTART狀態(tài)檢查,只有讀操作模式才能跳到這里
        if(status==TW_REP_START)
        {//發(fā)送restart信號(hào)成功
            TWDR=strTWI.SLA;     //發(fā)器件地址讀SLAR
            TWCR=TW_ACT;             //觸發(fā)下一步動(dòng)作,同時(shí)清start發(fā)送標(biāo)志
        }
        else
        {//重發(fā)start信號(hào)出錯(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<<TWEA)|TW_ACT;   //設(shè)定ACK,觸發(fā)下一步動(dòng)作
            }
            else
            {//只有一個(gè)數(shù)據(jù)
                TWCR=TW_ACT;     //設(shè)定NAK,觸發(fā)下一步動(dòng)作
            }
        }
        else
        {//發(fā)送器件地址出錯(cuò)
            state=ST_FAIL;
        }
        break;
    case ST_RDATA: //讀取數(shù)據(jù)狀態(tài)檢查,只有讀操作模式才能跳到這里
        state--;        //循環(huán),直到讀完指定長(zhǎng)度數(shù)據(jù)
        if(status==TW_MR_DATA_ACK)
        {//讀取數(shù)據(jù)成功,但不是最后一個(gè)數(shù)據(jù)
            *strTWI.pBUF++=TWDR;
            if (strTWI.DATALEN--)
            {//還有多個(gè)數(shù)據(jù)
                TWCR=(1<<TWEA)|TW_ACT;   //設(shè)定ACK,觸發(fā)下一步動(dòng)作
            }
            else
            {//準(zhǔn)備讀最后一個(gè)數(shù)據(jù)
                TWCR=TW_ACT;     //設(shè)定NAK,觸發(fā)下一步動(dòng)作
            }
        }
        else if(status==TW_MR_DATA_NACK)
        {//已經(jīng)讀完最后一個(gè)數(shù)據(jù)
            *strTWI.pBUF++=TWDR;
            TWCR=(1<<TWSTO)|TW_ACT;    //發(fā)送停止信號(hào),不會(huì)再產(chǎn)生中斷了
            strTWI.STATUS=TW_OK;
        }
        else
        {//讀取數(shù)據(jù)出錯(cuò)
            state=ST_FAIL;
        }
        break;
    case ST_WDATA: //寫(xiě)數(shù)據(jù)狀態(tài)檢查,只有寫(xiě)操作模式才能跳到這里
        state--;        //循環(huán),直到寫(xiě)完指定長(zhǎng)度數(shù)據(jù)
        if(status==TW_MT_DATA_ACK)
        {//寫(xiě)數(shù)據(jù)成功
            if (strTWI.DATALEN)
            {//還要寫(xiě)
                TWDR=*strTWI.pBUF++;
                strTWI.DATALEN--;
                TWCR=TW_ACT;            //觸發(fā)下一步動(dòng)作
            }
            else
            {//寫(xiě)夠了
                TWCR=(1<<TWSTO)|TW_ACT;   //發(fā)送停止信號(hào),不會(huì)再產(chǎn)生中斷了
                strTWI.STATUS=TW_OK;
                //啟動(dòng)寫(xiě)命令后需要10ms(最大)的編程時(shí)間才能真正的把數(shù)據(jù)記錄下來(lái)
                //編程期間器件不響應(yīng)任何命令
            }
        }
        else
        {//寫(xiě)數(shù)據(jù)失敗
            state=ST_FAIL;
        }
        break;
    default:
        //錯(cuò)誤狀態(tài)
        state=ST_FAIL;
        break;
    }

    if (state==ST_FAIL)
    {//錯(cuò)誤處理
        strTWI.FAILCNT++;
        if (strTWI.FAILCNT<FAIL_MAX)
        {//重試次數(shù)未超出最大值,
            TWCR=(1<<TWSTA)|TW_ACT;    //發(fā)生錯(cuò)誤,啟動(dòng)start信號(hào)
        }
        else
        {//否則停止
            TWCR=(1<<TWSTO)|TW_ACT;    //發(fā)送停止信號(hào),不會(huì)再產(chǎn)生中斷了
            strTWI.STATUS=TW_FAIL;
        }
    }
    state++;
    strTWI.STATE=state;       //保存狀態(tài)
}

int main(void)
{
    unsigned char i;
    //上電默認(rèn)DDRx=0x00,PORTx=0x00 輸入,無(wú)上拉電阻
    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ī)模式,該地址無(wú)效
    TWCR=0x00;         //關(guān)閉TWI模塊
    sei();          //使能全局中斷
    strTWI.STATUS=TW_OK;

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

        i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x00,&BUFFER[0],256);
        //從0x00地址開(kāi)始讀出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è)備都(必須)有自己的地址。
 注意:就是說(shuō)不能有兩個(gè)相同地址的設(shè)備
 TWI協(xié)議解決了總線仲裁的問(wèn)題。
 
 所有 TWI 兼容的器件的總線驅(qū)動(dòng)都是漏極開(kāi)路或集電極開(kāi)路的。這樣就實(shí)現(xiàn)了對(duì)接口操作非常關(guān)鍵的線與功能。
 TWI器件輸出為"0”時(shí),TWI總線會(huì)產(chǎn)生低電平。
 當(dāng)所有的TWI器件輸出為三態(tài)時(shí),總線會(huì)輸出高電平,允許上拉電阻將電壓拉高。
 注意:為保證所有的總線操作,凡是與TWI 總線連接的AVR 器件必須上電。
 
 與總線連接的器件數(shù)目受如下條件限制:
 總線電容要低于400pF,而且可以用7 位從機(jī)地址進(jìn)行尋址。
 兩個(gè)不同的規(guī)范,一種是總線速度低于100 kHz,而另外一種是總線速度高達(dá)400 kHz。
 
SCL和SDA引腳
 SCL與SDA為MCU的 TWI接口引腳。
 引腳的輸出驅(qū)動(dòng)器包含一個(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í)鐘信號(hào)SCL的周期。
 具體由TWI狀態(tài)寄存器TWSR的預(yù)分頻系數(shù)以及比特率寄存器TWBR設(shè)定。
 當(dāng)TWI工作在從機(jī)模式時(shí),不需要對(duì)比特率或預(yù)分頻進(jìn)行設(shè)定,但從機(jī)的CPU時(shí)鐘頻率必須大于TWI時(shí)鐘線SCL頻率的16倍。
注意,從機(jī)可能會(huì)延長(zhǎng)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ī)會(huì)在SDA 與 SCL 產(chǎn)生錯(cuò)誤輸出作為提示信號(hào)。
 問(wèn)題出現(xiàn)于TWI 工作在主機(jī)模式下,向從機(jī)發(fā)送Start + SLA + R/W 的時(shí)候(不需要真的有從機(jī)與總線連接)。
 
控制單元
 控制單元監(jiān)聽(tīng)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è)表示無(wú)事件發(fā)生的特殊狀態(tài)字。
 一旦TWINT 標(biāo)志位置"1”,時(shí)鐘線SCL 即被拉低,暫停TWI 總線上的數(shù)據(jù)傳輸,讓用戶程序處理事件。
 在下列狀況出現(xiàn)時(shí), TWINT 標(biāo)志位置位:
 ? 在TWI 傳送完START/REPEATED START 信號(hào)之后
 ? 在TWI 傳送完SLA+R/W 數(shù)據(jù)之后
 ? 在TWI 傳送完地址字節(jié)之后
 ? 在TWI 總線仲裁失敗之后
 ? 在TWI 被主機(jī)尋址之后( 廣播方式或從機(jī)地址匹配)
 ? 在TWI 接收到一個(gè)數(shù)據(jù)字節(jié)之后
 ? 作為從機(jī)工作時(shí), TWI 接收到STOP 或REPEATED START 信號(hào)之后
 ? 由于非法的START 或STOP 信號(hào)造成總線錯(cuò)誤時(shí)
 
TWI 寄存器說(shuō)明
 
TWI 比特率寄存器- TWBR
 ? Bits 7..0 – TWI 比特率寄存器
  TWBR 為比特率發(fā)生器分頻因子。
  比特率發(fā)生器是一個(gè)分頻器,在主機(jī)模式下產(chǎn)生SCL時(shí)鐘頻率。
  比特率計(jì)算公式請(qǐng)見(jiàn)前面的[比特率發(fā)生器單元]
 
TWI 控制寄存器- TWCR
 TWCR 用來(lái)控制TWI操作。
 它用來(lái)使能TWI,通過(guò)施加START到總線上來(lái)啟動(dòng)主機(jī)訪問(wèn),產(chǎn)生接收器應(yīng)答,產(chǎn)生STOP 狀態(tài),以及在寫(xiě)入數(shù)據(jù)到TWDR 寄存器時(shí)控制總線的暫停等。
 這個(gè)寄存器還可以給出在TWDR 無(wú)法訪問(wèn)期間,試圖將數(shù)據(jù)寫(xiě)入到TWDR 而引起的寫(xiě)入沖突信息。
 ? 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信號(hào)的低電平被延長(zhǎng)。
  TWINT 標(biāo)志的清零必須通過(guò)軟件寫(xiě)"1” 來(lái)完成。
  執(zhí)行中斷時(shí)硬件不會(huì)自動(dòng)將其改寫(xiě)為"0”。
  要注意的是,只要這一位被清零,TWI 立即開(kāi)始工作。
  因此,在清零TWINT 之前一定要首先完成對(duì)地址寄存器TWAR,狀態(tài)寄存器TWSR,以及數(shù)據(jù)寄存器TWDR 的訪問(wèn)。
 ? 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ù)地址識(shí)別。
 ? Bit 5 – TWSTA: TWI START 狀態(tài)標(biāo)志
  當(dāng)CPU 希望自己成為總線上的主機(jī)時(shí)需要置位TWSTA。
  TWI 硬件檢測(cè)總線是否可用。
  若總線空閑,接口就在總線上產(chǎn)生START 狀態(tài)。
  若總線忙,接口就一直等待,直到檢測(cè)到一個(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自動(dòng)清零。
  在從機(jī)模式下,置位TWSTO 可以使接口從錯(cuò)誤狀態(tài)恢復(fù)到未被尋址的狀態(tài)。
  此時(shí)總線上不會(huì)有STOP 狀態(tài)產(chǎn)生,但TWI 返回一個(gè)定義好的未被尋址的從機(jī)模式且釋放SCL 與SDA 為高阻態(tài)。
 ? Bit 3 – TWWC: TWI 寫(xiě)碰撞標(biāo)志
  當(dāng)TWINT 為低時(shí)寫(xiě)數(shù)據(jù)寄存器TWDR 將置位TWWC。
  當(dāng)TWINT 為高時(shí),每一次對(duì)TWDR 的寫(xiě)訪問(wèn)都將更新此標(biāo)志。
 ? Bit 2 – TWEN: TWI 使能
  TWEN 位用于使能TWI操作與激活TWI接口。
  當(dāng)TWEN位被寫(xiě)為"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位用來(lái)反映TWI 邏輯和總線的狀態(tài)。
  不同的狀態(tài)代碼將會(huì)在后面的部分描述。
  注意從TWSR 讀出的值包括5 位狀態(tài)值與2 位預(yù)分頻值。
  檢測(cè)狀態(tài)位時(shí)設(shè)計(jì)者應(yīng)屏蔽預(yù)分頻位為"0”。這使?fàn)顟B(tài)檢測(cè)獨(dú)立于預(yù)分頻器設(shè)置。
 ? Bits 1..0 – TWPS: TWI 預(yù)分頻位
  這兩位可讀/ 寫(xiě),用于控制比特率預(yù)分頻因子。
  預(yù)分頻系數(shù)為4的n次方
  計(jì)算比特率的公式見(jiàn)前面的[比特率發(fā)生器單元]
 
TWI 數(shù)據(jù)寄存器- TWDR
 在發(fā)送模式, TWDR 包含了要發(fā)送的字節(jié);
 在接收模式, TWDR 包含了接收到的數(shù)據(jù)。
 當(dāng)TWI 接口沒(méi)有進(jìn)行移位工作(TWINT 置位) 時(shí)這個(gè)寄存器是可寫(xiě)的。
 在第一次中斷發(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)容沒(méi)有定義。
 總線仲裁失敗時(shí),主機(jī)將切換為從機(jī),但總線上出現(xiàn)的數(shù)據(jù)不會(huì)丟失。
 ACK 的處理由 TWI邏輯自動(dòng)管理, CPU 不能直接訪問(wèn)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ī)訪問(wèn)自己。
 TWAR 的LSB 用于識(shí)別廣播地址 (0x00)。
 器件內(nèi)有一個(gè)地址比較器。一旦接收到的地址和本機(jī)地址一致,芯片就請(qǐng)求中斷。
 ? Bits 7..1 – TWA: TWI 從機(jī)地址寄存器
  其值為從機(jī)地址。
 ? Bit 0 – TWGCE: 使能TWI 廣播識(shí)別
  置位后MCU 可以識(shí)別TWI 總線廣播。
 
使用TWI
 AVR的TWI接口是面向字節(jié)和基于中斷的。
 所有的總線事件,如接收到一個(gè)字節(jié)或發(fā)送了一個(gè)START 信號(hào)等,都會(huì)產(chǎn)生一個(gè)TWI 中斷。
 由于TWI 接口是基于中斷的,因此TWI接口在字節(jié)發(fā)送和接收過(guò)程中,不需要應(yīng)用程序的干預(yù)。
 TWCR寄存器的TWI中斷允許位[TWIE]和全局中斷允許位[I]一起決定了應(yīng)用程序是否響應(yīng)TWINT標(biāo)志位產(chǎn)生的中斷請(qǐng)求。
 如果TWIE 被清零,應(yīng)用程序只能采用輪詢TWINT 標(biāo)志位的方法來(lái)檢測(cè)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)是否正確,并通過(guò)設(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特性有部分不同,請(qǐng)參考數(shù)據(jù)手冊(cè))
 1 AT24C02/04/08 是一個(gè)2K/4K/8K位串行CMOS E2PROM 內(nèi)部含有256/512/1024 個(gè)8位字節(jié)
 2 AT24C02有一個(gè)8 字節(jié)頁(yè)寫(xiě)緩沖器,AT24C04/08/16 有一個(gè)16字節(jié)頁(yè)寫(xiě)緩沖器
 3 通過(guò)器件地址輸入端A0,A1,A2可以實(shí)現(xiàn)將最多
  8個(gè)24C02器件
  4個(gè)24C04器件
  2個(gè)24C08器件
 

關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 欧美精品一区二区三区蜜桃视频 | 国外成人在线视频网站 | 在线日韩在线 | 欧美精品一区久久 | www久久国产 | 91成人免费 | 97超碰成人| 欧美精品一区在线观看 | 91福利在线导航 | www狠狠干 | 日韩欧美在线免费 | 中文字幕国产视频 | 亚洲在线一区 | 国产欧美一区二区三区久久 | 亚洲精品久久久一区二区三区 | 麻豆精品久久久 | 日韩久久综合 | 精品一区在线看 | 国产精品久久久久久久毛片 | 亚洲成人网在线 | 美女网站视频免费黄 | 国内精品视频在线 | 国产免费福利 | 欧美精品日韩精品 | 久久久久久久久久久一区二区 | 色婷婷精品久久二区二区蜜臂av | 国产japanhdxxxx麻豆 | 亚洲欧美精品 | 综合久久久 | 天天色天天色 | 日韩一区二区三区在线播放 | 久久一区二区三区四区 | 久久人爽 | 久色视频在线 | 亚洲精美视频 | av网站在线看 | 影音先锋欧美资源 | 国产亚洲欧美另类一区二区三区 | 中文字幕在线观看第一页 | 麻豆成人在线视频 | 久久精品中文字幕 |