细说STM32F407单片机IIC总线基础知识

目录

一、 I2C总线结构

1、I2C总线的特点

2、I2C总线通信协议

3、 STM32F407的I2C接口

二、 I2C的HAL驱动程序

1、 I2C接口的初始化

2、阻塞式数据传输

(1)函数HAL_I2C_IsDeviceReady()

(2)主设备发送和接收数据

(3)从设备发送和接收数据

(4)I2C存储器数据传输

3、中断方式数据传输

4、 DMA方式数据传输

5、其它


        I2C(Inter-Integrated Circuit)接口,有时也写作IIC或I²C接口,是一种串行数字总线接口。I2C接口只有2根信号线,总线上可以连接多个设备,硬件实现简单,可扩展性强。I2C接口主要用于通信速率要求不高,以及多个器件之通信的应用场景。

        本文使用的开发板:旺宝红龙STM32F407ZGT6 KIT V1.0。

一、 I2C总线结构

        一个器件的I2C接口只有2根信号线,即双向串行数据线SDA和时钟信号线SCL。I2C是种多设备总线,一根I2C总线上可以挂载多个设备。

 

1、I2C总线的特点

  • I2C总线只有两根信号线,SDA是双向串行数据线,SCL是时钟信号线,用于数据收发的同步。
  • I2C总线上可以挂载多个设备,一般有一个主设备、多个从设备。MCU一般作为主设备,外围器件作为从设备。在I2C通信协议中,主动发起通信的器件就是主设备,被动进行响应的器件就是从设备。
  • I2C总线上每个器件有一个7位或10位的地址,主设备发起通信时,会首先发送目标设备地址,只有地址对应的从设备才会做出响应。
  • I2C总线的两根信号线有上拉电阻。当I2C器件空闲时,其输出接口是高阻态。当所有设备都空闲时,I2C总线上是高电平
  • I2C通信有标准模式和快速模式,标准模式传输速率为100kbit/s,快速模式传输速率为400kbit/s。

2、I2C总线通信协议

        I2C通信总是由主机启动,每个通信过程由起始信号开始,由停止信号结束。一个数据包有8位,每个数据包后有一个应答位(ACK)或非应答位(NACK)。例如,主设备向从设备发送1字节数据的时序图:

 

  • 起始位:当SCL是高电平时,SDA的下跳沿就是起始位,是启动一次I2C通信的起始信号。
  • 停止位:当SCL为高电平时,SDA的上跳沿就是停止位,是停止一次I2C通信的结束信号。
  • 数据位:在SCL的一个时钟周期内传输一个数据位,当SCL为低电平时,发送设备更新SDA的电平,当SCL为高电平时,接收设备读取SDA的电平就是有效的一位数据
  • 数据包:I2C数据通信一个数据包总是8位,也就是1字节的数据。
  • 应答信号:在发送完8位数据包后,发送设备在第9个SCL时钟周期采集接收设备的应答信号。若在SCL的第9个周期采集的SDA为低电平,就是应答信号ACK,如果采集的SDA是高电平,就是非应答信号NACK。

        在一次I2C通信过程中,可以传输多字节的数据。主机启动I2C通信后,发送的第一个字节是目标设备地址,后面再发送或接收的数据由具体器件的指令定义决定。I2C通信协议只是定义了基本的数据传输时序,并且通信时序由MCU的硬件I2C接口实现。

3、 STM32F407的I2C接口

        STM32F407芯片上有3个硬件I2C接口,记作I2C1、I2C2和I2C3,均支持I2C标准模式和I2C快速模式,还与系统管理总线(System Management Bus,SMBus)2.0兼容。STM32F407上的I2C接口具有如下特性。

  • 同一个I2C接口既可以工作于主模式,又可以工作于从模式。
  • 工作于从模式时,可以设置两个从设备地址,从而对两个从地址应答。
  • 使用7位或10位设备地址,还可以进行广播呼叫。
  • 支持不同的通信速度:标准模式传输速率为100kbit/s,快速模式传输速率为400kbit/s。
  • 带DMA功能的1字节缓存。

