STM32实现硬件IIC通信(HAL库)

文章目录

  • 一. 前言
  • 二. 关于IIC通信
  • 三. IIC通信过程
  • 四. STM32实现硬件IIC通信
  • 五. 关于硬件IIC的Bug

一. 前言

最近正在DIY一款智能电池,需要使用STM32F030F4P6和TI的电池管理芯片BQ40Z50进行SMBUS通信。SMBUS本质上就是IIC通信,项目用到STM32CubeMX+HAL库,使用硬件IIC完成MCU对芯片的寄存器数据的读取和改写。

整篇博客主要是梳理一下IIC的通信流程,并记录一下项目实现的过程,如有错的地方,欢迎各位读者批评指正。

二. 关于IIC通信

总线又两条信号线构成一条是数据线SDA ,用于数据传输。另一条则是时钟线SCL ,用于传输CLK信号,始终由主设备控制,主机(Master) 通过控制时钟信号可以实现对从机(Slave) 的控制与读写操作。各设备通过SDA、SCL接入总线,每个连接到IIC总线上的器件都有一个唯一的地址,如上图所示。

SDA和SCL需通过上拉电阻 接至VCC。由于连接到总线上的器件输出级必须是漏极开路或者集电极开路的,因此只要有一个器件任意时刻输出低电平,都将总线上的信号变低;当IIC总线空闲时,SDA和SCL两条线均为高电平,即各器件的SDA和SCL都是线与的关系。

三. IIC通信过程

IIC通信过程由一系列的操作组成:

  1. 起始信号 :通信开始时,主设备发送一个低电平的SCL时钟脉冲,然后再发送一个低电平的SDA数据线脉冲。这个SDA的下降沿表示I2C总线上的一个开始信号。

  2. 从设备地址 :主设备发送从设备地址到I2C总线。I2C地址由7Bit或10Bit组成,取决于使用的设备。

  3. 读/写位传输 :读写位占据 1bit 数据,指定了数据传输的方向:

    a. 主设备发送数据,从设备接受数据,为 0 
    b. 主设备接收数据,从设备发送数据,为 1 
    
  4. 仲裁机制和应答 :应答位由1个Bit的数据组成。主设备通过检测应答位,以确定从设备是否存在。若主设备收到的是NACK,这会让主设备发生重启或停止流程:

     a. 如果从设备存在并正确收到地址,从设备将SDA下拉,产生应答信号 0 (ACK)。
     b. 如果从设备不存在或未正确收到地址,导致SDA空闲,产生非应答信号1(NACK)。
    
  5. 数据传输 :在确认通信目标后,主设备将发送或接收数据。数据传输是在主机产生的每个时钟周期的上升沿或下降沿进行的。

    a. 主设备发送数据: 上图所示,主设备 将要发送的数据位(8位或更多)依次发送到SDA线上,并在每个时钟周期上升沿时更新数据。从设备在每个时钟周期下降沿时接收数据,并在接收之后发送应答位来确认是否接收正确。

    b. 主设备接收数据: 上图所示,当读/写传输位为1时,到了数据传输时,主机从发送变成接收,从机从接收变成发送。从设备 将要发送的数据位(8位或更多)依次发送到SDA线上,并在每个时钟周期上升沿时更新数据。主设备在每个CLK下降沿时接收数据,并在接收之后发送应答位来确认是否接收正确。

  6. 停止信号(Stop Signal) :通信完成后,主设备发送一个停止信号,由一个高电平的SCL时钟脉冲和一个高电平的SDA数据线脉冲组成。这个SDA的上升沿表示I2C总线上的一个停止信号。

四. STM32实现硬件IIC通信

本项目用的是STM32F030F4P6通过Smbus通信和TI的电池管理芯片BQ40Z50通信,读取电池内部的电压、电流及电量信息,并且通过改写电池内部寄存器控制输入输出的Mos管。Smbus本质上就是IIC通信,下面通过访问BQ40Z50内部的电压寄存器的例子来说明模拟IIC的实现过程:

