I²C其实不难,分清几个点就可以了,【开始】、【停止】、【应答】、【写地址】、【写数据】、然后就是结合起来【在某个地址 写数据】、【读数据】。。。
就这么点,对应着iic协议时序原理图,一个一个打破,OK。
简单粗暴的代码呈上,【基于51单片机主控 及 24C02(串行E2PROM是基于I2C-BUS 的存储器件 )】
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define write_ADD 0xa0 //24c02 写数据地址
#define read_ADD 0xa1 //24c02 读数据地址
uchar a;
sbit SDA=P2^0; //数据线
sbit SCL=P2^1; //时钟线
void init(); //初始化
void respons(); //应答
void start(); //开始
void stop(); //结束
void write_byte(uchar dat); //写字节
void delay(); //延时
uchar read_byte(); //读字节
void write(uchar addr,uchar dat); //指定地址写
uchar read(uchar addr); //指定地址读
bit flag; //应答标志位
/********************
简单延时函数
********************/
void delay()
{ ;; }
/********************
开始
********************/
void start() //SCL在高电平期间,SDA一个下降沿则表示启动信号
{
sda=1;
delay();
scl=1;
delay();
sda=0; //sda产生一个下降沿
delay();
}
/********************
停止
********************/
void stop() // SCL在高电平期间,SDA一个上升沿则表示停止信号
{
sda=0;
delay();
scl=1;
delay();
sda=1; //SDA产生上升沿
delay();
}
/********************
应答
********************/
void respons() //SCL在高电平期间,SDA被从设备拉为低电平表示应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++; //至多等待250个CPU时钟周期 ,等待SDA拉低
scl=0; //拉低后,时钟也拉低,禁止数据写入。 应答完成
delay();
}
/
/********************
iic初始化
********************/
void init()// 将总线都拉高一释放总线 发送启动信号前,要先初始化总线。即总有检测到总线空闲才开始发送启动信号
{
sda=1;
delay();
scl=1;
delay();
}
/********************
写函数
********************/
void write_byte(uchar date) //写一个字节
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1; //左移位,高位移出,即是移给CY,
scl=0;//拉低SCL,因为只有在时钟信号为低电平期间按数据线上的高低电平状态才允许变化;并在此时和上一个循环的scl=1一起形成一个上升沿
delay();
sda=CY; //把移出的高位传到数据线,
delay();
scl=1;//拉高SCL,此时SDA上的数据稳定
delay();
}
scl=0;//拉低SCL,为下次数据传输做好准备
delay();
sda=1;//释放SDA总线,接下来由从设备控制,比如从设备接收完数据后,在SCL为高时,拉低SDA作为应答信号
delay();
}
/********************
读函数
********************/
uchar read_byte()//读一个字节
{
uchar i,k;
scl=0; //拉低时钟
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;//上升沿时,IIC设备将数据放在sda线上,并在高电平期间数据已经稳定,可以接收啦
delay();
k=(k<<1)|sda; //左移后,按位与,反复八次,就是一个字节
scl=0;//拉低SCL,使发送端可以把数据放在SDA上
delay();
}
return k;
}
/********************
地址写函数
********************/
void write_add(uchar address,uchar date)//任意地址写一个字节
{
start();//启动
write_byte(0xa0);//发送从设备地址
respons();//等待从设备的响应
write_byte(address);//发出芯片内地址
respons();//等待从设备的响应
write_byte(date);//发送数据
respons();//等待从设备的响应
stop();//停止
}
/********************
地址读函数
********************/
uchar read_add(uchar address)//读取一个字节
{
uchar date;
start(); //启动
write_byte(0xa0); //发送从设备地址 写操作
respons(); //等待从设备的响应
write_byte(address);//发送芯片内地址
respons(); //等待从设备的响应
start(); //启动
write_byte(0xa1); //发送从设备地址 读操作
respons(); //等待从设备的响应
date=read_byte(); //获取数据
stop(); //停止
return date; //返回数据
}
//主函数
void main()
{
init();
write_add(5,0xaa); //向地址5写入0xaa
delay(10); //延时,
P1=read_add(5); //读取地址5的值,用示波器看看,或者点个灯试试哈哈~
while(1);
}
//打完收工、希望这个对大家有用,当初学IIC,一时半会转不过弯,后面绕了几圈才明白,别泄气,加油一起共勉!
//本人QQ 65434340,一起交流一起学习!