歡迎您光臨本站 登入註冊首頁

I2C的讀寫操作實驗

admin @ 2014-03-25 , reply:0

概述

[實驗任務]  利用24C08斷電以後存儲的數據不消失的特點,可以做一個斷電保護裝置。首先利用單片機做一個0-99秒的自動計時器。然後隨機關斷電源,在通電以後計時器接著斷電前的狀態……

[實驗任務]
   利用24C08斷電以後存儲的數據不消失的特點,可以做一個斷電保護裝置。首先利用單片機做一個0-99秒的自動計時器。然後隨機關斷電源,在 通電以後計時器接著斷電前的狀態繼續計時。

[實驗原理]
    首先簡單的說明以下I2C匯流排,I2C匯流排是一種串列數據匯流排,只有二根信號線,一根是雙向的數據線SDA,另一根是時鐘線SCL。在 I2C匯流排上傳送的一個數據位元組由八位組成。匯流排對每次傳送的位元組數沒有限制,但每個位元組后必須跟一位應答位。數據傳送首先傳送最高位(MSB),數據傳送按圖1所示格式進行。首先由主機發出啟動信號“S”(SDA在SCL高電平期間由高電平跳變為低電平),然後由主機發送一個位元組的數據。啟動信號后的第一個位元組數據具有特殊含義:高七位是從機的地址,第八位是傳送方向位,0表示主機發送數據(寫),1表示主機接收數據(讀)。被定址到的從機設備按傳送方向位設置為對應工作方式。標準I2C匯流排的設備都有一個七位地址,所有連接在I2C匯流排上的設備都接收啟動信號后的第一個位元組,並將接收到的地址與自己的地址進行比較,如果地址相符則為主機要尋訪的從機,應在第九位答時鐘脈衝時向SDA線送出低電平作為應答。除了第一位元組是通用呼叫地址或十位從機地址之外第二位元組開始即數據位元組。數據傳送完畢,由主機發出停止信號“P”(SDA在SCL高電平期間由低電平跳變為高電平)。
   AT24C系列串列E2PROM具有I2C匯流排介面功能,功耗小,寬電源電壓(根據不同型號2.5V~6.0V),工作電流約為3mA,靜態電流隨電源電壓不同為30μA~110μA,AT24C系列串列E2PROM參數如下
型 號    容 量   器件定址位元組(8位) 一次裝載位元組數
AT24C01  128×8   1010A2A1A0  R/W         4
AT24C02  256×8   1010A2A1A0   R/W         8
AT24C04  512×8   1010A2A1P0   R/W         16
AT24C08  1024×8  1010A2P1P0   R/W         16
AT24C16  2048×8  1010P2P1P0   R/W         16 
  由於I2C匯流排可掛接多個串列介面器件,在I2C匯流排中每個器件應有唯一的器件地址,按I2C匯流排規則,器件地址為7位數據(即一個I2C匯流排系統中理論上可掛接128個不同地址的器件),它和1位數據方向位構成一個器件定址位元組,最低位D0為方向位(讀/寫)。器件定址位元組中的最高4位(D7~D4)為器件型號地址,不同的I2C匯流排介面器件的型號地址是廠家給定的,如AT24C系列E2PROM的型號地址皆為1010,器件地址中的低3位為引腳地址A2  A1  A0,對應器件定址位元組中的D3、D2、D1位,在硬體設計時由連接的引腳電平給定。
  對AT24C系列 E2PROM的讀寫操作完全遵守I2C匯流排的主收從發和主發從收的規則。

[C語言源程序]
#include
#include
#include
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
                         0x6d,0x7d,0x07, 0x7f,0x6f,};
