對I2C總線上掛接多個AT24C02的讀寫操作

2021-03-06 電氣自動化資料庫

#include <reg51.h>         //  包含51單片機寄存器定義的頭文件

#include <intrins.h>       //包含_nop_()函數定義的頭文件

#defineOP_READ10xa1// 器件1地址以及讀取操作,0xa1即為1010 0001B

#defineOP_WRITE1 0xa0// 器件1地址以及寫入操作,0xa1即為1010 0000B

#defineOP_READ20xaf// 器件2地址以及讀取操作,0xa1即為1010 1111B

#defineOP_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++)// 循環移入8個位

{

    SDA = (bit)(y&0x80);   //通過按位「與」運算將最高位數據送到S

                      //因為傳送時高位在前,低位在後

_nop_();              //等待一個機器周期   

   SCL = 1;              //在SCL的上升沿將數據寫入AT24Cxx      

   _nop_();              //等待一個機器周期

  _nop_();               //等待一個機器周期       

  SCL = 0;              //將SCL重新置為低電平,以在SCL線形成傳送數據所需的8個脈衝

y <<= 1;              //將y中的各二進位向左移一位

}

SDA = 1;  // 發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)釋放SDA線,

                //以讓SDA線轉由接收設備(AT24Cxx)控制

_nop_();        //等待一個機器周期

_nop_();        //等待一個機器周期

SCL = 1;       //根據上述規定,SCL應為高電平

_nop_();       //等待一個機器周期

_nop_();       //等待一個機器周期

_nop_();       //等待一個機器周期

_nop_();       //等待一個機器周期

ack_bit = SDA; //接受設備(AT24Cxx)向SDA送低電平,表示已經接收到一個字節

               //若送高電平,表示沒有接收到,傳送異常

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個字節的寫入周期為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個字節的寫入周期為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,使主從設備處於空閒狀態

SCL = 1;         

   WriteSet1(0x36,0xaa);   //將數據"0xaa"寫入第一個AT24C02的指定地址"0x36"

x=ReadSet1(0x36);       //從第二個AT24C02中的指定地址"0x36"讀出數據  

   WriteSet2(0x48,x);      //將讀出的數據寫入第二個AT24C02的指定地址"0x48"?

P1=ReadSet2(0x48);      //將從第二個AT24C02的指定地址讀出的數據送P1口顯示驗證

}

