当前位置: 首页 > news >正文

【自学嵌入式:51单片机】I2C通信

目录
  • I2C总线
    • 两线制
    • 多主多从
    • 双向
    • 同步通信
    • 半双工
    • 串行通信
  • I2C通信数据传输流程
    • 启动信号
    • 地址位和读写位
    • 应答信号
    • 发送数据
    • 停止信号
    • 按读和写两种模式来看I2C通信
  • I2C通信总结
  • 代码实现
    • 发送启动信号
    • 发送停止信号
    • 发送数据
    • 接收数据
    • 接收应答信号
    • 发送应答信号

I2C总线

I2C总线(读作I方C总线),全称Inter-Integrated Circuit,它是由飞利浦公司研发的二线制、多主多从、双向、同步、半双工的串行总线。I2C通信就是利用I2C总线进行数据传输,

两线制

只需要两个引脚进行数据传输
设备间能发送数据,主要是通过SDA这个数据引脚传输,传低电平把SDA拉低,传高电平就是把SDA拉高
image
用时钟信号SCL引脚控制传输的节拍。

多主多从

多主多从是指在这一个I2C总线上可以有多个主机和多个从机
image

当然也可以一主一从或者一主多从
image

image
主机多为控制芯片(单片机),从机多为显示设备或传感器等
image
主机是可以发出命令的设备,从机是能接收命令的设备
image
通信规则

  • 任何时刻,从机只接收一个主机的命令;
  • 多主机情况下,从机优先接收最先发送命令的主机的命令;
  • 为了区分命令发给谁,每个设备都有自己的地址,即每个设备都有设备ID。

双向

双向是指,主机可以向从机发送数据,也可以接收从机发来的数据,从机可以接收主机发来的数据,也可以向主机发送数据,传输数据的方向是双向的

同步通信

image
I2C通信通过设备的SCL引脚传递时钟信号,对数据传输进行同步

半双工

image
数据传送虽然是双向,但是数据线就一根,需要分时传送,即任何时刻只能有一个方向的数据传输

串行通信

传输数据时是一位一位从高位开始从高到底传输,也就是发送一个字节,首先发送的是这个字节对应的最高位二进制,接收一个字节也是同理

I2C通信数据传输流程

image

一次完整的I2C通信包括:(1)启动信号;(2)发送地址位和读写位(放在一个字节里面发送);(3)接收应答位;(4)发送数据(接收数据);(5)接收(发送)应答位;(6)停止信号

启动信号

image

每一次I2C通信,先以一个启动信号开始,I2C通信有固定的启动信号,在程序中只要按具体时序图要求发送启动信号。
如上图,也就是SDA下降沿,SCL高电平。

地址位和读写位

靠地址位找到对应的通信设备,也称为寻址,每个从机都有一个固定的器件地址,有7位的,有10位的,下面只介绍7位的地址,每次通信设备的地址要设定准确。
image
比如olde屏幕,通常是主机对其进行写操作,读写位置0,其他7位记录要通信的设备地址

应答信号

image

主机在发送为地址位和读写位后,就会等待接收一位数据,根据这个数据判断从机是否正确地应答了,数据0表示接收数据成功,即正确应答,数据1表示未成功接收,即非应答。
主机接收完数据同样要给从机发送应答信号,也是数据0表示接收数据成功,即正确应答,数据1表示未成功接收,即非应答。

发送数据

依次将一个字节8位二进制从高位到低位发送

停止信号

image

SCL高电平,SDA上升沿,一次I2C通信完成就要以停止信号结束

按读和写两种模式来看I2C通信

按读和写两种不同模式,I2C通信过程也有所不同
写模式:
image
读模式:
image

当从机内部也有不同寄存器代表不同功能时,就需要区分,发布的数据是要写入哪个寄存器的,在发送完地址位和读写位并收到应答位后,要先发送内部寄存器的地址,仍然是将地址以一个8位数据发送过去,收到应答后,收到应答后,再继续发送要写入到这个寄存器的数据
image

这一部分都可以称为是发送数据

I2C通信总结

image

代码实现

image

I2C通信的波特率是100K,也就是每秒传送10万个位,取倒数,一位传送实际是10微秒,也就是SCL的时钟周期不能小于10微秒
image
也就是它的高电平和低电平的总时长不能小于10微秒
image

所以平均一下就是高电平和低电平的时间都不要小于5微秒
我这个板子的晶振是11.0592Mhz,一个机器周期是正好的1微秒,Delay函数中四个空语句,恰好是4个机器周期,也就是4微秒,在程序中利用这一语句实现传输速率的调整

