電子產業(yè)一站式賦能平臺

PCB聯盟網

搜索
查看: 2307|回復: 0
收起左側

單片機C語言實例-353-對I2C總線上掛接多個AT24C02的讀寫操作

[復制鏈接]
跳轉到指定樓層
樓主
發(fā)表于 2022-4-2 09:22:30 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
單片機C語言實例-353-對I2C總線上掛接多個AT24C02的讀寫操作

//實例87:對I2C總線上掛接多個AT24C02的讀寫操作
#include <reg51.h>         //  包含51單片機寄存器定義的頭文件
#include <intrins.h>       //包含_nop_()函數定義的頭文件
#define        OP_READ1        0xa1                // 器件1地址以及讀取操作,0xa1即為1010 0001B
#define        OP_WRITE1 0xa0                // 器件1地址以及寫入操作,0xa1即為1010 0000B
#define        OP_READ2        0xaf                // 器件2地址以及讀取操作,0xa1即為1010 1111B
#define        OP_WRITE2 0xae                // 器件2地址以及寫入操作,0xa1即為1010 1110B
sbit SDA=P3^4;             //將串行數據總線SDA位定義在為P3.4引腳
sbit SCL=P3^3;             //將串行時鐘總線SDA位定義在為P3.3引腳
/*****************************************************
函數功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;       
         for(i=0;i<10;i++)
          for(j=0;j<33;j++)
           ;                 
}
/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delaynms(unsigned char n)
{
   unsigned char i;
        for(i=0;i<n;i++)
           delay1ms();
}
/***************************************************
函數功能:開始數據傳送
***************************************************/
void start()
// 開始位
{
        SDA = 1;    //SDA初始化為高電平“1”
        SCL = 1;    //開始數據傳送時,要求SCL為高電平“1”
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        SDA = 0;    //SDA的下降沿被認為是開始信號
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        SCL = 0;    //SCL為低電平時,SDA上數據才允許變化(即允許以后的數據傳遞)
        _nop_();    //等待一個機器周期
}
/***************************************************
函數功能:結束數據傳送
***************************************************/
void stop()
// 停止位
{
        SDA = 0;     //SDA初始化為低電平“0”
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        SCL = 1;     //結束數據傳送時,要求SCL為高電平“1”
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        SDA = 1;    //SDA的上升沿被認為是結束信號       
}
/***************************************************
函數功能:從AT24Cxx讀取數據
出口參數:x
***************************************************/
unsigned char ReadData()
// 從AT24Cxx移入數據到MCU
{
        unsigned char i;
        unsigned char x;           //儲存從AT24Cxx中讀出的數據
        for(i = 0; i < 8; i++)
        {
                SCL = 1;                //SCL置為高電平
                x<<=1;                  //將x中的各二進位向左移一位
                x|=(unsigned char)SDA;  //將SDA上的數據通過按位“或“運算存入x中
                SCL = 0;               //在SCL的下降沿讀出數據
        }
        return(x);                //將讀取的數據返回
}
/***************************************************
函數功能:向AT24Cxx的當前地址寫入數據
入口參數:y (儲存待寫入的數據)
***************************************************/
//在調用此數據寫入函數前需首先調用開始函數start(),所以SCL=0
bit WriteCurrent(unsigned char y)
{
        unsigned char i;
        bit ack_bit;               //儲存應答位
        for(i = 0; i < 8; i++)                // 循環(huán)移入8個位
        {
            SDA = (bit)(y&0x80);   //通過按位“與”運算將最高位數據送到S
                                      //因為傳送時高位在前,低位在后
                _nop_();              //等待一個機器周期   
           SCL = 1;              //在SCL的上升沿將數據寫入AT24Cxx      
           _nop_();              //等待一個機器周期
          _nop_();               //等待一個機器周期      
               
                  SCL = 0;              //將SCL重新置為低電平,以在SCL線形成傳送數據所需的8個脈沖
                y <<= 1;              //將y中的各二進位向左移一位
        }
        SDA = 1;                          // 發(fā)送設備(主機)應在時鐘脈沖的高電平期間(SCL=1)釋放SDA線,
                        //以讓SDA線轉由接收設備(AT24Cxx)控制
        _nop_();        //等待一個機器周期
        _nop_();        //等待一個機器周期
        SCL = 1;       //根據上述規(guī)定,SCL應為高電平
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        ack_bit = SDA; //接受設備(AT24Cxx)向SDA送低電平,表示已經接收到一個字節(jié)
                       //若送高電平,表示沒有接收到,傳送異常
        SCL = 0;       //SCL為低電平時,SDA上數據才允許變化(即允許以后的數據傳遞)
        return  ack_bit;// 返回AT24Cxx應答位
}
/***************************************************
函數功能:向第一個AT24Cxx中的指定地址寫入數據
入口參數:add (儲存指定的地址);dat(儲存待寫入的數據)
***************************************************/
void WriteSet1(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數據WriteCurrent
{
        start();                  //開始數據傳遞
        WriteCurrent(OP_WRITE1);  //選擇要操作的第一個AT24Cxx芯片,并告知要對其寫入數據
        WriteCurrent(add);        //寫入指定地址
        WriteCurrent(dat);        //向當前地址(上面指定的地址)寫入數據
        stop();                   //停止數據傳遞
        delaynms(4);                   //1個字節(jié)的寫入周期為1ms, 最好延時1ms以上
}
/***************************************************
函數功能:向第二個AT24Cxx中的指定地址寫入數據
入口參數:add (儲存指定的地址);dat(儲存待寫入的數據)
***************************************************/
void WriteSet2(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數據WriteCurrent
{
        start();                  //開始數據傳遞
        WriteCurrent(OP_WRITE2);  //選擇要操作的AT24Cxx芯片,并告知要對其寫入數據
        WriteCurrent(add);        //寫入指定地址
        WriteCurrent(dat);        //向當前地址(上面指定的地址)寫入數據
        stop();                   //停止數據傳遞
        delaynms(4);                   //1個字節(jié)的寫入周期為1ms, 最好延時1ms以上
}
/***************************************************
函數功能:從第一個AT24Cxx中的當前地址讀取數據
出口參數:x (儲存讀出的數據)
***************************************************/
unsigned char ReadCurrent1()
{
        unsigned char x;
        start();                   //開始數據傳遞
        WriteCurrent(OP_READ1);   //選擇要操作的第一個AT24Cxx芯片,并告知要讀其數據
        x=ReadData();             //將讀取的數據存入x
        stop();                   //停止數據傳遞
        return x;                 //返回讀取的數據
}

/***************************************************
函數功能:從第二個AT24Cxx中的當前地址讀取數據
出口參數:x (儲存讀出的數據)
***************************************************/
unsigned char ReadCurrent2()
{
        unsigned char x;
        start();                   //開始數據傳遞
        WriteCurrent(OP_READ2);    //選擇要操作的第二個AT24Cxx芯片,并告知要讀其數據
        x=ReadData();              //將讀取的數據存入x
        stop();                    //停止數據傳遞
        return x;                  //返回讀取的數據
}
/***************************************************
函數功能:從第一個AT24Cxx中的指定地址讀取數據
入口參數:set_addr
出口參數:x
***************************************************/
unsigned char ReadSet1(unsigned char set_addr)
// 在指定地址讀取
{
        start();                      //開始數據傳遞
        WriteCurrent(OP_WRITE1);       //選擇要操作的第一個AT24Cxx芯片,并告知要對其寫入數據
        WriteCurrent(set_addr);       //寫入指定地址
        return(ReadCurrent1());        //從第一個AT24Cxx芯片指定地址讀出數據并返回
}
/***************************************************
函數功能:從第二個AT24Cxx中的指定地址讀取數據
入口參數:set_addr
出口參數:x
***************************************************/
unsigned char ReadSet2(unsigned char set_addr)
// 在指定地址讀取
{
        start();                       //開始數據傳遞
        WriteCurrent(OP_WRITE2);       //選擇要操作的第二個AT24Cxx芯片,并告知要對其寫入數據
        WriteCurrent(set_addr);        //寫入指定地址
        return(ReadCurrent2());        //從第二個AT24Cxx芯片指定地址讀出數據并返回
}
/***************************************************
函數功能:主函數
***************************************************/
main(void)
{
   unsigned char x;
   SDA = 1;           // SDA=1,SCL=1,使主從設備處于空閑狀態(tài)
        SCL = 1;                 
   WriteSet1(0x36,0xaa);   //將數據"0xaa"寫入第一個AT24C02的指定地址"0x36"
        x=ReadSet1(0x36);       //從第二個AT24C02中的指定地址"0x36"讀出數據  
   WriteSet2(0x48,x);      //將讀出的數據寫入第二個AT24C02的指定地址"0x48"?
        P1=ReadSet2(0x48);      //將從第二個AT24C02的指定地址讀出的數據送P1口顯示驗證
}


更多詳情參考附件文檔

游客,如果您要查看本帖隱藏內容請回復

回復

使用道具 舉報

發(fā)表回復

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯系客服 關注微信 下載APP 返回頂部 返回列表