代码较复杂,跟着老师来都会比较混乱
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
sbit dula = P2^6;
sbit wela = P2^7;
sbit SCL = P2^1;
sbit SDA = P2^0;
void time0Init();
void display(uchar);
void delayms(uchar);
void delay5us();
void I2C_Stop();
void I2C_Start();
void I2CSendByte(uchar);
uchar count1,num;
uchar code SMGwei[] = {0xfe,0xfd,0xfb};
uchar code SMGduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
bit ACKflag; //声明ACKflag 为字节变量
/*I2C通信初始化*/
void I2C_Start() //起始信号
{
SCL = 1;
SDA = 1;
delay5us();
SDA = 0;
delay5us();
}
void I2C_Stop() //停止信号
{
SCL = 0;
SDA = 0;
SCL = 1;
delay5us();
SDA = 1;
delay5us();
}
/*I2C应答和非应答*/
//I2C主机读从机应答
bit ReadACK()
{
SCL = 0;
SCL = 1;
delay5us();
if(SDA)//非应答
{
SCL = 0;
return (1);
}
else//应答
{
SCL = 0;
return(0);
}
}
//I2C主机发送应答
void sendACK(bit i)
{
SCL = 0;
if(i)
SDA = 1;
else
SDA = 0;
SCL = 1;
delay5us();
SCL = 0;
SDA = 1; //释放数据总线
}
void At24c02Write(uchar adress,DAT)
{
I2C_Start();
/*发送器件地址 + Write(0)*/
I2CSendByte(0xA0 + 0);
/*读是否应答*/
if(ReadACK()) //若为1 从机没有应答
ACKflag = 1; //无应答
else
ACKflag = 0; //应答
/*写入首地址(放在256个容器中的哪一个)*/
I2CSendByte(adress);
/*读是否应答*/
if(ReadACK()) //若为1 从机没有应答
ACKflag = 1; //无应答
else
ACKflag = 0; //应答
I2CSendByte(DAT);
/*读是否应答*/
if(ReadACK()) //若为1 从机没有应答
ACKflag = 1; //无应答
else
ACKflag = 0; //应答
I2C_Stop();
}
uchar I2cReadByte()
{
uchar j,DAT;
for(j = 0;j<8;j++)
{
DAT <<=1;
SCL = 0;
SCL = 1;
if(SDA)
DAT |= 0X01;
}
return (DAT);
}
uchar At24c02Read(uchar adress)
{
uchar DAT;
I2C_Start();
/*发送器件地址 + Write(0)*/
I2CSendByte(0xA0 + 0);
/*读是否应答*/
if(ReadACK()) //若为1 从机没有应答
ACKflag = 1; //无应答
else
ACKflag = 0; //应答
/*写入首地址(放在256个容器中的哪一个)*/
I2CSendByte(adress);
ReadACK();//不管应不应答
I2C_Start();
/*从机地址+1*/
I2CSendByte(0xA0 + 1);
if(ReadACK()) //若为1 从机没有应答
ACKflag = 1; //无应答
else
ACKflag = 0; //应答
DAT = I2cReadByte(); //读一字节
sendACK(1);
I2C_Stop();
return (DAT);
}
void I2CSendByte(uchar DAT) //发送一个字节
{
uchar i;
for(i = 0;i < 8; i++)
{
SCL = 0; //拉低时钟线才能允许数据变化
if(DAT & 0X80)
SDA = 1;
else
SDA = 0;
SCL = 1;
DAT <<= 1;
}
SCL = 0;
SDA = 1;//释放数据总线
}
/*数码管显示函数*/
void display(uchar num)
{
static uchar wei;
P0 = 0xff;
wela = 1;
P0 = SMGwei[wei];
wela = 0;
switch(wei)
{
case 0: dula = 1; P0 = SMGduan[num/100]; dula =0; break;
case 1: dula = 1; P0 = SMGduan[num%100/10]; dula =0; break;
case 2: dula = 1; P0 = SMGduan[num%10]; dula =0; break;
}
P0 =0xff;
wei++;
if(wei == 3)
{
wei = 0;
}
}
/*time0定时器初始化函数*/
void time0Init() //1MS
{
TR0 = 1;
TMOD |= 0X01;
TH0 = 0x0F0;
TL0 = 0x60;
EA = 1;
ET0 = 1;
}
/*time0定时器中断函数*/
void time0() interrupt 1
{
TF0 = 0;
TH0 = 0x0F0;
TL0 = 0x60;
display(num);
}
/*1.延时函数 2.延时5微秒函数*/
void delayms(uchar xms)
{
uchar i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void delay5us()
{
_nop_(); //延时5微妙
}
/*主函数*/
void main()
{
time0Init();
EA = 0; //屏蔽中断
At24c02Write(3,258);
delayms(5);
num = At24c02Read(3);
if(!ACKflag)
{
P1 = 0;
}
else
{
P1 = 0xff;
}//若应答则P1口上的全部灯亮
EA = 1; //开中断
while(1); //等待中断发生
}