unsigned char sec;        //定義計數值,每過1秒,sec加1
unsigned int tcnt;        //定時中斷次數
bit  write=0;             //寫24C08的標誌;
sbit gewei=P2^0;          //個位選通定義
sbit shiwei=P2^1;         //十位選通定義
/////////24C08讀寫驅動程序////////////////////
sbit scl=P3^4;   // 24c08 SCL
sbit sda=P3^5;  // 24c08 SDA
void delay1(unsigned char x)
{  unsigned int i;
  for(i=0;i<x;i++);
  ;}
void flash()
{  ;  ; }
void x24c08_init()  //24c08初始化子程序
 {scl=1; flash(); sda=1; flash();}
void start()        //啟動I2C匯流排
{sda=1; flash(); scl=1; flash(); sda=0; flash(); scl=0; flash();}
void stop()         //停止I2C匯流排
{sda=0; flash(); scl=1; flash(); sda=1; flash();}
void writex(unsigned char j)  //寫一個位元組
{  unsigned char i,temp;
   temp=j;
   for (i=0;i<8;i++)
   {temp=temp<<1; scl=0; flash(); sda=CY; flash(); scl=1; flash();}
   scl=0; flash(); sda=1; flash();
}
unsigned char readx()   //讀一個位元組
{
   unsigned char i,j,k=0;
   scl=0;  flash();  sda=1;
   for (i=0;i<8;i++)
    { 
flash();  scl=1;  flash();
      if (sda==1) j=1;
      else j=0;
      k=(k<<1)|j;
   scl=0;}
   flash();  return(k);
}
void clock()         // I2C匯流排時鐘
{
   unsigned char i=0;
   scl=1;  flash();
   while ((sda==1)&&(i<255))i++;
   scl=0; flash();
}
////////從24c02的地址address中讀取一個位元組數據/////
unsigned char x24c08_read(unsigned char address)
{
   unsigned char i;
   start(); writex(0xa0);
   clock(); writex(address);
   clock(); start();
   writex(0xa1); clock();
   i=readx(); stop();
   delay1(10);
   return(i);
}
//////向24c02的address地址中寫入一位元組數據info/////
void x24c08_write(unsigned char address,unsigned char info)
{
   EA=0;
   start(); writex(0xa0);
   clock(); writex(address);
   clock(); writex(info);
   clock(); stop();
   EA=1;
   delay1(50);
}
/////////////24C08讀寫驅動程序完/////////////////////
void Delay(unsigned int tc)     //延時程序
{
 while( tc != 0 )   
    {unsigned int i;   
     for(i=0; i<100; i++); 
     tc--;}
}
void LED()                  //LED顯示函數
{
   shiwei=0; P0=table[sec/10]; Delay(8); shiwei=1;
   gewei=0;  P0=table[sec%10]; Delay(5); gewei=1;
}
void t0(void) interrupt 1 using 0  //定時中斷服務函數
{
TH0=(65536-50000)/256; //對TH0 TL0賦值
TL0=(65536-50000)%256; //重裝計數初值
tcnt++;        //每過250ust tcnt加一
if(tcnt==20)  //計滿20次(1秒)時
   {
    tcnt=0;   //重新再計
    sec++;
    write=1;  //1秒寫一次24C08
    if(sec==100) //定時100秒,在從零開始計時
      {sec=0;}
   }
}
void main(void)
{
TMOD=0x01;  //定時器工作在方式1
ET0=1;  EA=1;
x24c08_init();        //初始化24C08
sec=x24c08_read(2);//讀出保存的數據賦於sec
TH0=(65536-50000)/256; //對TH0 TL0賦值
TL0=(65536-50000)%256; //使定時器0.05秒中斷一次
TR0=1;           //開始計時
 while(1)
  {
  LED();
 if(write==1) //判斷計時器是否計時一秒
    {
  write=0;              //清零
     x24c08_write(2,sec);  //在24c08的地址2中寫入數據sec
 }
   }
}

[硬體電路圖]
 


[admin via 研發互助社區 ] I2C的讀寫操作實驗已經有4137次圍觀

http://cocdig.com/docs/show-post-42064.html