新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > I2c程序 51系列及 AVR系列

        I2c程序 51系列及 AVR系列

        作者: 時間:2016-11-11 來源:網絡 收藏
        keil c編譯 51

        #define uchar unsigned char
        #define uint unsigned int
        #include "reg51.h"
        #include "intrins.h"

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

        sbit Scl=P3^3; //串行時鐘
        sbit Sda=P3^4; //串行數據

        /*發送起始條件*/
        void Start(void) /*起始條件*/
        {
        Sda=1;
        Scl=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Sda=0;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        }
        void Stop(void) /*停止條件*/
        {
        Sda=0;
        Scl=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Sda=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        }
        void Ack(void) /*應答位*/
        {
        Sda=0;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Scl=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Scl=0;
        }
        void NoAck(void) /*反向應答位*/
        {
        Sda=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Scl=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Scl=0;
        }
        void Send(uchar Data) /*發送數據子程序,Data為要求發送的數據*/
        {
        uchar BitCounter=8; /*位數控制*/
        uchar temp; /*中間變量控制*/
        do
        {
        temp=Data;
        Scl=0;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        if((temp&0x80)==0x80)/* 如果最高位是1*/
        Sda=1;
        else
        Sda=0;
        Scl=1;
        temp=Data<<1; /*RLC*/
        Data=temp;
        BitCounter--;
        }while(BitCounter);
        Scl=0;
        }
        uchar Read(void) /*讀一個字節的數據,并返回該字節值*/
        {
        uchar temp=0;
        uchar temp1=0;
        uchar BitCounter=8;
        Sda=1;
        do{
        Scl=0;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        Scl=1;
        _nop_ ();
        _nop_ ();
        _nop_ ();
        _nop_ ();
        if(Sda) /*如果Sda=1;*/
        temp=temp|0x01; /*temp的最低位置1*/
        else
        temp=temp&0xfe; /*否則temp的最低位清0*/
        if(BitCounter-1)
        { temp1=temp<<1;
        temp=temp1;
        }
        BitCounter--;
        }while(BitCounter);
        return(temp);
        }
        ////////////////////////////////////////////////
        void WrToROM(uchar Data[],uchar Address,uchar Num)
        {
        uchar i=0;
        uchar *PData;
        PData=Data;
        Start();
        Send(0xa0);
        Ack();
        Send(Address);
        Ack();
        for(i=0;i {
        Send(*(PData+i));
        Ack();
        }
        Stop();
        }
        void RdFromROM(uchar Data[],uchar Address,uchar Num)
        {
        uchar i=0;
        uchar *PData;
        PData=Data;
        for(i=0;i {
        Start();
        Send(0xa0);
        Ack();
        Send(Address+i);
        Ack();
        Start();
        Send(0xa1);
        Ack();
        *(PData+i)=Read();
        Scl=0;
        NoAck();
        Stop();
        }
        }

        /////////////////////////////////END of IIC/////////////////////////////////
        ////////////////////start of DS1621/////////////////////////////////
        void delay_ms(unsigned char temp)
        {
        while(temp--);
        }
        void temp_config(unsigned char temp)
        {

        Start();
        Send(0x90);
        Ack();
        Send(0xac);
        Ack();
        Send(temp);
        Ack();
        Stop();
        delay_ms(110);
        }


        void init_temp()
        {
        Scl=1; //串行時鐘
        Sda=1;
        Start();
        Send(0x90);
        Ack();
        Send(0xee);
        Ack();
        Stop();
        temp_config(8);
        }


        void read_temp() ////// Returns degrees F (0-255)
        {
        unsigned char datah,datal;

        ////溫度數據讀入開始
        Start(); //
        Send(0x90);
        Ack();
        Send(0xaa);
        Ack();
        Start();
        Send(0x91);
        Ack();
        datah=Read();
        Ack();
        datal=Read();
        Stop();
        ///溫度數據讀入結束
        if((datah&0x80)!=0)
        {
        word1[3]=-;
        datah=datah-1;
        datah=~datah;
        word1[4]=datah/100+48;
        word1[5]=((datah/10)%10)+48;
        word1[6]=datah%10+48;
        word1[7]=C;

        }
        else
        {
        word1[3]=+;
        word1[4]=datah/100+48;
        word1[5]=((datah/10)%10)+48;
        word1[6]=datah%10+48;
        word1[7]=C;

        }

        }


        AVR

        void Start() //I2C總線的開始條件
        {Set_SDA(1); //SDA=1;
        Set_SCL(1); //SCL=1;
        delay(100); //等待時鐘信號變高
        Set_SDA(0); //SDA=0;
        delay(100);
        Set_SCL(0); // SCL=0;
        }

        void Stop() //I2C總線結束條件
        {Set_SDA(0); //SDA=0;
        delay(100);
        Set_SCL(1); //SCL=1;
        delay(100); //等待時鐘信號變低
        Set_SDA(1); //SDA=1;
        delay(100);
        Set_SCL(0); //SCL=0;
        }

        void Ack() //I2C總線應答
        {Set_SDA(0); //SDA=0;
        delay(50);
        Set_SCL(1); //SCL=1;
        delay(100);
        Set_SCL(0); //SCL=0;
        delay(50);
        Set_SDA(1); //SDA=1;
        }

        void Nack() //I2C總線應答非
        {Set_SDA(1); //SDA=1;
        delay(50);
        Set_SCL(1); //SCL=1;
        delay(100);
        Set_SCL(0); //SCL=0;
        delay(50);
        Set_SDA(0); //SDA=0;
        }

        void Check_Ack() //I2C總線應答檢查
        {Set_SDA(1); //SDA=1;
        Set_SCL(1); //SCL=1;
        Ack_Flag=0; //清除應答標志;
        DDRA&=0xbf; //設置SDA為輸入
        if(!((PINA & 0x40)>>6))
        {delay(50);
        Set_SCL(0); //SCL=0;
        delay(100);}
        else
        {Ack_Flag=1; //收到應答;
        delay(50);
        Set_SCL(0); //SCL=0;
        delay(100);}
        DDRA |=0xff; //重新設置SDA為輸出
        }

        void Write_Bit0() //寫1bit數據:0
        {Set_SDA(0); //SDA=0;
        Set_SCL(1); //SCL=1;
        delay(100);
        Set_SCL(0); //SCL=0;
        }

        void Write_Bit1() //寫1bit數據:1
        {Set_SDA(1); //SDA=1;
        Set_SCL(1); //SCL=1;
        delay(100);
        Set_SCL(0); //SCL=0;
        Set_SDA(0); //SDA=0;
        }

        void Write_Byte(uchar Data) //寫一字節數據Data
        {uchar i;
        for(i=0;i<8;i++)
        {if(Data & 0x80) Write_Bit1(); //傳輸位從高位到低位,先傳最高位
        else Write_Bit0();
        Data <<=1;} //數據左移
        }

        uchar Read_Byte() //讀一字節數據:返回值即讀的數據
        {uchar Read_Data=0xff; // Read_Data為讀入的數據,初始值為0xff
        uchar j;
        for (j=0;j<8;j++)
        {Set_SDA(1);
        Set_SCL(1);
        DDRA &=0xbf;
        if((PINA & 0x40)==0)
        {Read_Data <<=1;
        Read_Data=(Read_Data & 0xfe);
        Set_SCL(0);}
        else
        {Read_Data <<=1;
        Read_Data =( Read_Data | 0x01);
        Set_SCL(0);}}
        DDRA |=0x40;
        return(Read_Data);
        }

        //***************************寫一字節數據****************************//
        //向從地址為Slave的IIC器件的Address地址寫一字節數據Data
        void Write_1byte(uchar Slave,uchar Address,uchar Data)
        {Start(); //開始
        Write_Byte(Slave); //寫I2C器件地址
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Write_Byte(Address); //送寄存器地址
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Write_Byte(Data); //寫入一字節數據
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Stop(); //停止
        }

        //***************************寫兩字節數據****************************//
        //向從地址為Slave的IIC器件的Address地址開始寫兩字節數據Data0,Data1
        void Write_2byte(uchar Slave,uchar Address,uchar Data0,uchar Data1)
        {Start(); //開始
        Write_Byte(Slave); //寫I2C器件地址
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Write_Byte(Address); //送寄存器地址
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Write_Byte(Data0);
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Write_Byte(Data1);
        do Check_Ack(); //檢查應答位
        while(Ack_Flag==1);
        Stop(); //停止信號
        }

        //***************************讀一字節數據****************************//
        //從從地址為Slave的IIC器件的Address地址處讀一字節數據
        uchar Read_1byte(uchar Slave,uchar Address)
        {uchar data0,x;
        do{
        Start(); //開始信號
        Write_Byte(Slave); //寫I2C器件地址
        Check_Ack(); //檢查應答位
        }while(Ack_Flag);
        do{
        Write_Byte(Address); //寫寄存器地址
        Check_Ack(); //檢查應答位
        }while(Ack_Flag);
        do{
        Start(); //開始
        Write_Byte(Slave+1); //寫I2C器件地址(+1表示為讀操作)
        Check_Ack(); //檢查應答位
        }while(Ack_Flag);
        data0=Read_Byte(); //讀1字節
        Nack(); //讀完發送一個Not Ack應答
        Stop(); //停止
        return data0; //返回讀取數據
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 监利县| 宽城| 福鼎市| 平安县| 吉隆县| 冀州市| 耒阳市| 二手房| 临安市| 大姚县| 保山市| 张家川| 库车县| 沙雅县| 潞西市| 永福县| 原阳县| 醴陵市| 神木县| 定安县| 济源市| 咸宁市| 无棣县| 平遥县| 城口县| 五大连池市| 韶山市| 城市| 云阳县| 牙克石市| 宜宾县| 嘉定区| 新兴县| 马公市| 莱州市| 会泽县| 区。| 伊通| 阜康市| 博野县| 包头市|