【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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何进行数字化基础设施的构建呢?

数字化基础设施的构建是一个复杂而系统的过程&#xff0c;它涉及多个方面和层次的建设。以下是一个详细的构建步骤和关键点&#xff1a; 一、明确建设目标和需求 战略规划&#xff1a;结合企业的长期发展目标&#xff0c;明确数字化基础设施建设的总体方向和具体目标。需求分析…

LabVIEW中AVI帧转图像数据

在LabVIEW中&#xff0c;有时需要将AVI视频文件的帧转换为图像数据进行进一步处理。下面详细讲解了如何从AVI视频提取单帧并将其转换为图像数据集群&#xff0c;以便与其他图像处理VI兼容。 问题背景&#xff1a; 用户已经拥有能够处理JPEG图像数据集群的VI&#xff0c;现在希…

房产销售系统:SpringBoot技术应用案例

第二章关键技术的研究 2.1相关技术 房产销售系统是在Java MySQL开发环境的基础上开发的。Java是一种服务器端脚本语言&#xff0c;易于学习&#xff0c;实用且面向用户。全球超过35&#xff05;的Java驱动的互联网站点使用Java。MySQL是一个数据库管理系统&#xff0c;因为它的…

学习大数据DAY58 增量抽取数据表

作业 1 SQL 优化的常见写法有哪些 - 面试经常被问 使用索引&#xff1a;合理创建和使用索引是提高查询效率的关键。索引可以加速数据的检 索速度&#xff0c;但是索引也会占用额外的存储空间&#xff0c;并且在插入、删除和更新操作时会 有额外的开销。 避免全表扫描&…

线段树介绍及线段树的使用场景

1.线段树用来解决什么问题 假如说你有一个数组&#xff0c;数组下标为 0-1000&#xff0c;然后对外提供一些方法&#xff0c; 1.1比如说你对外提供add方法&#xff0c;add方法&#xff08;1,200,6&#xff09;&#xff0c;请你把从1 到 200 位置所有的值 加上6 1.2更新&…

Qt与MQTT交互通信

MQTT全称是&#xff08;Message Queuing Telemetry Transport&#xff09;&#xff0c;即消息队列遥测传输协议 是一种基于发布/订阅&#xff08;Publish/Subscribe&#xff09;模式的轻量级通讯协议&#xff0c;并且该协议构建于TCP/IP协议之上&#xff0c;常用于互联网中&am…

Zabbix自定义监控项与触发器

当我们需要获取某台主机上的数据时&#xff0c;直接利用 zabbix 提供的模板可以很方便的获得需要的数据,但是有些特别的数据&#xff0c;利用这些现有的模板或监控项是无法实现的&#xff0c;例如网站状态信息的监控、mysql数据库主从状态等信息。这是就需要自己定义键值和监控…

【Unity】在Unity 3D中使用Spine开发2D动画

文章目录 内容概括前言下载安装 Spine Pro导入Unity插件Spine动画导入Unity使用展现动画效果展现 内容概括 本文主要讲解 Spine Pro 免&#xff08;破&#xff09;费&#xff08;解&#xff09;版的安装&#xff0c;以及如何将动画导入到Unity中使用。 前言 通常要用 Spine …

基于鸿蒙API10的RTSP播放器(七:亮度调节功能测试)

目标&#xff1a; 当我的手指在设备左方进行上下移动的时候&#xff0c;可以进行屏幕亮度的调节&#xff0c;在调节的同时&#xff0c;有实时的调节进度条显示 步骤&#xff1a; 界面逻辑&#xff1a;使用Stack() 组件&#xff0c;完成音量图标和进度条的组合显示&#xff0c…

Unity 粒子系统参数说明

一、Particle System 1. Duration&#xff08;持续时间&#xff09; 粒子系统运行一次所需的时间。它决定粒子系统持续播放的时间长度。 2. Looping&#xff08;循环播放&#xff09; 如果启用&#xff0c;粒子系统将在播放完一次后自动重新开始播放&#xff0c;直到你停止它…

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…

javase复习day22泛型、set、数据结构

泛型 package MyGenerics;import java.util.ArrayList; import java.util.Iterator;public class GenericsTest1 {public static void main(String[] args) {//没有泛型的情况ArrayList list new ArrayList();//所有数据都被认为是Object类型&#xff0c;都可以加入集合中list…

记录开发一个英语听力训练网站

背景 在当前全球经济衰退的背景下&#xff0c;IT相关的工作在国内的竞争也是越来越激烈&#xff0c;为了能够获得更多的可能性&#xff0c;英语的学习也许能为程序员打开一扇新的窗户&#xff0c;比如很多远程的工作尤其是国际化背景的工作团队&#xff0c;英语的协作沟通是必…

uniapp 发布苹果IOS详细流程,包括苹果开发者公司账号申请、IOS证书、.p12证书文件等

记录一下uniapp发布苹果IOS的流程。 一、苹果开发者公司账号申请 1、邓白氏编码申请&#xff08;先申请公司邓白氏编码&#xff0c;这一步需要1-2周&#xff0c;没有这个编码苹果开发者没法申请&#xff0c;已有编码的跳过此步骤&#xff09;&#xff1a; 1&#xff09;联系苹…

[机器学习]决策树

1 决策树简介 2 信息熵 3 ID3决策树 3.1 决策树构建流程 3.2 决策树案例 4 C4.5决策树 5 CART决策树&#xff08;分类&回归&#xff09; 6 泰坦尼克号生存预测案例 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import …

链表的快速排序(C/C++实现)

一、前言 大家在做需要排名的项目的时候&#xff0c;需要把各种数据从高到低排序。如果用的快速排序的话&#xff0c;处理数组是十分简单的。因为数组的存储空间的连续的&#xff0c;可以通过下标就可以简单的实现。但如果是链表的话&#xff0c;内存地址是随机分配的&#xf…

【H2O2|全栈】关于CSS(2)CSS基础(二)

目录 CSS基础知识 前言 准备工作 选择器的组合 盒模型 示例网页代码 后代选择器 亲代选择器 相邻兄弟选择器 后续兄弟选择器 多个元素选择器 通配符选择器 优先级 其他应用 伪类 锚链接的属性 列表的属性 list-style-type list-style-position list-style…

react 事件处理

概述 Web应用中&#xff0c;事件处理是重要的一环&#xff0c;事件处理将用户的操作行为转换为相应的逻辑执行或界面更新。在React中&#xff0c;处理事件响应的方式有多种&#xff0c;本文将详细介绍每一种处理方式的用法、使用场景和优缺点。 如果原生DOM有一个监听事件&…

QGis二次开发 —— 3、程序加载栅格tif与矢量shp文件可进行切换控制,可进行导出/导入工程(附源码)

效果 功能说明 软件可同时加载.tif栅格图片与.shp矢量图片、加载图片后可进行自由切换查看图层、可对加载的图片进行关闭 关闭后清空图层、可对加载的图片进行导出.qgs的QGIS工程、可对.qgs的QGis工程导入并导入后可进行自由切换查看图层。 源码 注意: 在加载tif栅格文件后会在…

el-table 如何实现行列转置?

在某些需求里需要用到 行列转置 的表格&#xff0c;但 el-table 提供的基本表格是不支持行列转置的&#xff0c;这样就需要对这个表格进行二次开发。下面来看具体实现的效果&#xff1a; 具体实现方式 基本原理就是对原有的可渲染的数据结构进行处理&#xff0c;表头与表格数…