二、 I2C的HAL驱动程序

        I2C的HAL驱动程序头文件是stm32f4xx_hal_i2c.h和stm32f4xx_hal_i2c_ex.h。I2C的HAL驱动程序包括宏定义、结构体定义、宏函数和功能函数。I2C的数据传输有阻塞式、中断方式和DMA方式 

1、 I2C接口的初始化

        对I2C接口进行初始化配置的函数是HAL_I2C_Init(),其函数原型定义如下:

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)

     其中,hi2c是I2C接口的对象指针,是I2C_HandleTypeDef结构体类型指针。在STM32CubeIDE自动生成的文件i2c.c中,会为启用的I2C接口定义外设对象变量,例如,为I2C1接口定义的变量如下:

I2C_HandleTypeDef hi2c1; //I2C1接口的外设对象变量

        结构体I2C_HandleTypeDef的成员变量主要是HAL程序内部用到的一些定义,只有成员变量Init是需要用户配置的I2C通信参数,是I2C_InitTypeDef结构体类型。

2、阻塞式数据传输

        阻塞式数据传输使用方便,且I2C接口的传输速率不高,一般传输数据量也不大,阻塞式传输是常用的数据传输方式。

函数名

功能描述

HAL_I2C_IsDeviceReady()

检查某个从设备是否准备好了I2C通信

HAL_I2C_Master_Transmit()

作为主设备向某个地址的从设备发送一定长度的数据

HAL_I2C_Master_Receive()

作为主设备从某个地址的从设备接收一定长度的数据

HAL_I2C_Slave_Transmit()

作为从设备发送一定长度的数据

HAL_I2C_Slave_Receive()

作为从设备接收一定长度的数据

HAL_I2C_Mem_Write()

向某个从设备的指定存储地址开始写入一定长度的数据

HAL_I2C_Mem_Read()

从某个从设备的指定存储地址开始读取一定长度的数据

(1)函数HAL_I2C_IsDeviceReady()

        函数HAL_I2C_IsDeviceReady()用于检查I2C网络上一个从设备是否做好了I2C通信准备,其函数原型定义如下:

HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint32_t Trials,uint32_t Timeout);

        其中,hi2c是I2C接口对象指针,DevAddress是从设备地址,Trials是尝试的次数,Timeout是超时等待时间(单位是嘀嗒信号节拍数),当SysTick定时器频率为默认的1000Hz时,Timeout的单位就是ms。

(2)主设备发送和接收数据

        一个I2C总线上有一个主设备,可能有多个从设备。主设备与从设备通信时,必须指定设备地址。I2C主设备发送和接收数据的两个函数的原型定义如下:

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint8_t *pData,uint16_t Size,uint32_t Timeout);

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint8_t *pData,uint16_t Size,uint32_t Timeout);

        其中,pData是发送或接收数据的缓冲区,Size是缓冲区大小。DevAddress是从设备地址无论是发送还是接收,这个地址都要设置为I2C设备的写操作地址。Timeout为超时等待时间单位是嘀嗒信号节拍数。

        阻塞式操作函数在数据发送或接收完成后才返回,返回值为HAL_OK时表示传输成功,否则可能是出现错误或超时。

(3)从设备发送和接收数据

        I2C从设备发送和接收数据的两个函数的原型定义如下:

HAL_StatusTypeDef HAL_I2C_slave_Transmit(I2C_HandleTypeDef *hi2c,uint8_t *pData,uint16_t Size,uint32_t Timeout);

HAL_StatusTypeDef HAL_I2C_slave_Receive(I2C_HandleTypeDef *hi2c,uint8_t *pData,uint16_t size,uint32_t Timeout)

        I2C从设备是应答式地响应主设备的传输要求,发送和接收数据的对象总是主设备,所以函数中无须设置目标设备地址。

