新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51單片機 I2C AT24C02

        51單片機 I2C AT24C02

        作者: 時間:2016-11-25 來源:網絡 收藏
        I2C協議在項目開發中使用很常見,很多存儲芯片使用I2C接口。由于51單片機沒有I2C接口,這里使用IO口模擬I2C通訊協議,來完成I2C芯片驅動。使用的I2C芯片為AT24C02

        原理圖如下:

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



        代碼如下:

        //程序功能:計時器每一秒向AT24C02保持數據,同時數碼管顯示,重啟之后讀取出數據接著計時,100S循環
        //程序問題:無法寫入
        #include
        #define uint unsigned int
        #define uchar unsigned char
        //變量定義
        uint timer_flag; //用于判斷定時器T0方式一是否計滿1s
        uchar shiwei,gewei; //數碼管顯示的十位與個位
        uint number;
        uchar time_date; //當前時間數據
        //控制端口聲明
        sbit duanxuan=P2^6; //數碼管段選端
        sbit weixuan=P2^7; //數碼管位選端
        sbit AT24C02_SDA=P2^0; //AT24C02串行數據輸入輸出端口
        sbit AT24C02_SCLK=P2^1; //時鐘信號端口
        //數碼管顯示數字段碼定義
        uchar code table[]={
        0x3f,0x06,0x5b,0x4f,
        0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,
        0x39,0x5e,0x79,0x71};
        //相關函數聲明
        void delay_minute(); //延時us級函數聲明
        void delay_xs(uint); //延時s級函數聲明
        void timer_init(); //定時器T0方式一初始化函數聲明
        void AT24C02_init(); //I^2C通訊總線初始化函數聲明
        void star(); //I^2C通訊啟動函數聲明
        void stop(); //I^2C通訊停止函數聲明
        void response(); //應答函數聲明
        void write_in_byte(uchar); //寫入一個字節函數聲明
        uchar read_out_byte(); //讀出一個字節函數聲明,函數放回到讀出的值
        //注意寫入一個字節與寫入數據的區別,前者是后者的一個子過程,讀取同
        void saveing(uchar,uchar); //向AT24C02保存數據函數聲明
        uchar load(uchar); //從AT24C02載入掉電之前的數據,函數放回到讀出的值
        void quwei(uchar); //顯示數字取出各位與十位
        void display(uchar); //數碼管顯示函數聲明
        //主函數
        void main()
        {
        AT24C02_init(); //AT24C02初始化
        time_date=load(3); //開機首先載入AT24C02中的數據,這里讀取的是第三位址的數據
        if(time_date>100) //防止上一次保存的數據是100,這里計時是100循環的
        {
        time_date=1;
        }
        timer_init(); //計時器T0方式一初始化
        while(1)
        {
        display(time_date); //顯示時間
        if(timer_flag==1) //如果計滿一秒,就保存時間數據
        {
        timer_flag=0;
        saveing(3,time_date); //保存時間數據
        }
        }
        }
        //延時us級函數主體
        void delay_minute()
        {;;}
        //延時s級函數主體
        void delay_xs(uint s)
        {
        uint i,j;
        for(i=s;i>0;i--)
        {
        for(j=110;j>0;j--)
        {
        }
        }
        }
        //定時器T0方式一初始化函數主體
        void timer_init()
        {
        //方式選擇
        TMOD=0x01;
        //預裝初值
        TH0=(65536-46080)/256;
        TL0=(65536-46080)%6;
        //開中斷
        EA=1;
        ET0=1;
        //啟動定時器
        TR0=1;
        }
        //I^2C通訊總線初始化函數主體
        void AT24C02_init() //兩線均寫1 AT24C02數據有效規則,sclk為高電平且sda數據穩定,當sda發生有效數據變化時,sclk必須要是0
        {
        AT24C02_SDA=1;
        delay_minute();
        AT24C02_SCLK=1;
        delay_minute();
        }
        //I^2C通訊啟動函數主體
        void star() //啟動規則:SCLK-1,SDA下降沿
        {
        AT24C02_SDA=1; //一定要SDA首先為1,再是SCLK為1,否則會出現一個停止信號
        delay_minute();
        AT24C02_SCLK=1;
        delay_minute();
        AT24C02_SDA=0;
        delay_minute();
        }
        //I^2C通訊停止函數主體
        void stop() //停止規則:SCLK-1,SDA上升沿
        {
        AT24C02_SDA=0; //一定要SDA首先為0,再是SCLK為1,否則會出現一個啟動信號
        delay_minute();
        AT24C02_SCLK=1;
        delay_minute();
        AT24C02_SDA=1;
        delay_minute();
        }
        //應答函數主體
        void response() //應答規則:SCLK-1,等待從機把SDA拉低
        {
        uint i;
        AT24C02_SCLK=1;
        delay_minute();
        while(AT24C02_SDA==1&&i<255)//等待從機把SDA拉低,且超過一定時間沒有應答,默認已經應答
        {
        i++;
        }
        AT24C02_SCLK=0; //應答之后,SCLK-0.防止數據誤操作,因為SCLK-1,數據就是有效地
        delay_minute();
        }
        //寫入一個字節函數主體
        void write_in_byte(uchar date)
        {
        uint i,buffer; //i用于循環發送每一位,buffer緩沖數據
        buffer=date;
        for(i=0;i<8;i++)
        {
        buffer=buffer<<1; //buffer左旋,高位就放入CY
        AT24C02_SCLK=0; //有效發送規則:sclk-0變化數據,sclk-1數據穩定后有效
        delay_minute();
        AT24C02_SDA=CY;
        delay_minute();
        AT24C02_SCLK=1;
        delay_minute();
        }
        AT24C02_SCLK=0; //不發送,一定是SCLK-0,SDA-1
        delay_minute();
        AT24C02_SDA=1;
        delay_minute();
        }
        //讀出一個字節函數主體
        uchar read_out_byte() //讀出規則:啟動-控制字片選+寫(為了寫入要讀取的地址)-應答-寫入存儲地址-應答-讀取數據-應答-停止
        {
        uchar i,buffer_writting;
        //--------------------------------------------------
        //不能少的
        AT24C02_SCLK=0; //方便SDA數據發生有效變化
        delay_minute();
        AT24C02_SDA=1;
        delay_minute();
        //--------------------------------------------------
        for(i=0;i<8;i++)
        {
        AT24C02_SCLK=1;
        delay_minute();
        buffer_writting=(buffer_writting<<1)|AT24C02_SDA;//buffer_writting左旋之后與AT24C02_SDA的數據線與
        delay_minute();
        AT24C02_SCLK=0;
        delay_minute();

        }
        return buffer_writting;
        }
        //向AT24C02保存數據函數主體
        void saveing(uchar address,uchar time_date0) //寫入字節規則:啟動-控制字片選+寫-應答-寫入存儲地址-應答-寫入數據-應答-停止
        {
        star(); //啟動信號
        write_in_byte(0xa0);
        response();
        write_in_byte(address);
        response();
        write_in_byte(time_date0);
        response();
        stop();
        }
        //從AT24C02載入掉電之前的數據函數主體
        uchar load(uchar address) //讀出規則:啟動-控制字片選+寫(為了寫入要讀取的地址)-應答-寫入存儲地址-應答-讀取數據-應答-停止
        {
        uchar time_date_former;
        star();
        write_in_byte(0xa0);
        response();
        write_in_byte(address);
        response();
        time_date_former=read_out_byte();
        stop();
        return time_date_former;
        }
        //顯示數字取出各位與十位函數主體
        void quwei(uchar quwei_date)
        {
        shiwei=quwei_date/10;
        gewei=quwei_date;
        }
        //數碼管顯示函數函數主體
        void display(uchar display_date)
        {
        quwei(display_date);
        //顯示第一個數碼管
        duanxuan=1;
        P0=table[shiwei];
        duanxuan=0;
        P0=0xff;
        weixuan=1;
        P0=0xfe;
        weixuan=0;
        delay_xs(2);
        //顯示第二的數碼管
        duanxuan=1;
        P0=table[gewei];
        duanxuan=0;
        P0=0xff;
        weixuan=1;
        P0=0xfd;
        weixuan=0;
        delay_xs(2);
        }
        //T0定時器方式一中斷服務程序
        void T0_timer_no1() interrupt 1
        {
        //預裝初值
        TH0=(65536-46080)/256;
        TL0=(65536-46080)%6;
        number++;
        if(number==20) //20次計滿就是1s
        {
        number=0;
        time_date++; //時間累加
        timer_flag=1; //計滿一次就保存數據
        if(time_date==100) //100s循環計時
        {
        time_date=0;
        }
        }
        }
        以上,結束。



        關鍵詞: 51單片機I2CAT24C0

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 馆陶县| 观塘区| 马关县| 崇明县| 乡宁县| 和田县| 邛崃市| 偏关县| 岳阳县| 榆中县| 喀什市| 合作市| 尉氏县| 南陵县| 彭山县| 江永县| 冷水江市| 武隆县| 成武县| 齐河县| 依兰县| 河津市| 呼图壁县| 新和县| 石首市| 辉南县| 大足县| 多伦县| 黔西县| 交口县| 蓬安县| 静乐县| 临桂县| 澄城县| 松原市| 合肥市| 寿光市| 安化县| 景洪市| 若羌县| 东丰县|