STM32CubeMX配置如下:


1. 主设备: STM32F030F4P6
2. 从设备: BQ40Z50
3. 通信频率: 10-100KHz
4. 从设备地址: 0x16
5. 电压寄存器地址: 0x09

读取寄存器数据:

  1. 主机(STM32)首先产生Start信号。
  2. 然后紧跟着发送从机设备地址(0x16),此时读写位为0,表明是向从机写命令;
  3. 这时候主机等待从机(BQ40Z50)的应答信号(ACK)。
  4. 当主机收到应答信号时,发送要访问的寄存器地址(0x09),继续等待从机的应答信号;
  5. 当主机收到应答信号后,主机要改变通信模式,主机将由发送变为接收,从机将由接收变为发送。接着主机重新发送一个开始Start信号,然后紧跟着发送从机地址(0x16),注意此时读写位为1,表明将主机设置成接收模式开始读取数据。
  6. 这时候主机等待从机的应答信号,当主机收到应答信号时,就可以接收从机发送来的寄存器数据。
  7. 主机产生停止信号,结束传送过程。

虽然通信过程比较复杂,但是实现非常简单。因为大部分步骤HAL库已经封装好。直接调用现成的接口即可:

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
                                   uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
                                   /**
* @brief  Read an amount of data in blocking mode from a specific memory address
* @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
*                the configuration information for the specified I2C.
* @param  DevAddress Target device address: The device 7 bits address value
*         in datasheet must be shifted to the left before calling the interface
* @param  MemAddress Internal memory address
* @param  MemAddSize Size of internal memory address
* @param  pData Pointer to data buffer
* @param  Size Amount of data to be sent
* @param  Timeout Timeout duration
* @retval HAL status
*/

比如,读取BQ40Z50的电压:

Uint8_t Rxbuffer[2];//用于接受数据的数组
			 
HAL_I2C_Mem_Read(hi2cx,0x16,0x09,I2C_MEMADD_SIZE_8BIT,Rxbuffer,2,OxFF);//IIC接受从机数据

voltage = Rxbuffer[1]<<8|Rxbuffer[0];//对接受数据进行解析

同样的,写入寄存器数据:

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
                                    uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
/**
  * @brief  Write an amount of data in blocking mode to a specific memory address
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address value
  *         in datasheet must be shifted to the left before calling the interface
  * @param  MemAddress Internal memory address
  * @param  MemAddSize Size of internal memory address
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */

比如:向0x00写入0x270C和0x430D可以关闭BQ40Z50的Mos管:

uint8_t Mos_off [2];
Mos_off [0] = 0x0C;
Mos_off [1] = 0x27;
if(HAL_I2C_Mem_Write(hi2cx,0x16,0x00,I2C_MEMADD_SIZE_8BIT,Mos_off ,2,0xFF)==HAL_OK)
{
	Mos_off [0] = 0x3D;
	Mos_off [1] = 0x04;
	HAL_I2C_Mem_Write(hi2cx,0x16,0x00,I2C_MEMADD_SIZE_8BIT,Mos_off ,2,0xFF);
}

五. 关于硬件IIC的Bug

在开发过程中,IIC经常会遇到很多莫名其妙的Bug,比如反复超时,陷入I2C_WaitOnFlagUntilTimeout()死循环中,或者是一直处于HAL_I2C_STATE_BUSY_RX直接卡死,看了网络上很多的帖子,但是都没有找到好的解决办法。

这里的解决方式非常简单粗暴,就在卡死的地方直接对硬件IIC进行重置,重新初始化,亲测有效。

各位有什么更好的方法,欢迎在评论区留言,一起探讨。

