📄 i2c.c
字号:
//严格的时序
#include<reg52.h>
#include<intrins.h>//_nop_()函数所在库
#define uchar unsigned char
#define uint unsigned int//简写宏定义
sbit sda=P2^0;//数据总线
sbit scl=P2^1;//时钟总线
void delay()//延时函数〉4.7US
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=2;b>0;b--);
}
void init_I2C()//初始I2C总线,都释放为高,SCL 为高电平时,SDA数据要稳定
{
sda=1;
scl=1;
}
void start_I2C()//开始信号,在SCL为高电平时SDA出现下跳变为开始;
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop_I2C()//停止信号,在SCL为高电平时SDA出现上跳变为停止;
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void write_byte(uchar dat)//写一个字节到24C02
{
uchar i;//数据是串行的,高位在前
for(i=0;i<8;i++)
{
scl=0;
delay();
dat=dat<<1;//移出的位到PSW的CY位
sda=CY;
scl=1;
delay();//在数据送出后置高SCL并延时保证SDA稳定
scl=0;
delay();
}
sda=1;//写完数据后习惯性释放数据线以等待回应
}
uchar read_I2C()//读一个字节注意将位移为完整字节的技巧
{
uchar i,renum;
for(i=0;i<8;i++)
{
scl=0;
delay();
sda=1;
delay();
scl=1;
delay();
renum=(renum<<1)|sda;//¥
scl=0;
delay();
sda=0;
delay();
}
return renum;
sda=1;//释放数据线
}
void ack_I2C()//应答信号,在SCL为高时24C02收到SDL上的低电平信号
{ //若未收到则在一定时间之后默认已收到
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++;//SDA从0到1,或一定时间后都可使之跳出循环
scl=0;
delay();
}
void write_I2C(uchar add,uchar sta)//按照时序向24C04写数据主要函数
{ //要严格按照时序,特别注意应答信号必不可少
start_I2C();//开始信号
write_byte(add);//存储器地址
ack_I2C();//应答
write_byte(2);//写存储器中欲写的单元
ack_I2C();//应答
write_byte(sta);//写数据
ack_I2C();//应答
stop_I2C();//停止信号
}
uchar readmain()//按照时序读24C04中数据主函数,注意读时也要写清读的地址
{
uchar temp;//读回数据暂存
start_I2C();
write_byte(0xa0);//要读的存储器地址
ack_I2C();
write_byte(2);//读存储器中欲写的单元
ack_I2C();
start_I2C();
write_byte(0xa1);//数据流向选择0xa1,1为读
ack_I2C();
temp=read_I2C();
stop_I2C();
return temp;
}
void main()
{
while(1)
{
init_I2C();
write_I2C(0xa0,0xee);//数据流向选择0xa0,0为写,0Xee为欲写数
delay1(200);//读写;大的数据流向或单元改变要添置延时,否则将会造成整个程序的失败
P1=readmain();
while(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -