【STM32 HAL库】IIC通信与CubeMX配置
【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
相关文章:

【STM32 HAL库】IIC通信与CubeMX配置
【STM32 HAL库】IIC通信与CubeMX配置 前言理论IIC总线时序图IIC写数据IIC读数据 轮询模式CubeMX配置应用示例AHT20初始化初始化函数读取说明读取函数 中断模式CubeMX配置状态机图fsm.caht20.c DMA模式CubeMX配置代码 前言 本文为笔者学习 IIC 通信的总结,基于keysk…...

iPhone 上丢失了重要的联系人?如何恢复已删除的 iPhone 联系人
丢失 iPhone 上的联系人可能会带来灾难。无论是一份很棒的新工作机会、潜在的恋爱对象,还是您一直想打电话的老朋友,如果您打开“联系人”应用时看到空白,这绝不是好事。不过,一切并非全无,仍然可以通过备份或专业软件…...

【有啥问啥】弱监督学习新突破:格灵深瞳多标签聚类辨别(Multi-Label Clustering and Discrimination, MLCD)方法
弱监督学习新突破:格灵深瞳多标签聚类辨别(Multi-Label Clustering and Discrimination, MLCD)方法 引言 在视觉大模型领域,如何有效利用海量无标签图像数据是一个亟待解决的问题。传统的深度学习模型依赖大量人工标注数据&…...
[强化你的LangChain工具创建技能:从基础到进阶]
强化你的LangChain工具创建技能:从基础到进阶 在现代AI开发中,为语言模型和智能代理提供工具是提升其功能的关键一步。本指南将带你深入了解如何在LangChain中创建工具,从简单的函数到复杂的可配置工具。 引言 在构建智能代理时࿰…...

4.提升客户服务体验:ChatGPT在客服中的应用(4/10)
本文大纲旨在指导撰写一篇全面探讨ChatGPT如何通过优化客户服务流程、提供实际应用案例和用户反馈,以提升客户服务体验的深入博客文章。 引言 在当今竞争激烈的商业环境中,客户服务已成为企业成功的关键因素。优质的客户服务不仅能够增强客户满意度和忠…...
Gradio导入AIGC大模型创建web端智能体聊天机器人,python(2)
Gradio导入AIGC大模型创建web端智能体聊天机器人,python(2) 选用这个大模型: https://huggingface.co/HuggingFaceTB/SmolLM-1.7B-Instructhttps://huggingface.co/HuggingFaceTB/SmolLM-1.7B-Instruct原因是该模型相对比较小&am…...
PEM 格式
文章目录 1.简介2.格式和内容3.常见用途4.标准化5.示例参考文献 1.简介 .pem 文件扩展名代表“Privacy Enhanced Mail”,但它被用于比电子邮件更广泛的上下文中,主要关联于加密、SSL/TLS 和证书管理。PEM 格式是一种用于存储和发送加密信息的标准&#…...
Android前台服务如何在后台启动activity?
本来最近在开发一个app保活另外一个app的功能,方案介绍如下: 应用A 启动一个前台服务保活自己应用A 用grpc连接应用B(服务端)是否存活如果发现B不存活,则在服务中拉起B 这次没有做好调研,直接开始了开发工作,等grpc都…...
c#visionpro开发 方法统计
toolblock开发 vpp第二种简单加载方式 public Cognex.VisionPro.ToolBlock.CogToolBlock ToolBlock1;//初始化后实例化一个方法 //窗口运行程序内部 ToolBlock1 (CogToolBlock)CogSerializer.LoadObjectFromFile(“tjjc.vpp”); MessageBox.Show(“算法加载成功”);//复制一个…...

dedecms——四种webshell姿势
姿势一:通过文件管理器上传WebShell 步骤一:访问目标靶场其思路为 dedecms 后台可以直接上传任意文件,可以通过文件管理器上传php文件获取webshell 步骤二:登陆到后台点击【核心】--》 【文件式管理器】--》 【文件上传】将准备好…...
GO GIN 推荐的库
在使用 Go 和 Gin 框架进行 Web 开发时,有许多第三方库可以增强功能和提高开发效率。以下是一些常用的、与 Gin 搭配使用的库: 1. 数据处理与验证 go-playground/validator 用于结构体字段的验证,Gin 默认已经集成了它。它提供了丰富的验证…...

YOLOv9改进策略【卷积层】| GnConv:一种通过门控卷积和递归设计来实现高效、可扩展、平移等变的高阶空间交互操作
一、本文介绍 本文记录的是利用GnConv优化YOLOv9的目标检测方法研究。YOLOv9在进行目标检测时,需要对不同层次的特征进行融合。GnConv可以考虑更高阶的空间交互,能够更好地捕捉特征之间的复杂关系,从而增强特征融合的效果,提高模…...

如何在Linux下升级R版本和RStudio
一、升级R版本 在Linux上,R的安装通常通过包管理器完成。不同的Linux发行版(如Ubuntu、Debian、Fedora等)可能略有不同。下面以Ubuntu为例,介绍如何升级R版本。如果你使用其他发行版,步骤可能类似。 二.更新步骤 2.…...

npm安装时候报错certificate has expired
打开了一个很久没用的电脑,npm和node都装好了,安装包的时候一直报错 request to https://registry.npm.taobao.org/create-react-app failed, reason: certificate has expired而且先报错rollbackFailedOptional 然而npm没什么问题,是ssl过…...

CSP-J_S第一轮复习资料1·计算机硬件
下一章...
oracle 表的外键
表的外键 3.5.1表之间的三种关系 在数据库设计中,工作中经常会分析商业逻辑中的表的设计。在设计表的关系之前,需要先了解关系型数据库特点。关系数据库有如下特点: 关系型数据库采用了关系模型来组织数据的数据库。 关系型数据库的最大特点…...

加密与安全_优雅存储二要素(AES-256-GCM )
文章目录 什么是二要素如何保护二要素(姓名和身份证)加密算法分类场景选择算法选择AES - ECB 模式 (不推荐)AES - CBC 模式 (推荐)GCM(Galois/Counter Mode)AES-256-GCM简介AES-256-GCM工作原理安全优势 应用场景其他模式 和 敏感…...

【C++高阶】解锁C++的深层魅力——探索特殊类的奥秘
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:C 类型转换 🌹🌹期待您的关注 🌹🌹 ❀C特殊类 📒1. 不能被拷贝…...

Vue学习记录之三(ref全家桶)
ref、reactive是在 setup() 声明组件内部状态用的, 这些变量通常都要 return 出去,除了供 < template > 或渲染函数渲染视图,也可以作为 props 或 emit 参数 在组件间传递。它们的值变更可触发页面渲染。 ref :是一个函数&…...

第二十六篇——九地篇:九种形势的应对之道
目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 地势的维度重新阐述了懂得人心的重要性,道久其归一为为别人。…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...