- 什么是IIC總線
IIC總線是同步通信的一種特殊形式,具有接線口少、控制簡單、器件封裝形式小、通信速率高等特點。在主從通信中,可以有多個IIC總線器件同時連接到IIC總線上,所有與IIC兼容的器件都具有標準的接口,通過地址來識別通信對象,使他們可以經由IIC總線互相直接通信。
IIC總線由SDA數據線和SCL時鐘線倆條線構成通信線路,既可發(fā)送數據也可以接收數據。在CPU和IC之間、IC與IC間都可以雙向傳播,每個器件都有唯一的地址,這樣就可以使信息進行準確的傳輸。CPU發(fā)出的信號分為地址碼和數據碼倆部分,地址碼用來選址,數據碼是通信的內容。
總而言之,IIC總線就是器件之間的通信線路,主器件可以通過IIC總線向從器件發(fā)送數據,也可以從從器件接收數據。51單片機不具備IIC總線接口,但我們可以通過軟件模擬IIC總線的工作時序,只需要正確調用各個函數就能夠方便的拓展IIC總線接口器件。
-什么是EEPROM
EEPROM就是一種存儲介質,就像ROM、PROM、FLASH儲存器等,下面我粗略地介紹一下EEPROM的由來
ROM:只讀存儲器,其中的內容在工廠中就燒錄好了,內容只能讀,不能改,所以用戶只能讀取其中數據,一旦數據出錯,ROM就相當于廢掉了。
PROM:可編程的ROM,相比于原來的ROM,用戶可以將自己所需要的數據寫入,但也只有一次機會,數據一旦寫入之后就無法修改。
EPROM:可擦除可編程ROM,相比較PROM,此芯片可以重復擦除和寫入,雖然它解決了PROM只能寫入一次的弊端,但EPROM數據的擦除是通過紫外線的照射來完成的,所以使用此芯片時對紫外線的防護是很重要的。
EEPROM電可擦除可編程ROM,鑒于EPROM擦除數據的不容易,EEPROM應運而生,它是以電子信號來修改其內容的,而且是以byte為最小修改單位的,不需要將數據全部清除來寫入,可以實現定向修改數據。而且因為其數據保存具有掉電不丟失的特性備受追捧。
在下的程序就是通過51單片機模擬IIC總線對AT24C02(EEPROM的型號)進行數據的存取和修改。
AT24C02的儲存容量為256B一般通過片內子地址尋址對內部256B中任意一個進行讀寫操作,其尋址范圍為00~FF。
-IIC總線的通信格式
就像串口通訊和紅外遙控一樣,IIC總線也有一套通信方式。
硬件結構:
先來認識一下IIC總線的硬件結構,SDA是數據線,SCL是時鐘線,總線上個器件均采用漏極開路結構與總線相連,因此SDA和SCL都需要上拉電阻,總線在空閑狀態(tài)保持高電平,一旦某一器件輸出低電平,都將使總線的信號變低,所以說各器件的SDA和SCL都是線“與”關系。
數據位有效性:
IIC中數據的傳輸是通過SDA和SCL進行高低電平變化來完成的,在傳送數據時,只有當時鐘線SCL為高電平的時候數據線SDA上的電平才有效(即SDA高電平代表1;SDA低電平代表0),所以在SCL為高電平的時候SDA上的數據一定要保持穩(wěn)定才行,不然數據的傳輸會很不穩(wěn)定的。那就是說SCL為低電平的時候SDA怎么變化都沒有關系,但SCL為高電平時SDA一定要穩(wěn)定,可以理解為傳輸信號的改變是在SCL為低電平的時候進行的(SCL高電平時SDA的改變即為傳輸信號的改變)。
啟始信號、停止信號:
IIC每次進行數據傳輸時先由主機發(fā)出啟始信號,代表數據傳輸的開始,信號格式為:在SCL高電平時期SDA產生下降沿(注意這與數據的傳輸不同,SCL高電平時器SDA要變化),這樣從器件就會檢測到該信號并做好準備。
相對應,停止信號時在SCL高電平時期SDA產生上升沿信號。倆種信號的時序圖如下
尋址信號:
主機在發(fā)出啟始信號后,再發(fā)出尋址信號,這里介紹一下七位尋址方式。
尋址信號由一個字節(jié)(8byte)構成,高七位為地址位,用來確定要進行通信的從器件,最低位是方向位,用來說明是傳輸數據還是接收數據。每一個從器件都會對比主機發(fā)送的地址碼和自己的地址,如果安排上了,再判斷從器件是接收主機數據還是向主機發(fā)送數據。
從器件的地址由固定地址和可編程地址倆部分組成,固定地址用于區(qū)別類別,可編程地址用來區(qū)別同類從器件。比如AT24C02有四位固定地址和三位可編程地址,三位可編程地址可以有八種表達方式,所以最多可以有八個AT24C02器件接再IIC中。
方向位為0時,主機向從機傳輸數據;方向位為1時,從機向主機傳輸數據。
應答信號:
IIC總線協(xié)議規(guī)定:每傳輸1字節(jié)數據(含地址及命令)后,都要有一個應答信號,以確定數據傳送是否被對方收到。應答信號由接收方產生,應答信號的格式為:在SCL為高電平時SDA為低電平(被動的,我們到時候只要檢測一下SDA是否被拉低即可),表示數據傳輸正確,產生應答。但當主機為接收方時,對最后一字節(jié)不應答。
(在敲代碼時我們一般將應答信號的檢驗放在數據發(fā)送函數中)
模塊化設計注解
這里只是挑重要模塊進行注解,后面有完整代碼。
延時10um函數:
void dy()
{
uint a;
for(a=3;a>0;a--)
;
}
IIC啟始函數:
void IICstart()//產生下降沿,啟動信號
{
SDA=1;
dy();
SCL=1;
dy();
SDA=0;
dy();
SCL=0;
}
IIC停止函數:
void IICstop()//產生上升沿,停止信號
{
SDA=0;
dy();
SCL=1;
dy();
SDA=1;
dy();
SCL=0;
}
IIC發(fā)送一個字節(jié)函數:
uchar IICsendbyte(uchar dat)//將dat一個字節(jié)的內容發(fā)送出去,先發(fā)送最高位,并檢測應答
{
uint i;
SCL=0
for(i=0;i<8;i++)//8位逐次發(fā)送
{
dat<<=1;
SDA=CY;//進行左移操作后最高位自動移入PSW寄存器中的CY位(可以用來zb)
dy();
SCL=1;
dy();
SCL=0;
dy();
}
SDA=1;//拉高SDA電平,準備檢測應答信號
dy();
SCL=1;
while(SDA)
{
j++;
if(j>200)//當超過2000umSDA還沒被拉低,算應答失敗或非應答
{
SDA=0;
dy();
return 0;//發(fā)送失敗返回0
}
}
SCL=0;
dy();
return 1;//發(fā)送成功返回1
}
IIC接收一個字節(jié)函數:
uchar IICreadbyte()//讀取一個字節(jié)數據,并返回
{
uint i;
uchar dat;
for(i=0;i<8;i++)
{
SCL=1;
dy();
dat<<=1;//一定要先移位
dat |=SDA;//與運算
dy();
SCL=0;
dy();
}
return dat;
}
向AT24C02寫字節(jié):
void AT24C02write(uchar addr,uchar dat)//往addr地址寫入dat數據
{
IICstart();//開始
IICsendbyte(0Xa0);//發(fā)送尋址 0Xa0代表尋址AT24C02并且方向位為0,主機向從機傳輸數據
IICsendbyte(addr);//發(fā)送儲存地址
IICsendbyte(dat);//發(fā)送儲存數據
ICCstop();//結束
}
從AT24C02讀字節(jié):
uchar AT24C02read(uchar addr)//讀取AT24C02中addr位置數據并返回
{
uchar dat;
IICstart();
IICsendbyte(0Xa0);//偽寫
IICsendbyte(addr);
IICstart();//開始讀取
IICsendbyte(0Xa1);//發(fā)送尋址 0Xa0代表尋址AT24C02并且方向位為1,從機向主機傳輸數據
dat=IICreadbyte(addr);//讀取數據
IICstop();
return dat;//返回數據
}
整體代碼
在下通過按鍵k1、k2、k3、k4實現數據在AT14C02中的保存、讀取、自增、清零等操作,并通過數碼管顯示數值(38譯碼器),親自測試可以運行。
#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char
uchar num,duan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit SDA=P2^0;
sbit SCL=P2^1;
sbit a=P2^2;
sbit b=P2^3;
sbit c=P2^4;
sbit k1=P1^3;
sbit k2=P1^2;
sbit k3=P1^1;
sbit k4=P1^0;
void delay10us() //時間>4.7um就ok
{
unsigned char a;
for(a=3;a>0;a--);
}
void dy(uint x) //按鍵時用的延時函數
{
while(x--);
}
void xs() //數碼管顯示
{
uint i;
for(i=0;i<4;i++)
{
switch(i)
{
case 0:a=0;b=0;c=0;P0=duan[num/1000];break; //千位
case 1:a=1;b=0;c=0;P0=duan[num/100];break; //百位
case 2:a=0;b=1;c=0;P0=duan[num/10%10];break; //十位
case 3:a=1;b=1;c=0;P0=duan[num%10];break; //個位
}
dy(100);
P0=0X00;
}
}
void IICstart() //起始信號
{
SDA=1;
delay10us();
SCL=1;
delay10us();
SDA=0;
delay10us();
}
void IICstop() //停止信號
{
SDA=0;
delay10us();
SCL=1;
delay10us();
SDA=1;
delay10us();
}
uchar IICsendbyte(uchar dat) //發(fā)送一個字節(jié)的數據
{
uint i,j=0;
SCL=0;
for(i=0;i<8;i++) //從最高位開始發(fā)送
{
dat<<=1;
SDA=CY; //左移時最高位會移入PSW寄存器的CY位中
delay10us();
SCL=1;
delay10us();
SCL=0;
delay10us();
}
SDA=1;
delay10us();
SCL=1;
while(SDA) //等待應答 即等待設備把SDA拉低
{
j++;
if(j>200) //如果超過2000um沒有應答就算發(fā)送失敗或非應答 表示接收結束
{
SCL=0;
delay10us();
return 0;
}
}
SCL=0; //不管應答或非應答,SCL都置0
delay10us();
return 1;
}
uchar IICreadbyte() //讀一個字節(jié),從最高位開始
{
uint i,dat=0;
SDA=1; //因為下面開始時SCL=1,所以SDA要穩(wěn)定
delay10us();
for(i=0;i<8;i++)
{
SCL=1;
delay10us();
dat<<=1;
dat |=SDA;
delay10us();
SCL=0;
delay10us();
}
return dat; //返回讀到的數據dat(一個字節(jié))
}
void AT24c02write(uchar addr,uchar dat) //往AT24c02的addr地址寫入dat數據
{
IICstart();
IICsendbyte(0Xa0); //發(fā)送要與之通信的器件地址,此處為AT24c02的地址
IICsendbyte(addr); //發(fā)送要寫入的內存地址,AT24c02內部可儲存256字節(jié),故地址可以為0~255
IICsendbyte(dat); //發(fā)送數據
IICstop();
}
uchar AT24c02read(uchar addr) //讀取AT24c02中addr地址的值,并返回給函數
{
uchar dat;
IICstart();
IICsendbyte(0Xa0); //偽寫
IICsendbyte(addr);
IICstart(); //真正開始讀數據
IICsendbyte(0Xa1);
dat=IICreadbyte();
IICstop();
return dat;
}
void key()
{
if(k1==0)
{
dy(1000);
if(k1==0)
{
AT24c02write(1,num);
}
while(!k1); //檢測放手
}
if(k2==0)
{
dy(1000) ;
if(k2==0)
{
num=AT24c02read(1);
}
while(!k2); //檢測放手
}
if(k3==0)
{
dy(1000);
if(k3==0)
{
num++;
if(num==256)
num=0;
}
while(!k3); //檢測放手
}
if(k4==0)
{
dy(1000);
if(k4==0)
{
num=0;
}
while(!k4); //檢測放手
}
}
void main()
{
while(1)
{
key();
xs();
}
}
上一篇:51單片機—串口通信
下一篇:C51—小知識點
推薦閱讀
史海拾趣
設計資源 培訓 開發(fā)板 精華推薦
- Microchip 升級數字信號控制器(DSC)產品線 推出PWM 分辨率和 ADC 速度業(yè)界領先的新器件
- 意法半導體STM32MP23x:突破成本限制的工業(yè)AI應用核心
- 意法半導體推出用于匹配遠距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數
- LGVL配合FreeType為可變字體設置字重-ESP32篇
- 使用樹莓派進行 ESP32 Jtag 調試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網頁和arduino的通訊
- ESP32 freeRTOS使用測試