1. I2C协议
1.1 物理层
I2C协议和摩托罗拉公司的SPI协议一样,是一种通讯协议。串行外围设备接口,是一种高速全双工的通信总线,是由 Phiilps 公司开发的。由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
I2C(Inter-Integrated Circuit),也可以叫IIC、I2C,译作集成电路总线,是两线式串行通信总线,用于设备间的通讯等,标准情况下最高传送速率达100Kbps。顾名思义,I2C通讯只需要两根线,一根是数据线SDA(Serial Data Line),一根是时钟线SCL(Serial Clock Line)。主设备控制时钟线决定I2C的波特率,配合数据线进行数据的传输,这两根线分别通过上拉电阻连接到电源。
1.2 信号
- 空闲状态:I2C总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
- 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
- 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
如何通俗地理解起始信号和停止信号呢?
我们可以把SDA当作一个单刀单掷的开关,把开关放下去(就是SDA由高到低的过程),SDA和SCL就接通了,就可以看成是开始(起始)。反之,把开关抬起来(就是SDA由低到高的过程),SDA和SCL就断开了,就可以看成是结束(停止)。
- 应答信号ACK
发送器每发送一个字节(8位),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接受了该字节(就是说当已经接收完第八位信号的时候,也就是已经完整接收一个字节了,就要开始把SDA数据线下拉了);应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
1.3 数据传输
在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
IIC读写过程
首先主机会产生一个起始信号,开始数据的传输。然后主机向从机发送地址位和读写位0(因为要确定哪个从机以及做什么操作),应答成功后,就会开始发送数据,从机会根据接收到的数据返回有效应答或者无效应答,直到主机产生停止信号,就表示这段传输结束了。
2. CubeMx的相关配置与相关代码
2.1 CubeMx配置
时钟树配置这里就忽略了哦~(我的单片机型号是STM32G473VET6)
传输速率根据工程的需要自己选择,最高可以到1MHz
2.2 重要函数
2.2.1 写数据
HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint8_t *pData,uint16_t Size,uint32_t Timeout);
- 功能: 写数据
- 参数:
*hi2c 设置使用的是那个IIC 例:&hi2c1
DevAddress 写入的地址 设置写入数据的地址 例:0xA0
*pData 需要写入的数据
Size 需要发送的字节数
Timeout 最大传输时间,超过传输时间将自动退出传输函数
// 发送两个字节数据,IIC写数据函数
- 例如:HAL_I2C_Master_Transmit(&hi2c1,0xA0,(uint8_t*)TxData,2,1000);
2.2.2 接收数据
HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint8_t *pData,uint16_t Size,uint32_t Timeout);
- 功能: 接收数据
- 参数:
*hi2c 设置使用的是那个IIC 例:&hi2c2
DevAddress 写入的地址 设置写入数据的地址 例:0xA0
*pData 存储读取到的数据
Size 需要发送的字节数
Timeout 最大传输时间,超过传输时间将自动退出传输函数
2.2.3 写多个数据
HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
- 功能:IIC写多个数据,该函数适用于IIC外设里面还有子地址寄存器的地址,比如E2PROM,除了
设备地址,每个存储字节都有其对应的地址。
- 参数:
*hi2c 设置使用的是那个IIC 例:&hi2c2
DevAddress 写入的地址 设置写入数据的地址 例:0xA0
MemAddress 从机寄存器地址,每写入一个字节数据,地址就会自动+1
MemAddSize 从机寄存器地址字节长度 8位/16位
写入数据的字节类型 8位/16位
I2C_MEMADD_SIZE_8BIT
I2C_MEMADD_SIZE_16BIT
*pData 需要写入的数据的起始地址
Size 传输数据的大小,需要发送的字节数
Timeout 最大传输时间,超过传输时间将自动退出传输函数
- 例如:HAL_I2C_Mem_Write(&hi2c1,ADDR,i,I2C_MEMADD_SIZE_8BIT,&(I2C_Buffer_Write[i]),8,1000);
2.2.4 MX生成的初始化函数
/**
* @brief I2C1 Initialization Function
* @param None
* @retval None
*/
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1; //句柄
hi2c1.Init.ClockSpeed = 100000; //时钟速度
hi2c1.Init.DutyCycle =。I2C_DUTYCYCLE_2; //I2C的SCL线时钟的占空比
hi2c1.Init.OwnAddress1 = 0; //I2C设备的地址。地址可设置为7位或10位。
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; //7位寻址模式
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
结束,作者水平有限,希望各位发现有错之后及时指正,谢谢文章来源:https://www.toymoban.com/news/detail-832024.html
如果喜欢作者的文章,记得点赞收藏关注哦!文章来源地址https://www.toymoban.com/news/detail-832024.html
到了这里,关于STM32基于CubeMX与HAL库的I2C应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!