新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ATMEGA16通過TWI對24C02進行讀寫

        ATMEGA16通過TWI對24C02進行讀寫

        作者: 時間:2016-11-23 來源:網絡 收藏

        #ifndef TWI_H
        #define TWI_H

        本文引用地址:http://www.104case.com/article/201611/320227.htm

        //主機模式啟動狀態碼
        #define TWI_START 0X08
        #define TWI_RESTART 0X10
        //主機發送模式狀態碼
        #define TWI_MT_SLA_ACK 0X18 //SLA+W 已發送,接收到ACK
        #define TWI_MT_SLA_NACK 0X20 //SLA+W 已發送,接收到NOT ACK
        #define TWI_MT_DATA_ACK 0X28 //數據已發送,接收到ACK
        #define TWI_MT_DATA_NACK 0X30 //數據已發送,接收到NOT ACK
        #define TWI_MT_ARB_LOST 0X38 //SLA+W 或數據的仲裁失敗
        //主機接收模式狀態碼
        #define TWI_MR_ARB_LOST 0X38 //SLA+R 或數據的仲裁失敗
        #define TWI_MR_SLA_ACK 0X40 //SLA+R 已發送,接收到ACK
        #define TWI_MR_SLA_NACK 0X48 //SLA+R 已發送,接收到NOT ACK
        #define TWI_MR_DATA_ACK 0X50 //數據已接收,接收到ACK
        #define TWI_MR_DATA_NACK 0X58 //數據已接收,接收到NOT ACK
        //從機接收模式狀態碼
        #define TWI_SR_SLA_ACK 0X60 //自己的SLA+W 已經被接收,ACK 已返回
        #define TWI_SR_ARB_LOST_SLA_ACK 0X68 //SLA+R/W 作為主機的仲裁失敗;自己的SLA+W 已經被接收,ACK 已返回
        #define TWI_SR_GCALL_ACK 0X70 //接收到廣播地址,ACK 已返回
        #define TWI_SR_ARB_LOST_GCALL_ACK 0X78 //SLA+R/W 作為主機的仲裁失敗;接收到廣播地址ACK 已返回
        #define TWI_SR_DATA_ACK 0X80 //以前以自己的 SLA+W 被尋址;數據已經被接收ACK 已返回
        #define TWI_SR_DATA_NACK 0X88 //以前以自己的 SLA+W 被尋址;數據已經被接收NOT ACK 已返回
        #define TWI_SR_GCALL_DATA_ACK 0X90 //以前以廣播方式被尋址;數據已經被接收ACK 已返回
        #define TWI_SR_GCALL_DATA_NACK 0X98 //以前以廣播方式被尋址;數據已經被接收NOT ACK 已返回
        #define TWI_SR_STOP 0XA0 //在以從機工作時接收到STOP或重復START
        //從機發送模式狀態碼
        #define TWI_ST_SLA_ACK 0XA8 //自己的SLA+R 已經被接收ACK 已返回
        #define TWI_ST_ARB_LOST_SLA_ACK 0XB0 //SLA+R/W 作為主機的仲裁失敗;自己的SLA+R 已經被接收ACK 已返回
        #define TWI_ST_DATA_ACK 0XB8 //TWDR 里數據已經發送,接收到ACK
        #define TWI_ST_DATA_NACK 0XC0 //TWDR 里數據已經發送,接收到NOT ACK
        #define TWI_ST_LAST_DATA 0XC8 //TWDR 的一字節數據已經發送(TWAE = “0”);接收到ACK
        //其他狀態
        #define TWI_NO_INFO 0xF8 //沒有相關的狀態信息,TWINT=0
        #define TWI_BUS_ERROR 0x00 //由于非法的START或STOP引起的總線錯誤
        //TWI使用時的控制位
        #define TWI_Start() TWCR = (1< //清零TWINT、清零start狀態、使能TWI.發出START 信號
        #define TWI_Wait() while (!(TWCR & (1< //等待TWINT 置位, TWINT 置位表示START 信號已發出
        #define TWI_Status (TWSR & 0xF8) //檢驗TWI 狀態寄存器,屏蔽預分頻位
        #define TWI_Stop() TWCR=(1< //發送STOP 信號
        #define TWI_SendAck() (TWCR|=(1< //使能TWI應答
        #define TWI_SendNoAck() (TWCR&=~(1< //不使能TWI應答
        #define TWI_RcvNckByte() (TWCR=(1< //使能TWI不產生應答
        #define TWI_RcvAckByte() (TWCR=(1< //使能TWI、產生應答
        #define TWI_Writebyte(twi_d) {TWDR=(twi_d);TWCR=(1<// 定義TWI運行狀態的極性
        #define TWI_ERR 0
        #define TWI_CRR 1

        #define TWI_WRITE 0
        #define TWI_READ 1
        void delay(uint ms)
        {
        uint i,j;
        for(i=ms;i>0;i--)
        for(j=1141;j>0;j--);
        }

        void TWI_Init(void)
        {
        TWBR=0X0F;
        TWSR=0;
        }

        uchar TWIWait(void)
        {
        uchar i=100;
        while(!(TWCR&(1< //等待TWINT置1
        {
        if((--i)==0)
        return TWI_ERR;
        }
        return TWI_CRR;
        }

        uchar TWIStart(void)
        {
        TWI_Start();
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_START)
        return TWI_ERR;
        return TWI_CRR;
        }

        uchar TWIREStart(void)
        {
        TWI_Start();
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_RESTART)
        return TWI_ERR;
        return TWI_CRR;
        }

        uchar TWI_Write_WADDR(uchar addr)
        {
        TWI_Writebyte(addr);
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_MT_SLA_ACK)
        return TWI_ERR;
        return TWI_CRR;
        }


        uchar TWI_Write_RADDR(uchar addr)
        {
        TWI_Writebyte(addr);
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_MR_SLA_ACK)
        return TWI_ERR;
        return TWI_CRR;
        }


        uchar TWI_SendData(uchar data)
        {
        TWI_Writebyte(data);
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_MT_DATA_ACK)
        return TWI_ERR;
        return TWI_CRR;
        }

        uchar TWI_ReciveDATA_ACK(uchar *pdata)
        {
        TWI_RcvAckByte();
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_MR_DATA_ACK)
        return TWI_ERR;
        *pdata=TWDR;
        return TWI_CRR;
        }

        uchar TWI_ReciveDATA_NACK(uchar *pdata)
        {
        TWI_RcvNckByte();
        if(TWIWait()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Status!=TWI_MR_DATA_NACK)
        return TWI_ERR;
        *pdata=TWDR;
        return TWI_CRR;
        }

        uchar TWI_W_Byte(uchar Maddr,uchar Saddr,uchar data)
        {
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR) //保證寫入的SLA+W正確
        return TWI_ERR;
        if(TWI_SendData(Saddr)==TWI_ERR) //器件內寄存器的地址作為一般數據發送
        return TWI_ERR;
        if(TWI_SendData(data)==TWI_ERR) //發送要寫入的數據
        return TWI_ERR;
        TWI_Stop();
        return TWI_CRR;
        }

        uchar TWI_W_Data(uchar Maddr,uchar Saddr,uchar *pdata,uchar num)
        {
        uchar i;
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR) //保證寫入的SLA+W正確
        return TWI_ERR;
        if(TWI_SendData(Saddr)==TWI_ERR) //器件內寄存器的地址作為一般數據發送
        return TWI_ERR;
        for(i=0;i {
        if(TWI_SendData(*(pdata++))==TWI_ERR)
        return TWI_ERR;
        }
        TWI_Stop();
        return TWI_CRR;
        }

        uchar TWI_R_Byte(uchar Maddr,uchar Saddr,uchar *pdata)
        {
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR) //保證寫入的SLA+W正確
        return TWI_ERR;
        if(TWI_SendData(Saddr)==TWI_ERR) ////器件內寄存器的地址作為一般數據發送
        return TWI_ERR;
        if(TWIREStart()==TWI_ERR) //這里的重新發送start很重要,這里我們的主機不想放棄TWI的使用權 參看《深入淺出AVR單片機》289頁
        return TWI_ERR;
        if(TWI_Write_RADDR((Maddr&0xfe)|TWI_READ)==TWI_ERR) //參看《深入淺出AVR單片機》289頁
        return TWI_ERR;
        if(TWI_ReciveDATA_NACK(pdata)==TWI_ERR) //讀取數據時,最后1字節的數據讀取完成以后發送NAK而不是ACK
        return TWI_ERR;
        TWI_Stop();
        return TWI_CRR;
        }

        uchar TWI_R_Data(uint Maddr,uchar Saddr,uchar *pdata,uchar num)
        {
        uchar i;
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR)
        return TWI_ERR;
        if(TWI_SendData(Saddr)==TWI_ERR)
        return TWI_ERR;
        if(TWIREStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_RADDR((Maddr&0xfe)|TWI_READ)==TWI_ERR)
        return TWI_ERR;
        for(i=0;i {
        if(TWI_ReciveDATA_ACK(pdata+i)==TWI_ERR)
        return TWI_ERR;
        }
        if(TWI_ReciveDATA_NACK(pdata+i)==TWI_ERR) //讀取數據時,最后1字節的數據讀取完成以后發送NAK而不是ACK,這點很重要
        return TWI_ERR;
        TWI_Stop();
        return TWI_CRR;
        }

        uchar TWI_W_NAddr(uchar addr,uchar data)
        {
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_WADDR(addr)==TWI_ERR)
        return TWI_ERR;
        if(TWI_SendData(data)==TWI_ERR)
        return TWI_ERR;
        TWI_Stop();
        return TWI_CRR;
        }

        uchar TWI_R_NAddr(uchar addr,uchar *pdata)
        {
        if(TWIStart()==TWI_ERR)
        return TWI_ERR;
        if(TWI_Write_RADDR(addr)==TWI_ERR)
        return TWI_ERR;
        if(TWI_ReciveDATA_NACK(pdata)==TWI_ERR)
        return TWI_ERR;
        TWI_Stop();
        return TWI_CRR;
        }
        #endif


        #include
        #include "IIC.h"
        void port_init(void)
        {
        DDRB=0XFF;
        PORTB=0XFF;
        TWCR=0X44;
        DDRD=0XFF;
        PORTD=0XFF;
        }

        uchar temp1[8]={18,17,16,15,14,13,12,11};
        uchar temp2[8]={0};
        uchar temp3[8]={0,0,0,0,0,0,0,0};
        void main(void)
        {
        TWI_Init();
        port_init();
        if(TWI_W_Data(0Xa0,0x00,temp1,8)==TWI_ERR)
        PORTD&=~(BIT(PD0));
        delay(5); //這里的延時很重要,如果不加,讀出來的數據很是匪夷所思
        if((TWI_R_Data(0Xa1,0x00,temp2,8))==TWI_ERR)
        PORTD&=~BIT(PD7);
        if(temp2[1]==17)
        PORTB=0X00;
        while(1)
        {
        if(temp2[0]==18)
        {
        PORTB=0XFE;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }
        if(temp2[1]==17)
        {
        PORTB=0XFD;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }
        if(temp2[2]==16)
        {
        PORTB=0XFB;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }

        if(temp2[3]==15)
        {
        PORTB=0XF7;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }

        if(temp2[4]==14)
        {
        PORTB=0XEF;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }

        if(temp2[5]==13)
        {
        PORTB=0XDF;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }

        if(temp2[6]==12)
        {
        PORTB=0XBF;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }

        if(temp2[7]==11)
        {
        PORTB=0X7F;
        delay(100);
        PORTB=0XFF;
        delay(50);
        }
        }
        }

        仿真PROTUES7.5圖如下



        示波器查看波形如圖


        IIC接收數據查看如圖


        關鍵詞: ATMEGA16TWI24C0

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 稻城县| 台前县| 民县| 阳西县| 稻城县| 珲春市| 罗平县| 山东省| 宝坻区| 长子县| 义乌市| 郓城县| 宜昌市| 都昌县| 鄂尔多斯市| 安溪县| 逊克县| 额尔古纳市| 云浮市| 江西省| 巍山| 湾仔区| 纳雍县| 莱芜市| 河津市| 亚东县| 子长县| 阿克| 沭阳县| 富宁县| 门头沟区| 开江县| 通辽市| 海丰县| 民乐县| 穆棱市| 尼勒克县| 霸州市| 阿城市| 南皮县| 萝北县|