(4)I2C存储器数据传输

        对于I2C接口的存储器,例如EEPROM芯片24C02,有两个专门的函数用于存储器数据读写。向存储器写入数据的函数是HAL_I2C_Mem_Write(),其原型定义如下:

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);

        其中,DevAddress是I2C从设备地址,MemAddress是存储器内部写入数据的起始地址,MemAddSize是存储器内部地址大小,即8位地址或16位地址,有两个宏定义表示存储器内部地址大小。

#define I2C_MEMADD_SIZE_8BIT 0x00000001U  //8位存储器地址
#define I2C_MEMADD_SIZE_16BIT 0x000000100 //16位存储器地址

        参数pData是待写入数据的缓冲区指针,Size是待写入数据的字节数,Timeout是超时等待时间。使用这个函数可以很方便地向I2C接口存储器一次性写入多字节的数据。从存储器读取数据的函数是HAL_I2C_Mem_Read),其原型定义如下:

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);

        使用I2C存储器数据传输函数的好处是,可以一次性传递地址和数据,函数会根据存储器的I2C通信协议依次传输地址和数据,而不需要用户自己分解通信过程。

3、中断方式数据传输

        一个I2C接口有两个中断号,一个用于事件中断,另一个用于错误中断。HAL_I2C_EV_IRQHandler()是事件中断ISR中调用的通用处理函数,HAL_I2C_ER_IRQHandler()是错误中断ISR中调用的通用处理函数。

        I2C接口的中断方式数据传输函数,以及各个传输函数关联的回调函数如表:

函数名

函数功能描述

关联的回调函数

HAL_I2C_Master_Transmit_IT()

主设备向某个地址的从设备发送
一定长度的数据

HAL_I2C_MasterTxCpltCallback()

HAL_I2C_Master_Receive_IT()

主设备从某个地址的从设备接收
一定长度的数据

HAL_I2C_MasterRxCpltCallback()

HAL_I2C_Master_Abort_IT()

主设备主动中止中断传输过程

HAL_I2C_AbortCpltCallback()

HAL_I2C_Slave_Transmit_IT()

作为从设备发送一定长度的数据

HAL_I2C_SlaveTxCpltCallback()

HAL_I2C_Slave_Receive_IT()

作为从设备接收一定长度的数据

HAL_I2C_SlaveRxCpltCallback()

HAL_I2C_Mem_Write_IT()

向某个从设备的指定存储地址开
始写入一定长度的数据

HAL_I2C_MemTxCpltCallback()

HAL_I2C_Mem_Read_IT()

从某个从设备的指定存储地址开
始读取一定长度的数据

HAL_I2C_MemRxCpltCallback()

所有中断方式传输函数

中断方式传输过程出现错误

HAL_I2C_ErrorCallback()

        中断方式数据传输函数的参数定义与对应的阻塞式传输函数类似,只是没有超时等待参数Timeout。例如,以中断方式读写I2C接口存储器的两个函数的原型定义如下:

HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t *pData,uint16_t Size);

HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,int16_t MemAddress,uint16_t MemAddSize,uint8_t *pData,uint16_t Size);

        中断方式数据传输是非阻塞式的,函数返回HAL_OK只是表示函数操作成功,并不表示数据传输完成,只有相关联的回调函数被调用时,才表示数据传输完成

4、 DMA方式数据传输

        一个I2C接口有I2C_TX和I2C_RX两个DMA请求,可以为DMA请求配置DMA流,从而进行DMA方式数据传输。I2C接口的DMA方式数据传输函数,以及DMA流发生传输完成事件(DMA_IT_TC)中断时的回调函数如表:

函数名

函数功能描述

关联的回调函数

HAL_I2C_Master_Transmit_DMA()

向某个地址的从设备发送一
定长度的数据

HAL_I2C_MasterTxCpltCallback()

HAL_I2C_Master_Receive_DMA()

从某个地址的从设备接收一
定长度的数据

HAL_I2C_MasterRxCpltCallback()

HAL_I2C_Slave_Transmit_DMA()

作为从设备发送一定长度的
数据

HAL_I2C_SlaveTxCpltCallback()

HAL_I2C_Slave_Receive_DMA()

作为从设备接收一定长度的
数据

HAL_I2C_SlaveRxCpltCallback()

