单片机学习小组
登录
直播中
xiangwangzihui
12年用户
511经验值
擅长:模拟技术
私信
关注
ST单片机的I2C怎么操作?
开启该帖子的消息推送
单片机
ST单片机
ST
单片机
的I2C怎么操作?
回帖
(1)
冯敏敏
2022-2-17 12:03:40
ST单片机的I2C总线操作分为主机模式与从机模式。做主机时,由主机提供时钟驱动。在通讯的过程中相关的硬件寄存器会根据某些事件的发生而置位。这样通信的双方就可以根据这些事件标志来控制通信的过程。在实际程序中有两种用法,一种是阻塞式的等待查询法。这种方式下通信过程是在不停地检查各种特定事件的过程中完成的。还有一种是中断处理法,I2C硬件在工作时会产生中断,应用程序在中断处理程序里检查各种硬件中断标志来完成通信过程。下文主要来源于ST的官方标准库文件stm8l10x_i2c.h
I2C
主机模式
下的事件(按通信流程顺序描述)
通讯开始时的EV5
在主机发送开始信号START(I2C_GenerateSTART()函数)之后必须等待EV5事件。此事件出现意味着可以在I2C总线上开始通讯(总线是空闲状态)该时间完成标志在库文件中被定义为:
I2C_EVENT_MASTER_MODE_SELECT = (uint16_t)0x0301
从机确认地址的EV6
在检查EV5后,主机发送从机地址(使用I2C_Send7bitAddress()函数),这个函数还确定本次通信的方向:做发送端或是接收端
然后主机必须等待从机设备发出确认信号ACK。
如果确认信号出现,那么:
1)如果是主机作接收端(7位地址)
那么会是
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED
标志被触发。
2)如果是主机作发送端(7位地址)
那么会是
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED标志
被触发。
3)在10位寻址模式下,主机在发出SRART信号并且检查EV5事件后必须发送10位寻址模式的地址头部分(使用I2C_SendData())
然后主机应该等待EV9事件。EV9事件出现意味着10位寻址模式下的地址头部已经被正确地发送到了总线上。然后,主机应当发送10位地址模式下的地址尾部LSB(使用I2C_Send7bitAddress()).然后主机等待EV6事件;
EV6
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = (uint16_t)0x0782
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED = (uint16_t)0x0302
EV9(10位地址模式下才会出现)
I2C_EVENT_MASTER_MODE_ADDRESS10 = (uint16_t)0x0308
通信过程中的事件:
如果通信已经建立,主机就要开始检查以下事件
1)如果是主机接收模式:主机必须要等待EV7事件,然后接收从机发来的数据(I2C_ReceiveData() function)
2)如果是主机发送模式:主机要马上发送数据(I2C_SendData()),然后等待事件EV8或EV8_2
EV8和EV8_2事件非常相似,但有以下不同:
-EV8事件意味着要发送的数据已经被写入到了数据寄存器,正在逐次进入物理发送器。
-EV8_2事件意味着数据已经确实进入了物理发送器,并且出现在了总线上。
在大多数情况下,使用EV8已经足够了。如果同时还要检查EV8_2事件会导致通信过程变慢,但是这样可以使通信过程有更高的可信度。EV8_2也比EV8更合适用来检查最后一部分数据是否已经成功发送(在STOP信号前的最后数据)
要注意的是,如果我们的软件不能确认最后的字节结尾已经被发送。那我们可以通过同时检查EV7事件和BTF标志(比如. (
I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF
))来确认这一点。不过在这种情况下通信会变慢。
EV7:
I2C_EVENT_MASTER_BYTE_RECEIVED = (uint16_t)0x0340
主机发送模式:
EV8:
I2C_EVENT_MASTER_BYTE_TRANSMITTING = (uint16_t)0x0780
EV8_2
I2C_EVENT_MASTER_BYTE_TRANSMITTED = (uint16_t)0x0784
*********************************************************************************************************************************
I2C
从机模式
下的事件(按照通信过程描述)
通信开始时的事件
首先,单片机作从机时要通过
I2C_AcknowledgeConfig()
函数使能自己的应答模式。另外要设置自己的通信地址。这个地址在
I2C_OwnAddress1
字段中。
主机发送了开始信号
START
并跟随发送了从器件地址后,从机会检查地址是否与自己匹配。如果匹配则会发送一个ACK信号:
1)在一般情况下当主机发送的地址和自己的地址匹配时会出现EV1事件
I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED
xxx
会是
TRANSMITTER
或
RECEIVER
:
I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED
I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED
2)如果主机发送的是
统一呼叫
(发送地址是0x00),并且从机使用函数
I2C_GeneralCallCmd()
使能了统一呼叫应答。那么也会出现EV1事件
I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED
EV1:
一般情况下:
I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED = (uint16_t)0x0202
I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = (uint16_t)0x0682
统一呼叫情况下:
I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED = (uint16_t)0x1200
在EV1事件出现后:
如果是从机接收模式:
EV2: 收到字节数据.
I2C_EVENT_SLAVE_BYTE_RECEIVED = (uint16_t)0x0240
EV4:通信结束(主机发送一个停止信号STOP终止通信).
I2C_EVENT_SLAVE_STOP_DETECTED = (uint16_t)0x0010
从机发送模式下:
EV3:从机发送完毕一个字节数据:
I2C_EVENT_SLAVE_BYTE_TRANSMITTED = (uint16_t)0x0684
I2C_EVENT_SLAVE_BYTE_TRANSMITTING = (uint16_t)0x0680
EV3_2:主机发送了NACK信号,之后从机就等待主机发送STOP信号也就是EV4事件;
I2C_EVENT_SLAVE_ACK_FAILURE = (uint16_t)0x0004
接收模式下事件
I2C_EVENT_SLAVE_BYTE_TRANSMITTED
和
I2C_EVENT_SLAVE_BYTE_TRANSMITTING
功能很接近.
I2C_EVENT_SLAVE_BYTE_TRANSMITTING
事件检测是可选的。用于确认EV3事件发生时数据传输正确完成。
正常通信时的时序:
ST单片机的I2C总线操作分为主机模式与从机模式。做主机时,由主机提供时钟驱动。在通讯的过程中相关的硬件寄存器会根据某些事件的发生而置位。这样通信的双方就可以根据这些事件标志来控制通信的过程。在实际程序中有两种用法,一种是阻塞式的等待查询法。这种方式下通信过程是在不停地检查各种特定事件的过程中完成的。还有一种是中断处理法,I2C硬件在工作时会产生中断,应用程序在中断处理程序里检查各种硬件中断标志来完成通信过程。下文主要来源于ST的官方标准库文件stm8l10x_i2c.h
I2C
主机模式
下的事件(按通信流程顺序描述)
通讯开始时的EV5
在主机发送开始信号START(I2C_GenerateSTART()函数)之后必须等待EV5事件。此事件出现意味着可以在I2C总线上开始通讯(总线是空闲状态)该时间完成标志在库文件中被定义为:
I2C_EVENT_MASTER_MODE_SELECT = (uint16_t)0x0301
从机确认地址的EV6
在检查EV5后,主机发送从机地址(使用I2C_Send7bitAddress()函数),这个函数还确定本次通信的方向:做发送端或是接收端
然后主机必须等待从机设备发出确认信号ACK。
如果确认信号出现,那么:
1)如果是主机作接收端(7位地址)
那么会是
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED
标志被触发。
2)如果是主机作发送端(7位地址)
那么会是
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED标志
被触发。
3)在10位寻址模式下,主机在发出SRART信号并且检查EV5事件后必须发送10位寻址模式的地址头部分(使用I2C_SendData())
然后主机应该等待EV9事件。EV9事件出现意味着10位寻址模式下的地址头部已经被正确地发送到了总线上。然后,主机应当发送10位地址模式下的地址尾部LSB(使用I2C_Send7bitAddress()).然后主机等待EV6事件;
EV6
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = (uint16_t)0x0782
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED = (uint16_t)0x0302
EV9(10位地址模式下才会出现)
I2C_EVENT_MASTER_MODE_ADDRESS10 = (uint16_t)0x0308
通信过程中的事件:
如果通信已经建立,主机就要开始检查以下事件
1)如果是主机接收模式:主机必须要等待EV7事件,然后接收从机发来的数据(I2C_ReceiveData() function)
2)如果是主机发送模式:主机要马上发送数据(I2C_SendData()),然后等待事件EV8或EV8_2
EV8和EV8_2事件非常相似,但有以下不同:
-EV8事件意味着要发送的数据已经被写入到了数据寄存器,正在逐次进入物理发送器。
-EV8_2事件意味着数据已经确实进入了物理发送器,并且出现在了总线上。
在大多数情况下,使用EV8已经足够了。如果同时还要检查EV8_2事件会导致通信过程变慢,但是这样可以使通信过程有更高的可信度。EV8_2也比EV8更合适用来检查最后一部分数据是否已经成功发送(在STOP信号前的最后数据)
要注意的是,如果我们的软件不能确认最后的字节结尾已经被发送。那我们可以通过同时检查EV7事件和BTF标志(比如. (
I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF
))来确认这一点。不过在这种情况下通信会变慢。
EV7:
I2C_EVENT_MASTER_BYTE_RECEIVED = (uint16_t)0x0340
主机发送模式:
EV8:
I2C_EVENT_MASTER_BYTE_TRANSMITTING = (uint16_t)0x0780
EV8_2
I2C_EVENT_MASTER_BYTE_TRANSMITTED = (uint16_t)0x0784
*********************************************************************************************************************************
I2C
从机模式
下的事件(按照通信过程描述)
通信开始时的事件
首先,单片机作从机时要通过
I2C_AcknowledgeConfig()
函数使能自己的应答模式。另外要设置自己的通信地址。这个地址在
I2C_OwnAddress1
字段中。
主机发送了开始信号
START
并跟随发送了从器件地址后,从机会检查地址是否与自己匹配。如果匹配则会发送一个ACK信号:
1)在一般情况下当主机发送的地址和自己的地址匹配时会出现EV1事件
I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED
xxx
会是
TRANSMITTER
或
RECEIVER
:
I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED
I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED
2)如果主机发送的是
统一呼叫
(发送地址是0x00),并且从机使用函数
I2C_GeneralCallCmd()
使能了统一呼叫应答。那么也会出现EV1事件
I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED
EV1:
一般情况下:
I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED = (uint16_t)0x0202
I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = (uint16_t)0x0682
统一呼叫情况下:
I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED = (uint16_t)0x1200
在EV1事件出现后:
如果是从机接收模式:
EV2: 收到字节数据.
I2C_EVENT_SLAVE_BYTE_RECEIVED = (uint16_t)0x0240
EV4:通信结束(主机发送一个停止信号STOP终止通信).
I2C_EVENT_SLAVE_STOP_DETECTED = (uint16_t)0x0010
从机发送模式下:
EV3:从机发送完毕一个字节数据:
I2C_EVENT_SLAVE_BYTE_TRANSMITTED = (uint16_t)0x0684
I2C_EVENT_SLAVE_BYTE_TRANSMITTING = (uint16_t)0x0680
EV3_2:主机发送了NACK信号,之后从机就等待主机发送STOP信号也就是EV4事件;
I2C_EVENT_SLAVE_ACK_FAILURE = (uint16_t)0x0004
接收模式下事件
I2C_EVENT_SLAVE_BYTE_TRANSMITTED
和
I2C_EVENT_SLAVE_BYTE_TRANSMITTING
功能很接近.
I2C_EVENT_SLAVE_BYTE_TRANSMITTING
事件检测是可选的。用于确认EV3事件发生时数据传输正确完成。
正常通信时的时序:
举报
更多回帖
rotate(-90deg);
回复
相关问答
单片机
ST单片机
基于AVR
单片机
的
I2C
操作
库
2020-11-09
907
如何在PSOC和
ST
之间实现
I2C
通信?
2023-01-17
298
请问
I2C
从
机
单片机
接收程序怎么写?
2019-10-21
3052
如何使用高速通用
I2C
接口与
单片机
相连接?
2021-04-22
1969
如何使用
单片机
I
/O口模拟
I2C
信号读取SHT30温湿度。
2018-02-05
9747
51
单片机
能不能io模拟
i2c
从
机
?
2023-11-02
257
89
c
51
单片机
模拟
i2c
总线怎么实现一主多从呢?
2023-05-08
1437
请问
ST
单片机
带CAN总线和
I
²
C
的有哪些型号?
2019-08-06
2080
LPC1768
单片机
硬件
I2C
中断驱动OLED的问题
2019-01-20
2736
请教用
单片机
模拟出HID
I2C
通信的实例
2018-10-30
3034
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分