51單片機(jī)讀寫AT24C02源代碼(詳細(xì)注釋)
#include
typedef unsigned char uchar;
typedef unsigned int uint;
#define write_c02 0xa0
#define read_c02 0xa1
sbit sda = P2^0;
sbit scl = P2^1;
void delay()
{ //delay:5us
;;
}
//i2c:init
void i2c_init()
{
sda = 1;
delay();
scl = 1;
delay();
}
//delayms:
void delayms(uint xms)
{
uchar x, y;
for(x = xms; x > 0; x--)
for(y = 110; y > 0; y--);
}
//start:
void start() //啟動(dòng)i2c
{
sda = 1;
scl = 1;
delay();//延時(shí)必須大于4.7us,此約為五微秒
sda = 0; //在scl為高電平時(shí),sda一個(gè)下降沿為啟動(dòng)信號(hào)
delay();
}
//stop:
void stop() //停止i2c
{
sda = 0;
scl = 1;
delay();
sda = 1; //在scl為高電平時(shí),sdasda一個(gè)上升沿為停止信號(hào)
delay();
}
//ack:
void ack() //應(yīng)答信號(hào)0
{
uchar i = 0; //等待變量
scl = 1;//在scl為高電平期間等待應(yīng)答
delay();
while((sda == 1) && i < 250)//若為應(yīng)答0即退出,從機(jī)向主機(jī)發(fā)送應(yīng)答信號(hào)
i++;//等待一段時(shí)間
scl = 0; //應(yīng)答之后將scl拉低
delay();
}
//nack:
void nack() //非應(yīng)答
{
scl = 1;//在scl為高電平期間,由主機(jī)向從機(jī)發(fā)送一個(gè)1,非應(yīng)答信號(hào)
delay();
sda = 1;
scl = 0; //應(yīng)答之后將scl拉低
delay();
}
//send byte:
void send_byte(uchar date)//寫一個(gè)字節(jié)
{
uchar i, temp;
temp = date; //存入要寫入的數(shù)據(jù),即要發(fā)送到sda上的數(shù)據(jù)
for(i = 0; i < 8; i++)
{ //發(fā)送8位
temp <<= 1; //to CY 將數(shù)據(jù)的最高位移入到PSW中的CY位中
scl = 0;//只有在scl為低電平時(shí),才允許sda上的數(shù)據(jù)變化
delay();
sda = CY; //將CY里的數(shù)據(jù)發(fā)送到sda數(shù)據(jù)線上
delay(); //可以延時(shí)
scl = 1; //在scl為高電平時(shí),不允許sda上的數(shù)據(jù)變化,使數(shù)據(jù)穩(wěn)定
delay();
scl = 0;//允許sda數(shù)據(jù)線的數(shù)據(jù)變化,等待下一個(gè)數(shù)據(jù)的傳輸
delay();
}
//wait ack:發(fā)送完一個(gè)字節(jié)數(shù)據(jù)后要主機(jī)要等待從機(jī)的應(yīng)答,第九位
scl = 0;//允許sda變化
delay();
sda = 1;//wait:ack,sda拉高等待應(yīng)答,當(dāng)sda=0時(shí),表示從機(jī)的應(yīng)答
delay();
}
//read: byte
uchar read_byte() //讀一個(gè)字節(jié)數(shù)據(jù)
{
uchar i, j, k;
scl = 0; //讀之前先允許sda變化
delay(); //等待數(shù)據(jù)
for(i = 0; i < 8; i++)
{
scl = 1; //不允許sda變化
delay(); //使sda數(shù)據(jù)穩(wěn)定后開始讀數(shù)據(jù)
j = sda; //讀出sda上的數(shù)據(jù)
k = (k << 1)| j; //將數(shù)據(jù)通過|運(yùn)算存入k中
scl = 0;//允許sda變化等待下一位數(shù)據(jù)的到來
delay();
}
//delay();//可不用延時(shí)
return k;//返回讀出的數(shù)據(jù)
}
//write:at24c02 在at24c02中的指定地址寫入數(shù)據(jù)
void write_at24c02(uchar address, uchar date)
{
start(); //啟動(dòng)i2c
send_byte(write_c02);//寫入期間地址和寫操作
ack(); //從機(jī)應(yīng)答0
send_byte(address); //寫入寫數(shù)據(jù)的單元地址
ack(); //ack0
send_byte(date); //在指定地址中寫入數(shù)據(jù)
ack(); //從機(jī)應(yīng)答0
stop(); //停止i2c
}
//read: at24c02 在at24c02的指定地址中讀出寫入的數(shù)據(jù)
uchar read_at24c02(address)
{
uchar dat;//用來存儲(chǔ)讀出的數(shù)據(jù)
start(); //啟動(dòng)i2c
send_byte(write_c02); //寫入at24c02器件地址和寫操作
ack(); //從機(jī)應(yīng)答0
send_byte(address); //寫入要讀取AT24C02的數(shù)據(jù)的單元地址
ack(); //從機(jī)應(yīng)答0
start(); //再次啟動(dòng)i2c
send_byte(read_c02); //寫入AT24C02器件地址和讀操作
ack();//從機(jī)應(yīng)答‘0’
dat = read_byte();//讀出指定地址中的數(shù)據(jù)
nack(); //主機(jī)發(fā)出非應(yīng)答‘1’
stop(); //停止i2c
return dat; //返回讀出的數(shù)據(jù)
}
//main:
void main()
{
uchar i;
i2c_init();
start();
while(1)
{
for(i = 0x00; i < 0xff; i++)
{
write_at24c02(10, i);
delayms(10);//需等待十毫秒
P1 = read_at24c02(10);//1010 1010
delayms(2000);
}
}
}
評(píng)論