下面是一個關(guān)于IIC總線的程序,用的是51單片機(jī)做控制器,對24c16的EEPROM進(jìn)行數(shù)據(jù)的讀寫,由于51沒有IIC總線接口,所以需要根據(jù)IIC的協(xié)議模擬它進(jìn)行數(shù)據(jù)傳輸。IIC是一中同步串口總線,scl為時鐘線,sda為數(shù)據(jù)線;scl為低時sda的數(shù)據(jù)允許變化,scl為高時sda的數(shù)據(jù)必須保持穩(wěn)定。同一個IIC總線根據(jù)器件地址的不同可以同時對多個器件進(jìn)行讀寫,例如可以同時接8個24c16系列的EEPROM。
本文引用地址:http://cafeforensic.com/article/201611/321664.htm下面的程序是一個時鐘程序,當(dāng)斷電時將數(shù)據(jù)將保存在24c16中。重新上電后先讀出24c16中存的數(shù)據(jù),之后一直對24c16進(jìn)行寫操作,這樣斷電就可以保持最后次數(shù)據(jù)在14c16里面了。
對24c16系列的EEPROM寫的過程:起始信號 寫器件地址 應(yīng)答寫地址 應(yīng)答 寫數(shù)據(jù).....無應(yīng)答 停止
對24c16系列的EEPROM寫的過程:起始信號寫器件地址 應(yīng)答寫地址 應(yīng)答 重新開始 寫器件+1 應(yīng)答 讀出數(shù)據(jù)停止
#include
#define uchar unsigned char
sbit sda=P2^1;
sbit scl=P2^0;
sbit p1_0=P1^0;
sbit p1_1=P1^1;
sbit p1_2=P1^2;
uchar a,tt;
uchar tem=0;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay()
{ ;; }
void start()//開始信號,scl在高電平時sda由高變低產(chǎn)生開始信號
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop()//停止信號,scl在高電平時sda由低變高產(chǎn)生停止信號
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void respons()//應(yīng)答,sda為高時表示從機(jī)有應(yīng)答,沒有就默認(rèn)應(yīng)答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++;
scl=0;
delay();
}
void init()//初始化定時器
{
sda=1;
delay();
scl=1;
delay();
TMOD=0x01;
TH0=(65536-50000)/256;
TH0=(65536-50000)%6;
EA=1;
ET0=1;
TR0=1;
p1_1=1;
p1_0=1;
}
void write_byte(uchar date)//寫一個字節(jié)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay();
sda=CY;//利用了CY這個移除來寫
delay();
scl=1;
delay();
scl=0;
delay();
}
scl=0;
delay();
sda=1;
delay();
}
uchar read_byte()//讀一個字節(jié)
{
uchar i,k;
scl=0;
delay();
sda=1;//釋放sda
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;//讀出來的字節(jié)存在k中
scl=0;
delay();
}
return k;
}
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=110;b>0;b--);
}
void write_add(uchar address,uchar date)//寫數(shù)據(jù)的整個過程
{
start();
write_byte(0xa0);//a0為從機(jī)器件地址,最后位為0表示寫
respons();
write_byte(address);//要寫的地址
respons();
write_byte(date);//要寫的數(shù)據(jù)
respons();
stop();
}
uchar read_add(uchar address))//讀數(shù)據(jù)的整個過程
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);//待讀數(shù)據(jù)的地址
respons();
start();//由寫變?yōu)樽x的過程需要重新執(zhí)行start的過程
write_byte(0xa1);//最后位為一表示讀
respons();
date=read_byte();//讀出數(shù)據(jù)
stop();
return date;
}
void main()
{
uchar shi,ge;
init();
if(read_add(20))
{
tem=read_add(20);
}
else
{
tem=0;
}
while(1)
{
if(tem>99)
{
tem=0;
}
shi=tem/10;
ge=tem;
p1_1=0;
P3=table[shi];
delay1(14);
p1_1=1;
p1_0=0;
P3=table[ge];
delay1(14);
p1_0=1;
}
}
void zhongd() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%6;
tt++;
if(tt==20)
{
tt=0;
tem++;
write_add(20,tem);
}
}
評論