STM32设置为I2C从机模式(HAL库版本)
STM32设置为I2C从机模式(HAL库版本)
目录
- STM32设置为I2C从机模式(HAL库版本)
- 前言
- 1 硬件连接
- 2 软件编程
- 2.1 步骤分解
- 2.2 测试用例
- 3 运行测试
- 3.1 I2C连续写入
- 3.2 I2C连续读取
- 3.3 I2C单次读写测试
- 4 总结
前言
我之前出过一篇关于STM32设置为I2C从机的博客,现在应粉丝要求,出一篇HAL库版本的I2C从机编程。
基于官方库版本的可以看下我之前发的文章:STM32设置为I2C从机模式
1 硬件连接
测试芯片:STM32F103RCT6
测试方法:用一个USB转I2C的工具接到STM32的I2C引脚上,通过上位机工具进行读写操作。如果没有这个工具,也可以用另外一组I2C作为主机或者其他设备测试通讯,同时也可以借助示波器或者逻辑分析仪来辅助调试。
硬件连接:
STM32这边使用硬件I2C1(PB6、PB7),并外接上拉电阻。


本次测试中使用的USB转I2C的工具如下图所示:

2 软件编程
2.1 步骤分解
1、初始化I2C配置
注:除了最后的HAL_I2C_EnableListen_IT()函数,其他代码都可以用STM32CubeMX自动生成
参考代码:
static void MX_I2C1_Init(void)
{hi2c1.Instance = I2C1; // 配置I2C1 hi2c1.Init.ClockSpeed = 100000; // 时钟频率:100k hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 占空比:1/2 hi2c1.Init.OwnAddress1 = 0x80; // 本机地址:0x80(若作为从设备则是从机地址) 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) // I2C1初始化 { Error_Handler(); } HAL_I2C_EnableListen_IT(&hi2c1); // 使能I2C1的侦听中断
}
2、初始化I2C引脚和中断
参考代码:
注:这个代码可以用STM32CubeMX自动生成
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(hi2c->Instance==I2C1){// 配置GPIO__HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// 配置I2C中断/* Peripheral clock enable */__HAL_RCC_I2C1_CLK_ENABLE();/* I2C1 interrupt Init */HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0); // 事件中断(必须有)HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0); // 错误中断(非必须)HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);}
}
3、配置I2C中断服务函数
参考代码:
注:这个代码可以用STM32CubeMX自动生成
// I2C1事件中断服务函数(必须有)
void I2C1_EV_IRQHandler(void)
{HAL_I2C_EV_IRQHandler(&hi2c1);
}// I2C1错误中断服务函数(非必须)
void I2C1_ER_IRQHandler(void)
{HAL_I2C_ER_IRQHandler(&hi2c1);
}
4、配置I2C从机回调处理函数
参考代码:
static uint8_t ram[256]; // 模拟I2C从机数据寄存器(主机读写的数据都放在这块内存)
uint8_t offset; // 从机寄存器当前偏移地址
static uint8_t first_byte_state = 1; // 是否收到第1个字节,也就是偏移地址(0:已收到,1:没有收到)// 侦听完成回调函数(完成一次完整的i2c通信以后会进入该函数)
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{// 完成一次通信,清除状态first_byte_state = 1;offset = 0;HAL_I2C_EnableListen_IT(hi2c); // slave is ready again
}// I2C设备地址回调函数(地址匹配上以后会进入该函数)
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{if(TransferDirection == I2C_DIRECTION_TRANSMIT) {// 主机发送,从机接收if(first_byte_state) {// 准备接收第1个字节数据HAL_I2C_Slave_Seq_Receive_IT(hi2c, &offset, 1, I2C_NEXT_FRAME); // 每次第1个数据均为偏移地址} } else {// 主机接收,从机发送HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME); // 打开中断并把ram[]里面对应的数据发送给主机}
}// I2C数据接收回调函数(在I2C完成一次接收时会关闭中断并调用该函数,因此在处理完成后需要手动重新打开中断)
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{if(first_byte_state) {// 收到的第1个字节数据(偏移地址)first_byte_state = 0;} else {// 收到的第N个字节数据offset++; // 每收到一个数据,偏移+1}// 打开I2C中断接收,下一个收到的数据将存放到ram[offset]HAL_I2C_Slave_Seq_Receive_IT(hi2c, &ram[offset], sizeof(ram), I2C_NEXT_FRAME); // 接收数据存到ram[]里面对应的位置
}// I2C数据发送回调函数(在I2C完成一次发送后会关闭中断并调用该函数,因此在处理完成后需要手动重新打开中断)
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{offset++; // 每发送一个数据,偏移+1HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], sizeof(ram), I2C_NEXT_FRAME); // 打开中断并把ram[]里面对应的数据发送给主机
}
2.2 测试用例
1、测试方法
使用USB转I2C的工具接入到MCU的I2C上面,然后使用上位机工具进行读写操作,最后通过串口把I2C通讯过程中的几个重要节点打印出来,验证结果是否正确。
2、测试程序
其实和上面讲解的代码是一样的,只是初始化时先把ram[]赋初值。
参考测试代码:
#include "stm32f1xx_hal.h"static uint8_t ram[256]; // 模拟I2C从机数据寄存器(主机读写的数据都放在这块内存)
uint8_t offset; // 从机寄存器当前偏移地址
static uint8_t first_byte_state = 1; // 是否收到第1个字节,也就是偏移地址(0:已收到,1:没有收到)// 侦听完成回调函数(完成一次完整的i2c通信以后会进入该函数)
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{// 完成一次通信,清除状态first_byte_state = 1;offset = 0;HAL_I2C_EnableListen_IT(hi2c); // slave is ready again
}// I2C设备地址回调函数(地址匹配上以后会进入该函数)
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{if(TransferDirection == I2C_DIRECTION_TRANSMIT) {// 主机发送,从机接收if(first_byte_state) {// 准备接收第1个字节数据HAL_I2C_Slave_Seq_Receive_IT(hi2c, &offset, 1, I2C_NEXT_FRAME); // 每次第1个数据均为偏移地址} } else {// 主机接收,从机发送HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME); // 打开中断并把ram[]里面对应的数据发送给主机}
}// I2C数据接收回调函数(在I2C完成一次接收时会关闭中断并调用该函数,因此在处理完成后需要手动重新打开中断)
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{if(first_byte_state) {// 收到的第1个字节数据(偏移地址)first_byte_state = 0;} else {// 收到的第N个字节数据offset++; // 每收到一个数据,偏移+1}// 打开I2C中断接收,下一个收到的数据将存放到ram[offset]HAL_I2C_Slave_Seq_Receive_IT(hi2c, &ram[offset], sizeof(ram), I2C_NEXT_FRAME); // 接收数据存到ram[]里面对应的位置
}// I2C数据发送回调函数(在I2C完成一次发送后会关闭中断并调用该函数,因此在处理完成后需要手动重新打开中断)
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{offset++; // 每发送一个数据,偏移+1HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], sizeof(ram), I2C_NEXT_FRAME); // 打开中断并把ram[]里面对应的数据发送给主机
}// 测试用例:初始化把ram设置为从0到255的数
void i2c_test(void)
{for (uint16_t i = 0; i < 256; i++){ram[i] = i;}
}
3 运行测试
3.1 I2C连续写入
通过上位机工具写入:

通过逻辑分析仪抓取波形:

3.2 I2C连续读取
通过上位机工具连续读取256字节:

通过逻辑分析仪抓取波形:


3.3 I2C单次读写测试
通过上位机工具读取原值,再写入新值,最后再读取新值:

通过逻辑分析仪抓取波形:

4 总结
通过上位机工具的测试以及逻辑分析仪的解析,STM32的硬件I2C从机通信正常且稳定,读写速度测试了100k和400k,没有发现问题,至此测试完成。
好了,关于STM32如何设置从机模式就介绍到这里,如果你们有什么问题,欢迎评论区留言。
需要完整源码工程的同学可以自行下载:源码下载地址
如果这篇文章能够帮到你,就…懂的。

相关文章:
STM32设置为I2C从机模式(HAL库版本)
STM32设置为I2C从机模式(HAL库版本) 目录 STM32设置为I2C从机模式(HAL库版本)前言1 硬件连接2 软件编程2.1 步骤分解2.2 测试用例 3 运行测试3.1 I2C连续写入3.2 I2C连续读取3.3 I2C单次读写测试 4 总结 前言 我之前出过一篇关于…...
牛客网Verilog刷题 | 入门特别版本
文章目录 1、 VL1 输出12、VL2 wire连线3、 VL3 多wire连接4、VL4 反相器5、VL5 与门6、VL6 NOR 门7、VL7 XOR 门8、VL8 逻辑运算10、VL10 逻辑运算211、VL11 多位信号12、VL12 信号顺序调整13、VL13 位运算与逻辑运算14、VL14 对信号按位操作15、VL15 信号级联合并16、VL16 信…...
ROS通信机制之话题(Topics)的发布与订阅以及自定义消息的实现
我们知道在ROS中,由很多互不相干的节点组成了一个复杂的系统,单个的节点看起来是没起什么作用,但是节点之间进行了通信之后,相互之间能够交互信息和数据的时候,就变得很有意思了。 节点之间进行通信的一个常用方法就是…...
容灾设备系统组成,容灾备份系统组成包括哪些
随着信息技术的快速发展,企业对数据的需求越来越大,数据已经成为企业的核心财产。但是,数据安全性和完整性面临巨大挑战。在这种环境下,容灾备份系统应运而生,成为保证企业数据安全的关键因素。下面我们就详细介绍容灾…...
腾讯云服务器租用价格表_一年、1个月和1小时报价明细
腾讯云服务器租用费用表:轻量应用服务器2核2G4M带宽112元一年,540元三年、2核4G5M带宽218元一年,2核4G5M带宽756元三年、云服务器CVM S5实例2核2G配置280.8元一年、GPU服务器GN10Xp实例145元7天,腾讯云服务器网长期更新腾讯云轻量…...
【java安全】JNDI注入概述
文章目录 【java安全】JNDI注入概述什么是JNDI?JDNI的结构InitialContext - 上下文Reference - 引用 JNDI注入JNDI & RMI利用版本:JNDI注入使用Reference 【java安全】JNDI注入概述 什么是JNDI? JNDI(Java Naming and Directory Interf…...
零基础如何使用IDEA启动前后端分离中的前端项目(Vue)?
一、在IDEA中配置vue插件 点击File-->Settings-->Plugins-->搜索vue.js插件进行安装,下面的图中我已经安装好了 二、搭建node.js环境 安装node.js 可以去官网下载:安装过程就很简单,直接下一步就行 测试是否安装成功:要…...
laravel实现AMQP(rabbitmq)生产者以及消费者
基于php-amqplib/php-amqplib组件适配laravel框架的amqp封装库 支持便捷可配置的队列工作模式 官网详情 在此基础上可支持延迟消息、死信队列等机制。 环境要求: PHP版本: ^7.3|^8.0 需要开启的扩展: socket 其他: 如果需要实现延迟任务需要安装对应版本的ra…...
LeetCode——二叉树篇(九)
刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 目录 669. 修剪二叉搜索树 108. 将有序数组转换为二叉搜索树 538. 把二叉搜索树转换为累加树 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root ,同时给定最小边界…...
uniapp scroll-view横向滚动无效,scroll-view子元素flex布局不生效
要素排查: 1.scroll-x属性需要开启,官方类型是Boolean,实际字符串也行。 2scroll-view标签需要给予一个固定宽度,可以是百分百也可以是固定宽度或者100vw。 3.子元素需要设置display: inline-block(行内块元素&#x…...
无涯教程-进程 - 简介
进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。另外,系统空间是“公共场所”,各进…...
HTML番外篇(四)-HTML5新增元素-CSS常见函数-理解浏览器前缀-BFC
一、HTML5新增元素 1.HTML5语义化元素 在HMTL5之前,我们的网站分布层级通常包括哪些部分呢? header、nav、main、footer ◼ 但是这样做有一个弊端: 我们往往过多的使用div, 通过id或class来区分元素;对于浏览器来说这些元素不…...
机器学习之Adam(Adaptive Moment Estimation)自适应学习率
Adam(Adaptive Moment Estimation)是一种常用的优化算法,特别适用于训练神经网络和深度学习模型。它是一种自适应学习率的优化算法,可以根据不同参数的梯度信息来动态调整学习率,以提高训练的效率和稳定性。 Adam算法…...
深入理解Linux权限管理:保护系统安全的重要措施
Linux操作系统以其稳定性、可靠性和灵活性而受到广泛使用。其中一个关键特性是其强大的权限管理系统,它可以保护系统资源和用户数据的安全性。本文将深入探讨Linux权限管理的概念、原则和实践,帮助您理解如何正确配置和管理权限,以确保系统的…...
kafka复习:(20):消费者拦截器的使用
一、定义消费者拦截器(只消费含"sister"的消息) package com.cisdi.dsp.modules.metaAnalysis.rest;import org.apache.kafka.clients.consumer.ConsumerInterceptor; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.…...
水库大坝安全监测的主要内容包括哪些?
在水库大坝的实时监测中,主要任务是通过无线传感网络监测各个监测点的水位、水压、渗流、流量、扬压力等数据,并在计算机上用数据模式或图形模式进行实时反映,以掌握整个水库大坝的各项变化情况。大坝安全监测系统能实现全天候远程自动监测&a…...
Cadence软件屏幕显示问题
问题 就是今天打开Cadence软件想导出网表看一下,发现没有显示确定按钮什么的,那个窗口也是无语,不能移动,缩放也只能左右缩放,还不能缩小什么的,真的醉了,后面就是调整窗口的分辨率。 因为我最…...
访问服务器快慢的因素
我们在租用服务器的过程中,可能在访问速度方面,会受到某些因素影响,如果您要进行此项业务,进行一些简单的了解 是非常的有必要的,下面壹基比小鑫带大家一起去做个具体的探讨吧。 对于服务器不太了解的都认为࿰…...
vue(element ui安装)
目录 一,element ui安装二,main.js三,使用element ui最后 一,element ui安装 先在盘服中找到你创建的node的位置 如有不懂根据可以看看上一章安装node 然后在终端找到 进入这个位置之后就可以安装了 输入npm i element-ui -S这个…...
基于FPGA视频接口之HDMI2.0编/解码
简介 为什么要特别说明HDMI的版本,是因为HDMI的版本众多,代表的HDMI速度同样不同,当前版本在HDMI2.1速度达到48Gbps,可以传输4K及以上图像,但我们当前还停留在1080P@60部分,且使用的芯片和硬件结构有很大差别,故将HDMI分为两个部分说明1080@60以下分辨率和4K以上分辨率(…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
