基于C语言模拟IIC总线来对I2C总线的理解

i2c 只是用两条双向的线,一条 serial data line (sda) ,另一条serial clock (scl)。
scl:上升沿将数据输入到每个eeprom器件中;下降沿驱动eeprom器件输出数据。(边沿触发)
sda:双向数据线,为od门,与其它任意数量的od与oc门成“线与”关系。
为了加深对i2c总线的理解,用c语言模拟iic总线,边看源代码边读波形:
如下图所示的写操作的时序图:
读时序的理解同理。对于时序不理解的朋友请参考“i2c总线概述及时序总结”
完整的程序如下:
#include
#define uchar unsigned char
#define uint unsigned int
#define write_add 0xa0
#define read_add 0xa1
uchar a;
sbit sda=p2^0;
sbit scl=p2^1;
void somenop(); //短延时
void init(); //初始化
void check_ack(void);
void i2cstart(void);
void i2cstop(void);
void write_byte(uchar dat);//写字节
void delay(uint z);
uchar read_byte(); //读字节
void write(uchar addr,uchar dat); //指定地址写
uchar read(uchar addr); //指定地址读
bit flag; //应答标志位
void main()
{
init();
write_add(5,0xaa); //向地址5写入0xaa
delay(10); //延时,否则被坑呀!!!
p1=read_add(5); //读取地址5的值
while(1);
}
//***************************************************************************
void delay()//简单延时函数
{ ;; }
//***************************************************************************
void start() //开始信号 scl在高电平期间,sda一个下降沿则表示启动信号
{
sda=1; //释放sda总线
delay();
scl=1;
delay();
sda=0;
delay();
}
//***************************************************************************
void stop() //停止 scl在高电平期间,sda一个上升沿则表示停止信号
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
//***************************************************************************
void respons() //应答 scl在高电平期间,sda被从设备拉为低电平表示应答
{
uchar i;
scl=1;
delay();
//至多等待250个cpu时钟周期
while((sda==1)&&(i《250))i++;
scl=0;
delay();
}
//***************************************************************************
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;
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;//返回数据
}

美国思科完成收购光学芯片制造商Acacia
运动控制器RTEX总线使用入门
虹软开放平台“AI创造营”西安站落幕,深度赋能开发者、助力AI普惠化
如何设计一个小型嵌入式操作系统
基于ISP芯片的机床自动进给数控装置的设计
基于C语言模拟IIC总线来对I2C总线的理解
perl进程管理
什么耳机对耳朵伤害小些?不伤耳的骨传导耳机
SWIFT表示,黑客手段已变得更加成熟,银行存款仍有风险
天津移动5G基站建设完成,将全面推进5G行业应用落地
Arduino/树莓派/单片机/arm区别分析
第八届中国智能产业高峰论坛在成都成功举行
什么是区块链系统思维
iPhone 12大热助力台积电保持领先地位
MS4515DO压力传感器的驱动设计与实现
谷歌第二季营收215亿美元 同比增长超过20%
韩国KAIST为f-VLED研发出一种低成本的生产方法
使用基本命令来查看Linux版本号
中信科移动实现重大突破:推动我国5G发展迈向新高度!
什么是函数的调用?