void User_I2C_ErrorInit(I2C_HandleTypeDef *hi2c)
{
	HAL_I2C_DeInit(hi2c);
	
	hi2c->Instance = I2C1;
	hi2c->Init.Timing = 0x2000090E;
	hi2c->Init.OwnAddress1 = 0;
	hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
	hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
	hi2c->Init.OwnAddress2 = 0;
	hi2c->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
	hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
	hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

    hi2c->Instance->CR1 |= I2C_CR1_SWRST;
    hi2c->Instance->CR1 &= ~I2C_CR1_SWRST;

	if (HAL_I2C_Init(hi2c) != HAL_OK)
	{
		User_Error_Handler();
	}

	/** Configure Analogue filter
	*/
	if (HAL_I2CEx_ConfigAnalogFilter(hi2c, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
	{
		User_Error_Handler();
	}

	/** Configure Digital filter
	*/
	if (HAL_I2CEx_ConfigDigitalFilter(hi2c, 0) != HAL_OK)
	{
		User_Error_Handler();
	}
}

static void User_Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

各位有什么更好的方法,欢迎在评论区留言,一起探讨。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于ROS的智能网联车远程交互软件,全UI无需记忆指令,剑指核心原理。

基于ROS的智能网联车远程交互软件&#xff0c;全UI无需记忆指令&#xff0c;剑指核心原理。 服务于中汽恒泰&#xff0c;伟大的项目&#xff0c;希望看官点赞&#xff0c;谢谢~~ 进程&#xff08;节点&#xff09;列表化&#xff0c;参数面板化&#xff0c;实现快速机器人配置…

SpringMVC(2)——controller方法参数与html表单对应

controller方法参数与html表单对应 0. User实体类 import org.springframework.format.annotation.DateTimeFormat;import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Map;public class User implements Serializable {private …

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日&#xff0c;阿里通义实验室发布开源语音大模型项目FunAudioLLM&#xff0c;而且一次包含两个模型&#xff1a;SenseVoice和CosyVoice。 CosyVoice专注自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;支持中英日粤韩5种语言的生成&#xff0c;效果显著优于…

apk反编译修改教程系列-----修改apk 解除软件限制功能 实例操作步骤解析_3【二十二】

在前面的几期博文中有过解析去除apk中功能权限的反编译步骤。另外在以往博文中也列举了修改apk中选项功能权限的操作方法。今天以另外一款apk作为演示修改反编译去除软件功能限制的步骤。兴趣的友友可以参考其中的修改过程。 课程的目的是了解apk中各个文件的具体作用以及简单…

JavaWeb—Servlet

概述 Javaweb的核心就是围绕servlet Servlet就是一个接口&#xff0c; 定义了java类 被浏览器访问到&#xff08;tomcat识别&#xff09;的接口 将来就是自己写一个类 &#xff0c;实现servlet接口 &#xff0c;重写方法 执行过程 当服务器接收到客户端浏览器的请求后&#xff…

【机器学习】机器学习与时间序列分析的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在时间序列分析中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 数据增强 1.2 模型选择1.2.1 自回归模型1.2.2 移动平均模型1.2.3 长短期记忆网络1.2.4 卷积神经网络 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 A…

C# 编程中互斥锁的使用

C# 中的互斥锁 互斥锁是 C# 中使用的同步原语&#xff0c;用于控制多个线程或进程对共享资源的访问。其目的是确保在任何给定时间只有一个线程或进程可以获取互斥锁&#xff0c;从而提供互斥。 C# 中互斥锁的优点 可以使用互斥锁 (Mutex) 并享受其带来的好处。 1. 共享资源…

一篇就够了,为你答疑解惑:锂电池一阶模型-在线参数辨识(附代码)

锂电池一阶模型-在线参数辨识 背景在线 VS 离线 参数辨识递推最小二乘法一阶戴维南Z域离散表达式 背景 锂电池一阶戴维南等效模型的基础知识和离线辨识方法&#xff0c;已经在上一期非常详细地讲解了一轮&#xff08;上期文章请戳此处&#xff09;&#xff0c;本期继续讲解一下…

秋招提前批面试经验分享(上)

⭐️感谢点开文章&#x1f44b;&#xff0c;欢迎来到我的微信公众号&#xff01;我是恒心&#x1f60a; 一位热爱技术分享的博主。如果觉得本文能帮到您&#xff0c;劳烦点个赞、在看支持一下哈&#x1f44d;&#xff01; ⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读…

vue3中使用EasyPlayer播放h265视频流

1、下载EasyPlayer 5.0.3版本 在package.json中加入EasyPlayer&#xff0c;并全局install下 "dependencies": {"easydarwin/easyplayer": "^5.0.3" }2、找到node_modules中的EasyPlayer.wasm和EasyPlayer-element.min.js 3、复制到public下面&…

多元微分学中可微、连续、存在问题

一、偏导存在 与一元证明相同&#xff0c;利用偏导定义式&#xff0c;证明偏导数左右极限存在且相同。 二、偏导连续 与一元证明相同&#xff0c;证明 三、极限存在 1、找一条路径&#xff0c;一般地找 y kx 2、代入f(x,y)&#xff0c;得f(x,kx) 3、证明f(x,kx)极限存在 注意&…

基于java语言+ Vue+ElementUI+ MySQL8.0.36数字化产科管理平台源码,妇幼信息化整体解决方案

基于java语言 VueElementUI MySQL8.0.36数字化产科管理平台源码&#xff0c;妇幼信息化整体解决方案 数字化产科管理平台是为医院产科量身定制的信息管理系统。它管理了孕妇从怀孕开始到生产结束42天一系列医院保健服务信息。该系统由门诊系统、住院系统、数据统计模块三部分组…

昇思25天学习打卡营第14天|Pix2Pix实现图像转换

Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到真实图片、灰度图到彩色图、航空图到…

MSPM0G3507——滴答定时器和普通定时

滴答定时器定时&#xff1a;&#xff08;放在主函数即可&#xff09; volatile unsigned int delay_times 0;//搭配滴答定时器实现的精确ms延时 void delay_ms(unsigned int ms) {delay_times ms;while( delay_times ! 0 ); } //滴答定时器中断 void SysTick_Handler(…

桌面快充插线板+伸缩数据线,轻松实现1+1>2

手机、平板、笔记本等电子设备已成为我们日常工作和学习的必备工具。然而,随着设备数量的增加,充电问题也日益凸显。桌面空间有限,多个快充头不仅显得杂乱无章,而且效率低下,无法满足我们高效办公的需求。 在这样的背景下,倍思Nomos氮化镓100W桌面充电站凭借其创新的设计和强大…

下载,连接mysql数据库驱动(最详细)

前言 本篇博客&#xff0c;我讲讲如何连接数据库&#xff1f;我使用mysql数据库举例。 目录 下载对应的数据库jar 包 百度网盘 存有8.4.0版本压缩包&#xff1a;链接&#xff1a;https://pan.baidu.com/s/13uZtXRmuewHRbXaaCU0Xsw?pwduipy 提取码&#xff1a;uipy 复制这…

Day05-04-持续集成总结

Day05-04-持续集成总结 1. 持续集成2. 代码上线目标项目 1. 持续集成 git 基本使用, 拉取代码,上传代码,分支操作,tag标签 gitlab 用户 用户组 项目 , 备份,https,优化. jenkins 工具平台,运维核心, 自由风格工程,maven风格项目,流水线项目, 流水线(pipeline) mavenpom.xmlta…

基于SpringBoot的时间管理系统

你好&#xff0c;我是专注于时间管理的技术爱好者&#xff01;如果你对时间管理有独到的见解&#xff0c;欢迎私信交流。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;Eclipse、MySQL数据库管理工具 系统展示 首页…

【C语言】 —— 编译和链接

【C语言】 —— 编译和链接 一、编译环境和运行环境二、翻译环境2.1、 预处理2.2、 编译&#xff08;1&#xff09;词法分析&#xff08;2&#xff09;语法分析&#xff08;3&#xff09;语义分析 2.3、 汇编2.4、链接 三、运行环境 一、编译环境和运行环境 平时我们说写 C语言…

区块链论文速读A会-ISSTA 2023(2/2)如何检测DeFi协议中的价格操纵漏洞

Conference&#xff1a;ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2023 第1~5篇区块链文章 请点击此…