STM32F1x HAL库学习笔记(9)硬件 I2C(IIC)主从机的配置
本文开发环境:
- MCU型号:STM32F103ZET6
- IDE环境: MDK 5.27
- 代码生成工具:STM32CubeMx 5.4.0
- HAL库版本:STM32Cube_FW_F1_V1.8.0
本文内容:
- STM32CubeMx 配置主从I2C(IIC)
- 示例工程
一、简介
I2C 是一种双线协议,由一根时钟线和一根数据线组成,由于时序简单,应用广泛,ST 硬件 I2C 网传不够稳定,通常也用软件来模拟,不过由于软件模拟需要占用CPU的资源,所以在一些情况下,硬件I2C是更好的选择。本文示例了 I2C 的主从通信,由于 STM32F103ZE 拥有2个硬件I2C,所以只需要一个单片机即可模拟双机的通信。
二、使用 STM32CubeMx 配置 I2C
使用 STM32CubeMx(以下简称 Mx) 可以非常方便的配置硬件I2C,一般有以下几个步骤:
- 选择目标单片机
- 选择系统时钟源,配置系统时钟树
- 打开调试 IO 口
- 配置 I2C:选择速度,配置地址等
- 生成指定 IDE 的工程
三、硬件I2C的配置
- 创建一个新的工程:
- 选择目标单片机(STM32F103ZET6):
- 选址时钟源:
一般单片机的最小系统板,都有外部晶振,这里可根据实际需求来配置。
-
配置系统时钟树:
-
打开调试:
-
配置 I2C 主机:
由于本文目的是把 I2C 配置为主机,所以其实只有2个选项需要配置,这里保持默认,即使用 标准模式,频率100KHz。
- 配置 I2C 从机:
- 基本配置:
2.打开中断:
- 基本配置:
从机需要配置作为从机时的地址,I2C需要地址,这样就可以实现一对多的通信。地址有2种,7位和10位,本文选择默认的7位。另外,从机需要打开中断,以便使用中断来接收数据。
- 配置工程的基本信息
- 生成工程
至此已经完成了所有工程的配置,点击GENERATE CODE
即可生成工程:
三、外部上拉
需要注意的是,I2C标准中定义了IO口为开漏模式,所以需要上拉电阻,在进行编程测试之前,请保证 I2C 有外部上拉是电阻,本文上拉电阻为 4.7K:
四、编程
1. 准备
环境已经准备完成以后,就可以编程来测试代码,Mx 默认是使用 HAL 库来初始化外设,所以可以调用 HAL 的 API 函数来测试 I2C 的通信功能。
本文示例选用以下 2个数组和3 个函数来测试:
//接收和发送数组
static uint8_t I2C_recvBuf[10] = {0};
static uint8_t I2C_sendBuf[10] = {0,1,2,3,4,5,6,7,8,9};
//HAL 接口函数
HAL_I2C_Master_Transmit(); //主机堵塞发送
HAL_I2C_Slave_Receive_IT(); //从机中断接收
HAL_I2C_SlaveRxCpltCallback(); //接收完成回调函数
2. 程序实现
具体程序如下所示:
// #1.定义数组
static uint8_t I2C_recvBuf[10] = {0};
static uint8_t I2C_sendBuf[10] = {0,1,2,3,4,5,6,7,8,9};
int main(void)
{
......
// #2.使能从机中断接收
HAL_I2C_Slave_Receive_IT(&hi2c2/*接收的I2C*/,I2C_recvBuf/*存放数据的地址*/,sizeof(I2C_recvBuf)/*接收数据的个数*/);
while (1)
{
......
// #3.主机发送数据
HAL_I2C_Master_Transmit(&hi2c1/*发送的I2C*/, (20<<1)|0x00/*地址*/, I2C_sendBuf/*发送数据的地址*/, sizeof(I2C_sendBuf/*发送的字节*/), 1000、/*等待的时间*/);
}
}
/* 从机接收回调函数 */
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
/* 再次打开 I2C 中断接收 */
HAL_I2C_Slave_Receive_IT(&hi2c2,I2C_recvBuf,sizeof(I2C_recvBuf));
}
需要注意,在I2C2完成一次接收一次,会关闭中断,并调用回调函数HAL_I2C_SlaveRxCpltCallback()
所以,可以在回调函数中写入数据处理的语句,但是需要运行HAL_I2C_Slave_Receive_IT()
来开启接收中断。
3. 验证
将 I2C1 和 I2C2 连接起来,也就是连接主机和从机:
- PB6 --> PB10
- PB7 --> PB11
该程序有多种验证的方法:
- 在回调函数中,打印
I2C_recvBuf
的值,查看是否和发送的一致。这需要额外添加打印的代码 - 使用硬件仿真,通过变量观察窗口查看
I2C_recvBuf
的值,这需要ST-LINK或J-Link调试器 - 使用 逻辑分析仪/示波器 直接进行时序的分析,这需要一个逻辑分析仪示波器
本文使用 硬件仿真 的方式:
- 运行程序仿真后,将
I2C_recvBuf
添加到Watch1
观察串口中:
2 . 观察Watch1
中,I2C_recvBuf
[] 的值:
五、注意事项
- I2C 总线必须外部上拉
- HAL 库在完成一个中断接收后,会关闭中断,所以需要在回调函数中再次打开
- 一些 MCU 在调用主机发送时,可能会一直返回数值2,即对于错误:
HAL_BUSY
,若排除上拉电路问题,可能是遇到 I2C 死锁现象,在官方勘误文件已经做出了应对的方法,详见: 【InterFace】STM32 I2C 死锁问题
六、附件
百度云连接
STM32F103ZE HW_I2C MDK_Project
提取码:5ugn
下一篇: Asp.NET调用百度翻译的方法