【STM32 HAL库】IIC通信与CubeMX配置

embedded/2024/9/23 10:21:40/

【STM32 HAL库】IIC通信与CubeMX配置

  • 前言
  • 理论
    • IIC总线时序图
    • IIC写数据
    • IIC读数据
  • 轮询模式
    • CubeMX配置
    • 应用示例
      • AHT20初始化
      • 初始化函数
      • 读取说明
      • 读取函数
  • 中断模式
    • CubeMX配置
    • 状态机图
    • fsm.c
    • aht20.c
  • DMA模式
    • CubeMX配置
    • 代码

前言

本文为笔者学习 IIC 通信的总结,基于keysking的视频内容,如有错误,欢迎指正

理论

在这里插入图片描述

IIC总线时序图

在这里插入图片描述

IIC写数据

在这里插入图片描述

IIC读数据

在这里插入图片描述

通信流程(以AHT20为例)

  • STM32主机)发送 IIC 启动信号
  • STM32 发送 AHT20(从机)地址
  • AHT20 识别地址并发送 ACK 信号
  • AHT20 发送数据至 STM32(发送完1 字节后结束
  • STM32 发送 ACK 信号表示接收完成
  • STM32重复接收下一个字节
  • 直至AHT20数据发送完成,STM32 发送 IIC 结束信号

IIC vs 串口通信:

  • IIC为半双工,串口为全双工

  • IIC 可支持多设备通信: IIC通信为总线协议,总线上每个从机都有唯一的地址,主机IIC通信先发送从机地址,非目标从机会忽略数据

  • 同步通信: STM32 的晶振提供统一时钟源,为IIC总线上的从机提供统一时钟信号(尤其可为无晶振提供精确时钟信号的小型传感器提供精确的同步时钟信号

  • 轮询模式:CPU持续搬运数据,程序执行被阻塞

  • 中断模式:CPU只在搬运数据时介入,正常情况下不阻塞程序

  • DMA模式:DMA自动搬运数据,无需CPU介入,节省资源

轮询模式

以AHT20温湿度传感器为例

CubeMX配置

在这里插入图片描述

应用示例

AHT20初始化

在这里插入图片描述

初始化函数

#include "aht20.h"
#define AHT20_ADDRESS 0x70void AHT20_Init() {uint8_t readBuffer;	//定义读缓冲器HAL_Delay(40);  // 上电后等待40msHAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &readBuffer, 1, HAL_MAX_DELAY);  // 读取AHT20 1字节状态字 判断AHT20当前状态if ((readBuffer & 0x08) == 0x00) {  // 检查状态字的 Bit[3] 是否为 1uint8_t sendBuffer[3] = {0xBE, 0x08, 0x00};  // 初始化命令(初始化指令+初始化参数HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);  // 发送初始化命令}
}

ps:
1.AHT20 地址定义为 0x70,实际为 7 位地址,左移 1 位后补 1 位用于区分读/写操作(0 表示写,1 表示读)。
2.I²C 的发送与接收函数先发送从机地址,待从机应答后再发送"发送"或"接收"请求。因此,初始化函数中的接收操作是在发送 AHT20 地址后,接收其状态字。

读取说明


AHT20数据存放形式
除去IIC硬件地址外,一共6个字节的数据:1字节状态字,3.5字节湿度数据,3.5字节温度数据
在这里插入图片描述
信号转换
在这里插入图片描述

读取函数

AHT20读取温湿度数据函数

void AHT20_Read(float *Temperature, float *Humidity) {uint8_t sendBuffer[3] = { 0xAC, 0x33, 0x00 };	//发送缓冲区存放"触发测量"命令+参数uint8_t readBuffer[6];	//定义接收缓冲区(6个字节,6*8bits,分别对应状态、湿度数据1、湿度数据2、湿度和温度数据3、温度数据4、温度数据5.共6字节HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);	//发送"触发测量"命令,AHT20开始测量HAL_Delay(75);//等待75ms待测量完成HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, readBuffer, 6, HAL_MAX_DELAY);//判断状态字(readbuffer[0]的Bit[7]是否为0,也即状态字的第八位(最高位)是否为0)if ((readBuffer[0] & 0x80) == 0x00) {uint32_t data = 0;	//32位data用来存放20位的湿度数据和温度数据// 计算湿度(位运算,拼接数据)data = ((uint32_t)readBuffer[3] >> 4) + ((uint32_t)readBuffer[2] << 4) + ((uint32_t)readBuffer[1] << 12);*Humidity = data * 100.0f / (1 << 20);	//相对湿度转换// 计算温度(位运算拼接数据)data = (((uint32_t)readBuffer[3] & 0x0F) << 16) + ((uint32_t)readBuffer[4] << 8) + (uint32_t)readBuffer[5];*Temperature = data * 200.0f / (1 << 20) - 50;	//温度转换}
}

中断模式

基本原理同串口的中断模式发送
但,因为I2C通信协议的复杂性多步骤的工作流程使得状态机成为管理I2C中断与DMA模式的有效手段
仅依赖发送和接收完成的中断嵌套,没有标志位的参与,也难以完成逻辑处理,所以状态机是必须的

CubeMX配置

在这里插入图片描述

以AHT20温湿度传感器为例

状态机图

在这里插入图片描述
状态机标志位

// 0: 初始状态 发送测量命令 1: 正在发送测量命令 2: 测量命令发送完成 等待75毫秒后读取AHT20数据 3: 读取中 4: 读取完成 解析并展示数据然后恢复到初始状态
uint8_t aht20State = 0;		//定义并初始化aht20初始状态为初始状态

fsm.c

void fsm(void)
{switch(aht20State)case 0:		//向aht20发送测量命令,并切换状态为发送中aht20_measure();aht20State = 1;break;case 1:		//发送中状态不执行任何操作,待发送完成后在中断回调函数中切换状态break;case 2:		//发送完成状态下,延时75ms后发送"获取aht20温湿度数据",开始接收aht20的温湿度数据,并切换状态为读取中HAL_Delay(75);aht20_get();aht20State = 3;break;case 3:		//读取中状态不执行任何操作,待读取完成后在中断回调函数中切换状态break;			case 4:		//读取完成状态时,进行aht20的温湿度数据解析,并发送给上位机。延时1s后切换状态为初始状态AHT20_Analysis(&temperature, &humidity);sprintf(message, "温度: %.1f ℃, 湿度: %.1f %%\r\n", temperature, humidity);HAL_UART_Transmit(&huart2, (uint8_t*)message, strlen(message), HAL_MAX_DELAY);HAL_Delay(1000);aht20State = 0;break;		
}void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {if (hi2c == &hi2c1) {aht20State = 2;		//在发送完成中断中实现状态切换}
}void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {if (hi2c == &hi2c1) {aht20State = 4;		//在接收完成中断中实现状态切换}
}

aht20.c

将AHT20的逻辑代码拆分为最基本的功能模块,以便状态机在各个状态下执行相应任务

void aht20_measure() {static uint8_t sendBuffer[3] = { 0xAC, 0x33, 0x00 };HAL_I2C_Master_Transmit_IT(&hi2c1, AHT20_ADDRESS, sendBuffer, 3);
}void aht20_get() {HAL_I2C_Master_Receive_IT(&hi2c1, AHT20_ADDRESS, readBuffer, 6);
}void aht20_analysis(float *Temperature, float *Humidity) {if ((readBuffer[0] & 0x80) == 0x00) {uint32_t data = 0;data = ((uint32_t)readBuffer[3] >> 4) + ((uint32_t)readBuffer[2] << 4) + ((uint32_t)readBuffer[1] << 12);*Humidity = data * 100.0f / (1 << 20);data = (((uint32_t)readBuffer[3] & 0x0F) << 16) + ((uint32_t)readBuffer[4] << 8) + (uint32_t)readBuffer[5];*Temperature = data * 200.0f / (1 << 20) - 50;}
}

DMA模式

CubeMX配置

在这里插入图片描述
在这里插入图片描述

代码

只需将上述I2C中断模式收发的函数改为DMA模式收发即可
也即 IT —> DMA


http://www.ppmy.cn/embedded/112267.html

相关文章

HTTP反向代理教学:轻松实现代理IP的妙用

在当今互联网时代&#xff0c;代理IP已经成为了很多人上网必不可少的工具。无论是为了保护隐私&#xff0c;还是为了更好地管理网络流量&#xff0c;代理IP都能发挥重要作用。今天&#xff0c;我们就来聊聊HTTP反向代理这个神奇的东西&#xff0c;教你如何轻松实现代理IP的妙用…

使用vue2+axios+chart.js画折线图 ,出现 RangeError: Maximum call stack size exceeded 错误

目录 效果图 解决方案 修正要点 效果图 修改前App.vue代码&#xff1a; <template><div id"app"><canvas id"myChart"></canvas></div> </template><script> import axios from axios; import { Chart, regis…

TDengine 与飞腾腾锐 D2000 完成兼容互认证,推动国产软硬件深度融合

在国家信息安全和自主可控技术日益受到重视的背景下&#xff0c;国产软硬件的发展已成为推动数字经济的重要力量。随着全球科技竞争加剧&#xff0c;企业在选择技术解决方案时&#xff0c;越来越倾向于采用国产产品以降低对外部技术的依赖。这一趋势不仅是为了确保数据安全与隐…

docker打包前端项目

&#x1f389; 前言 之前有出过一期打包后端项目和数据库的教程&#xff0c;现在填个坑&#xff0c;出一期打包前端项目的教程&#xff0c;废话不多说&#xff0c;我们直接进入正题。 &#x1f389; 编写Dockerfile文件 老规矩&#xff0c;先描述项目结构&#xff0c;结构图…

开源反向代理工具-Nginx

Nginx简介 NGINX 是一种高性能的反向代理服务器、负载均衡器和 HTTP 缓存服务器。它的设计初衷是为了应对高并发和低资源消耗&#xff0c;尤其适合处理大量的短连接请求。NGINX 的高效性能来自其事件驱动架构和异步非阻塞的处理方式。 Nginx工作原理 1.事件驱动模型 Nginx使用…

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测 目录 多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-LSSVM贝叶斯优化最小二乘支…

MySQL原理之UUID主键分析,插入或更新语法分析

文章目录 1 MySQL不能用UUID做主键1.1 前言1.2 mysql和程序实例1.2.1 准备工作1.2.2 开始测试1.2.3 程序写入结果1.2.4 效率测试结果 1.3 使用uuid和自增id的索引结构对比1.3.1 自增id1.3.2 uuid 1.4 自增id缺点1.5 雪花算法 2 插入或更新2.1 on duplicate key2.1.1 定义2.1.2 …

工厂方法模式和抽象工厂模式

工厂方法模式 一个工厂只能创建一种产品 工厂方法模式的结构 工厂方法模式包含以下4个角色 Product&#xff08;抽象产品&#xff09; ConcreteProduct&#xff08;具体产品&#xff09; Factory&#xff08;抽象工厂&#xff09; ConcreteFactory&#xff08;具体工厂…