//I2C通信专用延时程序
void delayI2C()
{_nop_();_nop_();_nop_();_nop_();
}

发送启动信号

image

//初始化I2C通信
void initI2C()
{//先都拉高成高电平SCL = 1;SDA = 1;//下降沿delayI2C();SDA = 0;delayI2C();SCL = 0;
}

【注】REGX52.H并没有包含SCL SDA位,要看对应的通信的模块的引脚和单片机引脚的连接

发送停止信号

image
SCL先高电平,SDA上升沿

//关闭I2C通信
void closeI2C()
{//先都拉低SCL = 0;SDA = 0;delayI2C();SCL = 1; //先拉高SCLdelayI2C();SDA = 1; //SCL高电平期间,再拉高SDA,这样就产生了一个上升沿delayI2C();}

发送数据

image

发送数据的规则就是,在SCL低电平期间,将要传送的数据位放到SDA线上,然后拉高SCL,从机在SCL高电平期间,读取SDA线上的数据依次循环8次就可以将一个字节的数据传送出去,

//I2C写入一个字节,I2C_Byte是待传送的数据
void writeByteI2C(unsigned char I2C_Byte)
{unsigned char i = 0;for(i = 0; i<8; i++){//I2C_Byte & 0x80(1000 0000)//获取最高位,看是1还是0if(I2C_Byte & 0x80){SDA = 1;}else{SDA = 0;}delayI2C();SCL = 1;delayI2C();SCL = 0;I2C_Byte <<= 1; //左移,循环读取每一位,让每一位都成为首位}
}

接收数据

// I2C读一个字节
unsigned char readByteI2C()
{unsigned char i, Byte = 0x00;for(i = 0; i<8; i++){SDA = 1; //拉高SDA,释放I2C总线//读总线之前一定要将SDA拉高SCL = 1; //然后将SCL拉高,准备接收SDA状态delayI2C();if(SDA){Byte |= (0x80>>i); //依次循环右移,得到一个字节(0x00分别或每一位得到,如果是低电平,不需要操作,该位就是0)}SCL = 0;}return Byte;
}

接收应答信号

image

//读取I2C总线应答信号
bit readAckI2C()
{bit Ack_bit; //应答信号SDA = 1; //拉高SDA,释放I2CdelayI2C();SCL = 1; // 把SCL拉高,第9个时钟信号delayI2C();Ack_bit = SDA; //读取应答信号delayI2C();SCL = 0; //拉低SCL,结束接收应答return Ack_bit;
}

发送应答信号

主机在接收完数据后,会给从机发送应答信号,主机成功接收,会在数据线SDA发送0,接收失败会发送1
image

//I2C发送应答位
void writeAckI2C(bit Ack_bit)
{//根据应答状态变量来确定SDA是1还是0if(Ack_bit){SDA = 1;}else{SDA = 0;}//第9个时钟周期//拉高SCL,再拉低SCL,完成一次发送应答信号SCL = 1; SCL = 0;
}
http://www.sczhlp.com/news/3585/

相关文章:

  • Python Ta-Lib库在容器中的安装
  • next-key lock - Charlie
  • IDEA连接达梦数据库 - 呓语
  • JSUT DO ONCE
  • 408-OS之银行家算法
  • FANUC CNC Guide v25.0 安装教程
  • Python三大Web框架:FastAPI vs Flask vs Django 详解与敏捷入门指南
  • 椰子味的暑假清单
  • 模拟赛 T2 题解
  • 框架历理 电商公式分类
  • day8
  • CF1837F Editorial for Two 2025.8.1模拟赛题解
  • WSL 安装 Debian后,换源tsinghua.edu.cn 无法更新
  • 对象存储MinIO
  • 7.1
  • [PaperReading] KIMI K2: OPEN AGENTIC INTELLIGENCE
  • cmake学习笔记
  • 想控利润,就得先把生产成本拆明白 - 智慧园区
  • 8/1
  • 虚拟机安装冬瓜HAOS
  • STM32学习笔记(13)——模数转换ADC
  • STM32学习笔记(11)——定时器初步应用(1)
  • STM32学习笔记(12)——定时器初步应用(2)
  • PVE9 Beta保姆级升级教程!PVE8→PVE9轻松升级
  • python多版本控制
  • 2025.8.1
  • 20250801-36
  • 20250801
  • 20250801 做题记录
  • 使用CSS Grid布局实现响应式设计