相關焦點

  • RT-Thread設備框架使用指南——I2C 總線設備
    SPI 總線有兩根線分別用於主從設備之間接收數據和發送數據,而 I2C 總線只使用一根線進行數據收發。I2C 和 SPI 一樣以主從的方式工作,不同於 SPI 一主多從的結構,它允許同時有多個主設備存在,每個連接到總線上的器件都有唯一的地址,主設備啟動數據傳輸並產生時鐘信號,從設備被主設備尋址,同一時刻只允許有一個主設備。
  • Linux驅動之I2C總線
    明確:struct i2c_board_info的分配,初始化和註冊三個步驟必須在平臺代碼中完成,不能以模塊加載的形式來實現! 對struct i2c_board_info的操作本質就是間接的在操作i2c_client。
  • 基於I2C總線性能問答集錦
    [問:lljiang] 當i2c總線接多個slave設備時,可以直接連接麼?[答:Alex] 我不是很清楚你的直接連接是是指什麼,但所有的slave設備都是並聯在總線上,是直接連接的[問:huanggang] I2C 總線SDA信號雙向隔離實現電路?
  • RT-Thread I2C總線設備學習筆記
    如何看懂時序圖(以SPI/I2C為例)淺談總線通信機制(通信基礎+串口+I2C)我們接下來將基於小熊派開發平臺進行實踐。當在串口終端輸入bh1750_cmd off數據關閉列印,協議數據停止列印,底板+光強模塊上的高亮LED燈熄滅。
  • I2C總線要點總結
    導致 NACK 產生的條件有五個:總線上沒有報文中所包含地址的接收器,因此沒有設備響應應答。接收器無法執行接收或發送操作,比如它正在執行某些實時功能,並且尚未準備好與主機進行通信。在傳輸過程中,接收器收到應用協議不理解的數據或命令。
  • STM32CubeMx入門教程(7) I2C的讀寫應用
    導語「本次 教程使用CubeMx配置I2C進行I2C總線設備的數據讀寫操作,使用EEPROM作為實驗對象」01--
  • 乾貨總結:I2C總線詳細要點
    導致 NACK 產生的條件有五個:總線上沒有報文中所包含地址的接收器,因此沒有設備響應應答。接收器無法執行接收或發送操作,比如它正在執行某些實時功能,並且尚未準備好與主機進行通信。在傳輸過程中,接收器收到應用協議不理解的數據或命令。
  • spi與i2c總線有什麼區別
    在主從通信中,可以有多個I2C總線器件同時接到I2C總線 上,通過地址來識別通信對象。   I2C 接口的協議裡面包括設備地址信息,可以同一總線上連接多個從設備,通過應答來互通數據及命令。但是傳輸速率有限,標準模式下可達到100Kbps,快速模式下可達到400Kbps(我們開發板一般在130Kbps),高速模式下達到4Mbps,不能實現全雙工,不適合傳輸很多的數據。
  • STM32F10x_硬體I2C讀寫EEPROM(標準外設庫版本)
  • TMS320VC5410A I/O口的多種擴展與I2C接口模擬
    2 模擬i2c接口與tlv320aic23的通信 2.1 i2c接口和tlv320aic23簡介 i2c(inter-integrated circuit)總線是一種由philips公司開發的兩線式串行總線,用於連接微控制器及其外圍設備。
  • 對I2C信號和SMBus信號進行無毛刺快速隔離的方法
    i2c 是一種流行的串行協議,適用於電源控制器、adc、dac、eeprom 以及其他器件。在某些數據採集和電源控制設備中,您必須把 i2c主設備與一個或多個從設備隔離開來,以便解決噪聲、接地和安全等問題。
  • 基於I2C總線技術的USB接口設計
    2.2 I2C總線技術介紹         I2C總線技術是Philips公司研製出來的串行擴展技術。他是一種簡單、雙向二線制同步串 行總線,他只需要2根線(串行時鐘線SCL和串行數據線SDA)即可在連接於總線上的器件之 間傳送信息。
  • CAN、I2S、I2C、SPI、SSP總線對比
    這就保證不會出現象在RS-485網絡中,當系統有錯誤,出現多節點同時向總線發送數據時,導致總線呈現短路,從而損壞某些節點的現象。而且CAN節點在錯誤嚴重的情況下具有自動關閉輸出功能,以使總線上其他節點的操作不受影響,從而保證不會出現象在網絡中,因個別節點出現問題,使得總線處於「死鎖」狀態。
  • PIC單片機之I2C總線
    現在我們就趁熱打鐵,再向上跨一步,一起來學習一下I2C 總線的工作原理及使用方法,這樣我們可以將一些我們要保存的數據存儲到I2C總線的非易失存儲器中,實現斷電保持的功能,比如:你設置了一個密碼,但不至於這個設備斷過電以後就要重新設置過,我們可以將密碼數據寫在非易失存儲器裡面,還有如汽車的量程表的讀數是不斷累計的,可以通過不斷訪問I2C 存儲器實現。
  • 邏輯分析儀的簡單使用介紹(附帶i2c、串口、spi數據分析)
    1、IIC數據解析      開始之前,以AT24C02讀寫為例,先對I2C協議進行一點簡介,熟悉的大佬自行跳過哈。IIC(Inter-Integrated Circuit)總線是一種由 PHILIPS 公司開發的兩線式串行總線,用於連接微控制器及其外圍設備。它是由數據線 SDA 和時鐘 SCL 構成的串行總線,可發送和接收數據。
  • 片上總線Wishbone 學習(十)總線周期之塊讀操作
    圖10的塊操作由五次讀操作完成,其過程如下:在時鐘上升沿0,主設備將地址信號ADR_O()、TGA_O()放到總線上,將WE_O置為低表示讀操作,將適當的SEL_O()信號置高通知從設備將數據放在數據總線的適當位置,將CYC_O和TGC_O
  • 5分鐘了解單片機數據、地址、控制總線結構!
    > 計算機系統是以微處理器為核心的,各器件要與微處理器相連,且必須協調工作,所以在微處理機中引入了總線的概念,各器件共同享用總線,任何時候只能有一個器件發送數據(可以有多個器件同時接收數據) 。 從圖2 中可以看出,完成一次總線( 讀寫) 操作周期為T,P0 口分時復用,在T0 期間,P0 口送出低8 位地址,在ALE 的下降沿完成數據鎖存,送出低8位地址信號。
  • 詞彙解讀時鐘周期、機器周期、指令周期、總線周期,看完此文不許說分不清了!
    怎麼還沒讓你說頭上就開始轉星星了!接著往下看保證頭上的星星挨個偷偷溜走!例如,取指令、存儲器讀、存儲器寫等,這每一項工作稱為一個基本操作,完成一個基本操作所需要的時間稱為機器周期。一般情況下,一個機器周期由若干個S周期(狀態周期)組成。8051系列單片機的一個機器周期由6個S周期(狀態周期)組成。
  • AHB總線協議
    1.1 AHB總線的架構AHB總線的強大之處在於它可以將微控制器(CPU)、高帶寬的片上RAM、高帶寬的外部存儲器接口、DMA總線master、各種擁有AHB接口的控制器等等連接起來構成一個獨立的完整的SOC系統,不僅如此,還可以通過AHB-APB橋來連接APB總線系統。AHB可以成為一個完整獨立的SOC晶片的骨架。