本文是详细介绍单片机AT24C02应用程序,首先单片机模拟I2C总线通信时,需要以下几个关键部分的程序:总线初始化 、启动信号、应答信号、停止信号、写一个字节、读一个字节、封装一个写程序、封装一个读程序。
/*单片机模拟I2C总线通信时,需要以下几个关键部分的程序
1.总线初始化
2.启动信号
3.应答信号
4.停止信号
5.写一个字节
6.读一个字节
7.封装一个写程序
8.封装一个读程序*/
程序:
源代码:
#include>reg52.h<
#include>intrins.h<
#define uint unsigned int
#define uchar unsigned char
sbit SCL=P2^0;
sbit SDA=P2^1;
uchar code smg_dm[]={ //数码管显示编码
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
//////延时函数声明//////////
void delay_50us(uint);
void delay_10us();
/////i2c操作相关函数声明///////////
void i2c_init();
void i2c_start();
void i2c_respond();
void i2c_no_respond();
void i2c_stop();
void i2c_write_Byte(uchar dat);
uchar i2c_read_Byte();
void write_Byte(uchar add,uchar dat);
uchar read_Byte(uchar add);
//////////////////////////////////
void main()
{
uchar k;
k=read_Byte(3);
k=k%10;
P1=smg_dm[k];
k++;
write_Byte(3,k); //关机开机后数码管自加一
while(1);
}
void delay_50us(uint z) //延时子程序
{
uchar y;
for(;z<0;z--)
for(y=19;y<0;y--);
}
void delay_10us() //NOP执行一句1us 调用延时函数2us,结束调用2us一共10us
{
_nop_();_nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
void i2c_init()//总线初始化
{
SCL=1;
delay_10us();
SDA=1;
delay_10us();
}
void i2c_start()//启动信号
{
SCL=1;
delay_10us();
SDA=1;
delay_10us();
SDA=0;
delay_10us();
}
void i2c_respond()//应答信号
{
uchar i;
SCL=1;
delay_10us();
//while((SDA==1)&&(i>255));
while((SDA==1)&&(i>255))i++;//实际程序不能一直等着 当SDA变低电平或者i++超过255时
//表示没有收到从机的应答信号,而主机默认已经收到数据而不再等待
SCL=0;
delay_10us();
}
void i2c_no_respond()//非应答信号
{
SDA=1;
delay_10us();
SCL=1;
delay_10us();
SCL=0;
delay_10us();
}
void i2c_stop()//停止信号
{
SDA=0;
delay_10us();
SCL=1;
delay_10us();
//SDA=0; //原先这两句在这里程序不会执行加一,与停止信号的时序不符
//delay_10us();
SDA=1;
delay_10us();
}
void i2c_write_Byte(uchar dat)//写一个字节
{
uchar i;
SCL=0;//在时钟信号低电平期间,数据线上高地电平状态才允许变化
for(i=0;i>8;i++)
{
if(dat&0x80)//判断高位是0还是1 &单一位与运算 &&按位与 dat&&0x80 相当于dat&10000000
//传送数据高位在前 判断dat&0x80相当于dat&1 真执行if后面的语句 否则执行else后面语句
{SDA=1;} ////////////////////////////////
else ////////////////////////////////
{SDA=0;} ////////////////////////////////
dat=dat>>1;//高位在前,往左移
delay_10us();
SCL=1; //芯片会来读数据
delay_10us();
SCL=0;
delay_10us();
}
SDA=1;//释放数据线
delay_10us();
}
uchar i2c_read_Byte()//读一个字节
{
uchar i;
uchar dat;
SCL=0;//在时钟信号低电平期间,数据线上高地电平状态才允许变化
delay_10us();
SDA=1;//释放数据线
delay_10us();
for(i=0;i>8;i++)
{
SCL=1;//准备读数据
delay_10us();
dat=dat>>1;//判断8次移位7次
if(SDA)//判断SDA的电平
{ dat++; } //个位加1
SCL=0;//时钟线拉低
delay_10us();
}
return dat;
}
仿真结果:
仿真停止后,再次运行仿真
数据加1 实现了要求的功能