标题:
带注释的AT24C02 IIC总线单片机读写源程序
[打印本页]
作者:
lxy5533533
时间:
2018-6-10 14:02
标题:
带注释的AT24C02 IIC总线单片机读写源程序
单片机源程序如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define AT24C02_addr
bit write=0;//写24C02的标志
sbit sda=P2^0;
sbit scl=P2^1;
sbit dula=P2^6;//申明U1锁存器的锁存端
sbit wela=P2^7;//U2锁存端
uchar i,miao,t;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void Delay5us() //@11.0592MHz
{
uchar i;
_nop_();
i = 11;
while (--i);
}
void start()//起始信号
{
scl=1;//先保持高电平,再进行数据传输
_nop_();//延时1微秒
sda=1;
Delay5us();//函数调用
sda=0;
Delay5us();
}
void stop()
{
scl=1;
_nop_();
sda=0;
Delay5us();
sda=1;
Delay5us();
}
void Mster_ASK()//主机发送应答
{
uchar i;
scl=1;
_nop_();
if(i==1)//受控器做出响应
{
sda=0;//释放sda线送出应答信号
}
else
{
sda=1;
}
_nop_();
scl=1;//数据保持稳定
Delay5us();
scl=0;//占用总线进行通信
sda=1;//准备下一次的通信
}
void test_ASK()//从机接受应答,低电平为应答
{
scl=1;//scl为高电平,数据不允许改变
Delay5us();
if(sda==1)//因为sda等于1时,表示空闲状态
{
scl=0;//表示不应答
_nop_();
stop();
return (0);
}
else//sda等于0,表示应答,scl拉低,表示收到这个是否应达的信息
{
scl=0;//低电平有效
_nop_();
return (1);
}
}
uchar sendbyte(uchar byte)//传送(写)一个字节
{
uchar i;
for(i=0;i<8;i++)
{
scl=0;//低电平时数据可以改变
_nop_();//稳定一下
if(byte&0x80)
{
sda=1;//发一个1的数据,先发高位
_nop_();
}
else
{
sda=0;//如果if处是0的话,就说明最高位是0,所以传数据0
_nop_();
}
scl=1;//数据手册看出来
_nop_();
byte<<=1;
}
}
uchar readbyte()//读一个字节
{
uchar dat,i;
scl=0;//可要可不要吧,看它忙不忙
_nop_();
scl=1;//置1,数据不允许改变
_nop_();
for(i=0;i<8;i++)
{
scl=1;//置1,数据不允许改变
_nop_();
if(sda)//若为1,则要读1出来
{
dat=dat|0x01;//或上都等于1
else
{
dat=dat&0xfe;//与上都等于0
}
_nop_();
scl=0; //释放总线,允许下一次数据输入
dat<<=1;
}
}
}
void T0()interrpt 1//定时中断服务函数
{
uchar t,miao,write;
TH0=(65536-50000)/256//从15536开始装初值,装满5000,即为50ms
TL0=(65536-50000)%256//装计数初值
t++;
if(t==20)//表示记满1秒
{
t=0;//重新计数
miao++;
}
if(miao=100)
miao=0;//重新计数
}
void display()
{
uchar bai,ge;
wela=1;//打开位选
P0=0x7e;//点亮第一位数码管
wela=0;//关闭位选
dula=1;;//打开段选
P0=table[bai];
dula=0;
wela=1;
P0=0x7d;
wela=0;
dula=1;
P0=table[ge];
dula=0;
main()
{
ACK_flag=0;
Init();//初始化
start();
sendbyte(AT24C02+0)//器件地址加0
if(!test_ASK())//若不应答,则为假,然 后取反
{
ACK_flag=1;
}
t=readbyte();//读出的时间赋予t
if(t>100)
t=0;//预防首次读取出错误数据
TMOD=0x01;//定时器工作在方式1
ET0=1;//开定时器0
EA=1;//开总定时器
TH0=(65536-50000)/256;//对TH0TL0赋值
TL0=(65536-50000)%256;//使定时器50毫秒中断一次
TR0=1;//开始计时
while(1)
{
display(t/10,t%10)
if(write==1)//判断计时器是否为1秒
{
write=0;//清0
sendbyte(2,t)//在地址2中写入数据t
}
}
}
void write_address(uchar date,uchar address)
{
start();
writebyte(0xa0);
Mster_ASK;//应答
write_byte(date);
test_ASK;//应答
stop();
}
void read_add(uchar address)
{
uchar date;
start();
writebyte(0xa0);
Mster_ASK();
writebyte(address);
test_ASK();
start();
writebyte(0xa1);
Mster_ASK();
test_ASK();
date=writebyte();
stop();
return date;
}
bit I2C_WriteData(uchar ADDR,uchar DAT) //I2C写数据
{
I2C_Start();
I2C_send_byte(AT24C02_ADDR+0);
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(ADDR);
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(DAT);
if (!Test_ACK())
{
return(0);
}
I2C_Stop();
return(1);
}
uchar I2C_ReadData(uchar ADDR) //I2C读数据
{
uchar dat;
I2C_Start();
I2C_send_byte(AT24C02_ADDR+0);
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(ADDR);
if (!Test_ACK())
{
return(0);
}
Master_ACK(0);
I2C_Start();
I2C_send_byte(AT24C02_ADDR+1);
if (!Test_ACK())
{
return(0);
}
dat = I2C_read_byte();
Master_ACK(0);
I2C_Stop();
return(dat);
}
void main()
{
I2C_init();
Timer0_init();
EEPROM_DATA = I2C_ReadData(255); //上电后首先读出24C02第255单元的值
while(1)
{
display(EEPROM_DATA);//数码管显示
}
}
/*定时器0中断服务程序*/
void timer0() interrupt 1 //T0内部查询顺序1
{
uchar i;
TH0 = 0x4b;
TL0 = 0xfe; //T0 定时50ms
i++;
if (i == 100) //5秒时间到
{
i = 0; //计数清零
if (EEPROM_DATA < 99) //判断待写数据值
{
EEPROM_DATA++;
}
else
{
EEPROM_DATA = 0;
}
if(!I2C_WriteData(255,EEPROM_DATA)) //写入待写数据并判断是否成功写入
{
LED1 = 0;//如果写失败 让LED1小灯点亮
}
else
{
LED1 = 1;
}
}
}
复制代码
作者:
赵大然
时间:
2018-9-6 17:17
有返回值的,会出现void函数吗?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1