【I²C(iic)-总线协议详解及故障分析】

1 IIC的基本介绍

对于嵌入式开发人员来说,IIC通信大家应该都很熟悉,

1.1 IIC的简介

IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。

IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
IIC总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

2 IIC数据格式

2.1 字节传输

在每个时钟脉冲期间传输一个数据位。SDA行上的数据必须在时钟脉冲的HIGH期间保持稳定,因为此时SDA行上的变化将被解释为START或STOP。位传输说明如下。
在这里插入图片描述

2.2 开始和结束条件

当总行不忙时,SDA和SCL行都保持高电平。SDA在SCL为HIGH时从高到低的转变定义为START条件(S), SDA在SCL为HIGH时从低到高的转变定义为STOP条件§。START和STOP条件如下所示。

在这里插入图片描述

2.3 系统调整

系统调整如上所示,下面解释了一些单词的定义:
a.发送器:将数据发送到总行的设备。
b.接收器:从总行接收数据的设备。
c.主控:发起传输的设备产生时钟信号,并终止传输。
d.从机:由主机寻址的设备。
e.多主站:多个主站可以尝试同时控制总行而不会损坏消息。
f.公断:确保在多个主机试图同时控制总行时,只允许一个主机这样做并且消息不会损坏的过程。
g.同步:同步两个或多个设备的时钟信号的过程。
在这里插入图片描述

3 总线挂死原因

在排除硬件错误的前提下去分析:

3.1 主机信号挂死

造成主机信号挂死的原因有 硬件IO损坏、软件状态机异常。需要从硬件角度和代码去分析解决。

3.2 主机信号异常

主要原因也在于代码问题

3.3从机拉死总线

IIC数据线是主机从机数据相与的,从机拉低后主机无法再次拉高拉起新的通信。此现象大多出现在信号被干扰时从机丢失Clock或者增加了Clock导致双方时序没有对齐。从机还在维持发送0的状态,从而把SDA拉低了。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 首先,你需要明确I2C总线协议的功能要求,并确定技术细节。其次,使用C语言编写I2C总线协议,可以使用标准的I2C库函数,以及特定于处理器的I2C驱动程序。最后,使用模拟或调试工具来验证I2C总线协议的正确性。 ### 回答2: I²C(Inter-Integrated Circuit)总线协议是一种用于在集成电路之间进行通信的串行总线协议。下面是使用C语言编写I²C总线协议的步骤: 首先,我们需要定义I²C总线的相关参数,包括时钟频率、数据位数和I²C地址等。可以使用宏定义或者全局变量来定义这些参数。 接下来,我们需要实现I²C总线的初始化函数,用于初始化I²C控制器和相关硬件。在初始化函数中,我们需要配置相关引脚的输入输出模式、上下拉电阻等。 然后,我们需要实现发送数据的函数。发送数据的过程包括发送起始位、I²C地址、数据、应答等步骤。通常情况下,我们可以使用位运算来控制每个步骤的时序和数据传输。 接着,我们需要实现接收数据的函数。接收数据的过程与发送类似,只是在发送结束后需要切换为接收模式,并且在接收数据时需要发送应答或非应答信号。 最后,我们可以实现其他辅助函数,例如读写寄存器、发送和接收多个字节的数据等。 在编写以上函数时,我们需要参考相关的I²C总线协议规范和硬件手册,以确保代码的正确性和可靠性。另外,为了提高代码的可读性和可维护性,可以使用适当的注释和模块化设计。 需要注意的是,具体的代码实现可能因硬件平台和具体需求而有所不同。以上只是基本的编写步骤和思路,实际编写过程中还需根据实际情况进行相应的优化和调整。 编写I²C总线协议的代码是一项复杂而精细的任务,需要对硬件和通信协议有深入的理解。因此,在实际应用中建议使用已经存在的I²C库或者驱动程序进行开发,以减少开发时间和复杂度。 ### 回答3: I2C(Inter-Integrated Circuit)总线协议是一种用于连接低速外设的串行通信协议,通过两根传输线SCL(时钟线)和SDA(数据线)进行通信。以下是使用C语言编写I2C总线协议的示例代码。 ```c #include <stdio.h> #include <stdint.h> #define I2C_ACK 0 #define I2C_NACK 1 // 初始化I2C总线 void i2c_init() { // TODO: 设置SCL和SDA引脚和配置相关寄存器 } // 发送一个起始信号 void i2c_start() { // TODO: 设置SDA和SCL引脚状态,产生起始信号 } // 发送一个停止信号 void i2c_stop() { // TODO: 设置SDA和SCL引脚状态,产生停止信号 } // 等待应答信号 int i2c_wait_ack() { // TODO: 读取SDA引脚状态,判断是否接收到应答信号 // 如果接收到应答信号,返回 I2C_ACK // 如果没有接收到应答信号,返回 I2C_NACK } // 发送一个字节 void i2c_write_byte(uint8_t data) { // TODO: 依次发送数据的每一位,同时检测应答信号 } // 读取一个字节 uint8_t i2c_read_byte() { // TODO: 依次读取数据的每一位,同时发送应答信号 // 返回读取的字节数据 } int main() { i2c_init(); // 初始化I2C总线 // 示例: 使用I2C总线向某个设备写入数据 i2c_start(); // 发送起始信号 i2c_write_byte(0xA0); // 发送设备地址和写入标志 i2c_wait_ack(); // 等待应答信号 i2c_write_byte(0x01); // 发送数据 i2c_wait_ack(); // 等待应答信号 i2c_write_byte(0x23); // 发送数据 i2c_wait_ack(); // 等待应答信号 i2c_stop(); // 发送停止信号 // 示例: 使用I2C总线从某个设备读取数据 i2c_start(); // 发送起始信号 i2c_write_byte(0xA1); // 发送设备地址和读取标志 i2c_wait_ack(); // 等待应答信号 uint8_t data = i2c_read_byte(); // 读取数据 i2c_send_ack(I2C_NACK); // 发送非应答信号 i2c_stop(); // 发送停止信号 printf("读取的数据是 %d\n", data); return 0; } ``` 以上示例是一个简单的I2C总线协议的实现。具体的操作需要根据硬件平台和具体的I2C总线驱动进行相应的设置和配置。可以根据实际需求对上述代码进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值