HAL_I2C_Mem_Write_DMA()

向某个从设备的指定存储地
址开始写入一定长度的数据

HAL_I2C_MemTxCpltCallback()

HAL_I2C_Mem_Read_DMA()

从某个从设备的指定存储地
址开始读取一定长度的数据

HAL_I2C_MemRxCpltCallback()

        DMA传输函数的参数形式与中断方式传输函数的参数形式相同,例如,以DMA方式读写I2C接口存储器的两个函数的原型定义如下:

HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t *pData,uint16_t Size);

HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t *pData,uint16_t Size);

        DMA传输是非阻塞式传输,函数返回HAL_OK时只表示函数操作完成,并不表示数据传输完成。DMA传输过程由DMA流产生中断事件,DMA流的中断函数指针指向I2C驱动程序中定义的一些回调函数。I2C的HAL驱动程序中并没有为DMA传输半完成中断事件设计和关联回调函数。

5、其它

        一个I2C从设备有两个地址,一个是写操作地址,另一个是读操作地址。例如开发板上的EEPROM芯片24C02的写操作地址是0xA0,读操作地址是0xA1,也就是在写操作地址上加1。在I2C的HAL驱动程序中,传递从设备地址参数时,只需设置写操作地址,函数内部会根据读写操作类型,自动使用写操作地址或读操作地址。但是在软件模拟I2C接口通信时,必须明确使用相应的地址。

        IIC总线判断高低电平;SPI总线判断边沿。 

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

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

相关文章

关于easy-es对时间范围查询遇到的小bug

前言:在使用easy-es之前作为一个小白的我只有es原生查询的基础,在自己通过查看官方文档自学easy-es遇到了一个挫折,其他的还好语法和MybatisPlus差不多,正以为我觉得很快就能入手,在对时间范围的判断就给我当头一棒&am…

Flink源码解析之:如何根据算法生成StreamGraph过程

Flink源码解析之:如何根据算法生成StreamGraph过程 在我们日常编写Flink应用的时候,会首先创建一个StreamExecutionEnvironment.getExecutionEnvironment()对象,在添加一些自定义处理算子后,会调用env.execute来执行定义好的Flin…

【代码随想录|完全背包问题】

518.零钱兑换|| 题目链接:518. 零钱兑换 II - 力扣(LeetCode) 这里求的是组合数,就是不强调元素排列的顺序,211和121是同一个数那种,要先遍历物品,这样的话我算出来的每个值才是按顺序121&…

一款汽车连接器(HSD(4+2))信号完整性仿真

下面是一款汽车连接器HSD(42) 的3D外形: 其爆炸图如下: 下面是Rosenboger同款产品的2D图: 其信号完整性参数如下: 下面介绍一下如何给上面的3D模型做信号完整性仿真。 在介绍仿真前先介绍一下上面的一些参数:上面的参数…

安卓/system/bin下命令中文说明(AI)

ATFWD-daemon:AT指令转发守护进程,用于将AT指令从应用层转发到调制解调器。 PktRspTest:数据包响应测试工具。 StoreKeybox:存储密钥盒工具,用于安全地存储加密密钥。 WifiLogger_app:WiFi日志记录应用&…

华为开源自研AI框架昇思MindSpore应用案例:ICNet用于实时的语义分割

ICNet用于实时的语义分割 ICNet 被广泛应用于实时的语义分割领域。它在处理图像数据时,能够以较高的效率进行语义分割操作,为相关领域的研究和实际应用提供了有力的支持。ICNet 的实时性使其在众多场景中都具有很大的优势,例如在视频处理、自…

docker-compose搭建sfpt服务器

1. 搭建 创建sftp目录,进入该目录创建docker-compose.yml文件内容如下: version: 3.7services:sftp:image: atmoz/sftpcontainer_name: sftpports:- "122:22"volumes:- ./sftp-data:/homeenvironment:SFTP_USERS: "liubei:liubei161:10…

跨域请求问题

