|
1.實驗任務 本實驗實現(xiàn)的是向24C02存儲計數(shù),并通過數(shù)碼管顯示。 2.實驗目的 掌握24C02的讀寫時序,學會利用單片機向24C02寫數(shù)據(jù)和讀數(shù)據(jù)。 3.實驗原理 I2C總線是一種用于IC器件之間連接的二線制總線。它通過SDA(串行數(shù)據(jù)線)及SCL(串行時鐘線)兩根線在連到總線上的器件之間傳送信息。 當時鐘線SCL為高電平時,數(shù)據(jù)線SDA由高電平跳變?yōu)榈碗娖蕉x為“開始”信號,起始狀態(tài)應處于任何其他命令之前;當SCL線處于高電平時,SDA線發(fā)生低電平到高電平的跳變?yōu)椤敖Y(jié)束”信號。器件將處于備用方式(Standby MODE).開始和結(jié)束信號都是由主器件產(chǎn)生。在開始信號以后,總線即被認為處于忙狀態(tài);在結(jié)束信號以后的一段時間內(nèi),總線被認為是空閑的。I2C總線的數(shù)據(jù)傳送格式是:在I2C總線開始信號后,送出的第一個字節(jié)數(shù)據(jù)是用來選擇從器件地址的,其中前7位為地址碼,第8位為方向位(R/W)讀寫控制。方向位為“0”表示發(fā)送,即主器件把信息寫到所選擇的從器件;方向位為“1”表示主器件將從從器件讀信息。開始信號后,系統(tǒng)中的各個器件將自己的地址和主器件送到總線上的地址 進行比較,如果與主器件發(fā)送到總線上的地址一致,則該器件即為被主器件尋址的器件,其接收信息還是發(fā)送信息則由第8位(R/W)確定。 在I2C總線上每次傳送的數(shù)據(jù)字節(jié)數(shù)不限,但每一個字節(jié)必須為8位,而且每個傳送的字節(jié)后面必須跟一個應答位(ACK),ACK信號在第9個時鐘周期時出現(xiàn)。數(shù)據(jù)傳送每次都是先傳最高位,通常從器件在接收到每個字節(jié)后都會作出響應,即釋放SCL線返回高電平,準備接收下一個數(shù)據(jù)字節(jié),主器件可繼續(xù)傳送。如果從器件正在處理一個實時事件而不能接收數(shù)據(jù)時,(例如正在處理一個內(nèi)部中斷,在這個中斷處理完之前就不能接收I2C總線上的數(shù)據(jù)字節(jié))可以使時鐘SCL線保持低電平,從器件必須使SDA保持高電平,此時主器件產(chǎn)生1個結(jié)束信號,使傳送異常結(jié)束,迫使主器件處于等待狀態(tài)。當從器件處理完畢時將釋放SCL線,主器件繼續(xù)傳送。當主器件發(fā)送完一個字節(jié)的數(shù)據(jù)后,接著發(fā)出對應于SCL線上的一個時鐘(ACK)認可位,在此時鐘內(nèi)主器件釋放SDA線,一個字節(jié)傳送結(jié)束,而從器件的響應信號將SDA線拉成低電平,使SDA在該時鐘的高電平期間為穩(wěn)定的低電平。從器件的響應信號結(jié)束后,SDA線返回高電平,進入下一個傳送周期。 24C02的時序圖如下: (1)起始與停止時序圖: 
(2)寫數(shù)據(jù)時序圖 
4.電路原理圖 
5.實驗源程序 #include "reg52.h" #include <stdio.h> #include <absacc.h> unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; unsigned char sec; //定義計數(shù)值,每過1秒,sec加1 unsigned int tcnt; //定時中斷次數(shù) sbit P2_1=P2^1; bit write=0; //寫24C08的標志; sbit gewei=P2^2; //個位選通定義 sbit shiwei=P2^3; //十位選通定義 /////////24C08讀寫驅(qū)動程序//////////////////// sbit scl=P3^7; //24c08 SCL sbit sda=P3^6; //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) //寫一個字節(jié) { 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() //讀一個字節(jié) { 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中讀取一個字節(jié)數(shù)據(jù)///// 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地址中寫入一字節(jié)數(shù)據(jù)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讀寫驅(qū)動程序完///////////////////// void Delay(unsigned int tc) //延時程序 { while( tc != 0 ) {unsigned int i; for(i=0; i<100; i++); tc--;} } void LED() //LED顯示函數(shù) { 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 //定時中斷服務函數(shù) { TH0=(65536-50000)/256; //對TH0 TL0賦值 TL0=(65536-50000)%256; //重裝計數(shù)初值 tcnt++; //每過250ust tcnt加一 if(tcnt==20) //計滿20次(1秒)時 { tcnt=0; //重新再計 sec++; write=1; //1秒寫一次24C08 if(sec==100) //定時100秒,在從零開始計時 {sec=0;} } } void main(void) { P2_1=0; TMOD=0x01; //定時器工作在方式1 ET0=1; EA=1; x24c08_init(); //初始化24C08 sec=x24c08_read(2);//讀出保存的數(shù)據(jù)賦于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中寫入數(shù)據(jù)sec } } }
|