跨域请求简介 跨域请求:通过一个域的JavaScript脚本和另外一个域的内容进行交互 域的信息:协议、域名、端口号 同域:当两个域的协议、域名、端口号均相同 如下所示: 同源【域】策略:在浏览器中存在一种安全策略就是…

AI发展新态势:从技术突破到安全隐忧

AI安全的新挑战 近期AI领域出现了令人担忧的新发现。根据最新研究,AI模型已经开始展现出策略性欺骗的倾向。具体表现在以下几个方面: 策略性欺骗行为的出现 在实验中发现,当研究人员试图让AI执行一些"反Anthropic"的操作时(如获取模型权限和外部服务器访问),模…

【学生管理系统】环境搭建

目录 1. 环境搭建 1.1 前端环境 1.2 后端环境 1.2.1 父项目 1.2.2 domain项目 1.2.3 gateway项目 1.3 数据库环境 1.3.1 用户数据库 1.3.2 班级数据库 1.3.3 学生数据库 1.3.4 课程数据库 1. 环境搭建 1.1 前端环境 项目名:nacos-nuxt-student-fore 创…

若依数据权限控制

效果 新建用户 表结构 sys_role_dept 这张表的存在。是为了实现数据权限自定义的功能 service层 mapper层 流程

vue源码分析(十)—— 生命周期

文章目录 前言一、关键方法 callHook二、详细的钩子函数说明1.beforeCreate和create2.beforeMount & mounted注意点组件(非根组件)的渲染节点(1)invokeInsertHook函数(2)insert方法(3&#…

【运维】部署MKDocs

部署MKDocs obsidian 记录笔记,通过 mkdocs 私有化部署。 1 使用MKDocs创建笔记 创建仓库,安装 Material for MkDocs 和 mkdocs-minify-plugin mkdir tmp cd tmp git initpip install mkdocs-material pip install mkdocs-minify-pluginmkdocs new .2 …

深度学习——神经网络中前向传播、反向传播与梯度计算原理

一、前向传播 1.1 概念 神经网络的前向传播(Forward Propagation)就像是一个数据处理的流水线。从输入层开始,按照网络的层次结构,每一层的神经元接收上一层神经元的输出作为自己的输入,经过线性变换(加权…

面试突击-JAVA集合类(持续更新...)

前言 这篇文档非常适合面试突击人群,java集合类是面试高频问点,阅读完此文章可以直接应对面试官一切问题,最终吊打面试官。 概览 Java 集合,也叫作容器,主要是由两大接口派生而来:一个是 Collection接口&am…

Ps:创建数据驱动的图形 - 数据组

在 Photoshop 的“变量” Variables对话框中,可以为某一图层定义(或关联)变量并指定变量类型和变量值。 请参阅: 《Ps:创建数据驱动的图形 - 定义变量》 每个实例的变量值的集合构成一个数据组 Data Set。在相应的数据…

小猫可以吃面包吗?

在宠物饲养日益普及的当下,小猫的饮食健康成为众多铲屎官关注的焦点。其中,小猫是否可以吃面包这一问题引发了不少讨论。 从面包的成分来看,其主要原料是面粉、水、酵母和盐,部分还会添加糖、油脂、鸡蛋、牛奶等。面粉富含碳水化…

OSI七层模型和交换机

概念讲解 OSI(Open System Interconnection,开放系统互连)七层模型是一种网络通信的参考模型,它将网络通信的功能分为七个层次,每个层次负责特定的任务。 七层模型记忆口诀:物(物理层&#xf…

算法题(19):多数元素

审题: 数组不为空且一定存在众数。需要返回众数的数值 思路: 方法一:哈希映射 先用哈希映射去存储对应数据出现的次数,然后遍历找到众数并输出 当然也可以在第一次映射的过程中就维护一个出现次数最多的数据,这样子就可…

【Chrome】浏览器提示警告Chrome is moving towards a new experience

文章目录 前言一、如何去掉 前言 Chrome is moving towards a new experience that allows users to choose to browse without third-party cookies. 这是谷歌浏览器(Chrome)关于隐私策略更新相关的提示 提示:以下是本篇文章正文内容&…