STM32学习(十)

I2C模块内部结构

I2C(Inter-Integrated Circuit)模块是一种由Philips公司开发的二线式串行总线协议,用于短距离通信,允许多个设备共享相同的总线‌。

  • 硬件连接简单‌:I2C通信仅需要两条总线,即SCL(时钟线)和SDA(数据线),大大简化了系统的硬件设计‌12。
  • 支持多设备共享‌:在I2C总线中,可以挂载多个从设备,每个设备都有一个唯一的地址,主设备通过广播地址的方式与从设备进行通信‌25。
  • 传输速率灵活‌:I2C总线传输模式具有向下兼容性,传输速率在标准模式下可达100kbps,快速模式下可达400kbps,高速模式下更是可达3.4Mbps‌34。

引脚初始化

引脚映射表

引脚实现代码

void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB,&GPIO_InitStruct)
}

连接电路

波特率

I2C的波特率指的是I2C总线上的数据传输速率,它可以根据不同的模式达到不同的速率‌。具体来说:

  • 在‌标准模式‌下,I2C的波特率为100kHz‌12。
  • 在‌快速模式‌下,I2C的波特率可以达到400kHz‌12。
  • 还有一些更高速的模式,如‌快速模式+‌,波特率可以达到1MHz‌1。

I2C总线中的波特率由主机控制,主机通过产生SCL(时钟线)信号来分配给所有从机,因此主机可以通过控制时钟信号频率来调节波特率,即控制通信速度‌。这种灵活性使得I2C总线能够适应不同的通信需求和应用场景。

占空比

在I2C总线通信中,占空比是指数据线(SDA)上的高电平持续时间与整个时钟周期(由时钟线SCL控制)的比例。这个比例决定了数据传输的稳定性和可靠性‌12。

在没有明确的情况下我们选择2/1的占空比

初始化I2C模块代码

void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);//开启I2C的时钟RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,ENABLE);//施加复位信号RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,DISABLE);//释放复位信号I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed = 400000;//波特率400kI2C_InitStruct.I2C_Mode = I2C_Mode_I2C;//标准的I2CI2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比2:1I2C_Init(I2C1,&I2C_InitStruct);I2C_Cmd(I2C1,ENABLE);//闭合I2C1的总开关
}

写数据

数据发送的流程

主设备向从设备发送数据

  1. 发送起始信号‌:主设备在SCL(时钟线)为高电平时,将SDA(数据线)从高拉低,产生起始信号,通知所有从设备准备接收数据‌。
  2. 发送设备地址‌:主设备紧接着发送从设备的7位地址,以及一个写信号(通常是低电平),指示这是一个写操作‌。
  3. 等待从设备响应‌:从设备监测到自己的地址后,通过在下一个时钟周期拉低SDA线(发送ACK)来响应,确认它准备好了接收数据‌。
  4. 发送数据‌:主设备开始发送数据,每个字节数据后会跟着等待接收来自从设备的响应(ACK)。从设备在接收到每个字节后,都会发送一个ACK信号来确认‌。
  5. 发送停止信号‌:数据发送完毕后,主设备发送停止信号(SCL高时SDA从低变高),终止传输‌。

从设备向主设备发送数据

  1. 主设备初始化读取操作‌:主设备发送起始信号,然后发送从设备的地址以及一个读取位(通常是高电平),指示这是一个读取操作‌。
  2. 从设备响应‌:从设备监测到自己的地址后,通过发送ACK信号来响应‌。
  3. 主设备发送重复开始信号或停止信号‌:如果主设备计划在同一事务中连续读取多个从设备或进行连续读取,它可以发送重复开始信号来保持总线控制权。如果仅从当前从设备读取且读取操作即将结束,主设备在收到从设备的ACK后可直接发送停止信号‌。
  4. 从设备发送数据‌:在收到读取命令后,从设备开始发送数据。主设备在接收到每个字节后,都会发送一个ACK信号来确认。当接收到最后一个数据字节后,主设备可能会发送一个无效响应(NACK),然后发送停止信号来终止传输‌。

等待总线空闲

发送数据前要监控总线是否繁忙,从BUSY标志位来判断总线是否空闲,I2C_GetFlagStatus函数用来获取BUSY标志。I2C_GetFlagStatus 函数是一个在 STM32 微控制器的 I2C(Inter-Integrated Circuit)库函数中常用的函数,用于检查 I2C 接口的状态标志。这个函数通常用于轮询(polling)方式,以确定 I2C 总线上的特定事件或状态是否已经发生,例如数据传输完成、接收到起始信号、检测到错误等。

FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
  • I2Cx:指向要检查的 I2C 接口的指针。例如,对于 STM32F103 系列,可能是 I2C1 或 I2C2
  • I2C_FLAG:要检查的特定 I2C 状态标志。这些标志在 STM32 的 I2C 库头文件中定义,通常是以 I2C_FLAG_ 开头的宏。
  • 返回值是 FlagStatus 枚举类型,它通常有两个可能的值:SET(标志已设置)和 RESET(标志未设置)。

发送起始位

发送起始位是向START寄存器内写数值1,使用函数I2C_GenerateStart完成。


I2C_GenerateStart 函数是用于生成 I2C 通信起始条件(START condition)的函数。在 I2C 通信中,起始条件是一个重要的信号,用于通知所有连接到总线的设备即将开始数据传输。当 NewState 参数为 ENABLE 时,I2C_GenerateStart 函数会设置相应的寄存器位,从而在 I2C 总线上生成一个起始条件。起始条件是一个在 SCL(时钟线)为高电平时,SDA(数据线)由高电平变为低电平的边沿。这个边沿会被所有连接到总线的 I2C 设备检测到,并通知它们即将开始数据传输。

void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
  • I2Cx:指向要操作的 I2C 接口的指针。在 STM32 微控制器中,这通常是 I2C1I2C2 等。
  • NewState:这是一个 FunctionalState 枚举类型的值,用于指定是否生成起始条件。它可以是 ENABLE(生成起始条件)或 DISABLE(不生成起始条件)。

在发送起止位后我们需要确定起止位是否发送完毕,我们通过SB标志来判断。

while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB) == RESET);

发送地址

AF标志位是ACK应答标志位,当AF为1时ACK答应失败未收到答应,ADDR寻址成功标志位,当寻址成功值为1,失败值为0。在发送地址前我们需要清理AF标志位的值然后发送地址。

I2C_ClearFlag(I2Cx,I2C_FLAG_AF);//清除AF
I2C_SendData(I2Cx,Addr & 0xfe);//发送地址和RW

在发送的过程中需要持续判断AF和ADDR标识符的状态

while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR) == SET){break;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) == SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -1;}
}

后续我们继续清除ADDR状态标示符

I2C_ReadRegister(I2Cx,I2C_Register_SR1);
I2C_ReadRegister(I2Cx,I2C_Register_SR2);

发送数据

发送数据过程中我们要持续监控ACK和发送数据寄存器的状态,AF为1标示为响应ACK,停止发送数据,BTF负责监控发送数据寄存器内是否有数据,保证在其空的情况下推送数据进入。

发送停止位

代码

int main(){My_I2C_Init();uint8_t commands[] = {0x00,0x8d,0x14,0xaf,0xa5};My_I2C_SendBytes(I2C1,0x78,commands,5);
}void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);//开启I2C的时钟RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,ENABLE);//施加复位信号RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,DISABLE);//释放复位信号I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed = 400000;//波特率400kI2C_InitStruct.I2C_Mode = I2C_Mode_I2C;//标准的I2CI2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比2:1I2C_Init(I2C1,&I2C_InitStruct);I2C_Cmd(I2C1,ENABLE);//闭合I2C1的总开关
}int My_I2C_SendBytes(I2C_TypeDef *I2Cx,uint8_t Addr,uint8_t *pData,uint16_t Size){//等待总线空闲while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY) == SET){}//发送起止位I2C_GenerateSTART(I2C1,ENABLE);//确定起止位是否发送完毕	while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB) == RESET){}//发送地址//清除AFI2C_ClearFlag(I2Cx,I2C_FLAG_AF);I2C_SendData(I2Cx,Addr & 0xfe);while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR) == SET){break;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) == SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -1;//寻址失败}}//清除ADDRI2C_ReadRegister(I2Cx,I2C_Register_SR1);I2C_ReadRegister(I2Cx,I2C_Register_SR2);//发送数据 for(uint8_t i = 0;i<Size;i++){while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) == SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE) == SET){break;}}I2C_SendData(I2Cx,pData[i]);}while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) == SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BTF) == SET){break;}}//发送停止位I2C_GenerateSTOP(I2Cx,ENABLE);return 0;
}

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

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

相关文章

使用 Rust 实现零拷贝数据处理:性能优化的极致探索

随着大数据处理需求的不断增长&#xff0c;数据处理框架需要高效的内存管理能力以提升吞吐量与降低延迟。在本文中&#xff0c;我们将探索 Rust 语言如何利用零拷贝&#xff08;Zero-Copy&#xff09;的特性来构建高效的数据处理系统。这一技术尽管强大&#xff0c;但由于它对内…

Oracle job(定时任务)

1、job的作用 可以定时执行任务&#xff08;分/次、时/次、天/次等&#xff09; 2、创建job --创建job --注意点&#xff1a; --①job_no 为系统自动获取&#xff1b; --②存储过程名需要加‘&#xff1b;’ --③定时器开始执行时间可以填‘sysdate,表示立即执行 --④执行频…

nginx配置 - 资源参数配置(性能优化)

nginx - 资源参数配置 (性能优化) 一、worker_rilimit_nofile配置的含义使用场景如何调整参数系统级文件描述符限制(补充)二、worker_connections三、两者之间的数值关系四、sendfile五、keepalive_timeout本文重点讨论: 最大文件描述符数量 worker_rilimit_nofile和最大连…

iOS - 引用计数(ARC)

1. 基本数据结构 // 对象结构 struct objc_object {isa_t isa; // isa 指针&#xff0c;包含引用计数信息 };// isa 的位域结构 union isa_t {uintptr_t bits;struct {uintptr_t nonpointer : 1; // 是否启用优化的 isa 指针uintptr_t has_assoc : 1; // 是…

尚硅谷· vue3+ts 知识点学习整理 |14h的课程(持续更ing)

vue3 主要内容 核心&#xff1a;ref、reactive、computed、watch、生命周期 常用&#xff1a;hooks、自定义ref、路由、pinia、miit 面试&#xff1a;组件通信、响应式相关api ----> 笔记&#xff1a;ts快速梳理&#xff1b;vue3快速上手.pdf 笔记及大纲 如下&#xff…

【Ubuntu20.04】Apollo10.0 Docker容器部署+常见错误解决

官方参考文档【点击我】 Apollo 10.0 版本开始&#xff0c;支持本机和Docker容器两种部署方式。 如果您使用本机部署方式&#xff0c;建议使用x86_64架构的Ubuntu 22.04操作系统或者aarch64架构的Ubuntu 20.04操作系统。 如果您使用Docker容器部署方式&#xff0c;可以使用x…

安卓14无法安装应用解决历程

客户手机基本情况&#xff1a; 安卓14&#xff0c;对应的 targetSdkVersion 34 前天遇到了安卓14适配问题&#xff0c;客户发来的截图是这样的 描述&#xff1a;无法安装我们公司的B应用。 型号&#xff1a;三星google美版 解决步骤&#xff1a; 1、寻找其他安卓14手机测试…

利用 NineData 实现 PostgreSQL 到 Kafka 的高效数据同步

记录一次 PostgreSQL 到 Kafka 的数据迁移实践。前段时间&#xff0c;NineData 的某个客户在一个项目中需要将 PostgreSQL 的数据实时同步到 Kafka。需求明确且普遍&#xff1a; PostgreSQL 中的交易数据&#xff0c;需要实时推送到 Kafka&#xff0c;供下游多个系统消费&#…

Zookeeper是如何保证事务的顺序一致性的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper是如何保证事务的顺序一致性的?】面试题。希望对大家有帮助&#xff1b; Zookeeper是如何保证事务的顺序一致性的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过多个机制来保证事务的顺序一…

电脑如何无线控制手机?

想在电脑上无线控制手机&#xff0c;需要用到Total Control控制软件&#xff0c;具体步骤如下&#xff1a; 1、首先我们在电脑上安装上控制软件Total Control并打开。 2、开启手机USB调试和ADB仅充电模式。 3、手机电脑均连接上相同局域网。 4、连接(首次使用需要用手机U…

内网穿透的应用-自托管文件分享系统PicoShare搭建流程与远程共享实战教程

文章目录 前言1. 本地安装Docker2. 本地部署PicoShare3. 如何使用PicoShare4. 公网远程访问本地 PicoShare4.1 内网穿透工具安装4.2 创建远程连接公网地址 5. 固定PicoShare公网地址 前言 大家好&#xff01;在数字化时代&#xff0c;文件共享变得越来越重要&#xff0c;尤其是…

STM32 拓展 电源控制

目录 电源控制 电源框图 VDDA供电区域 VDD供电区域 1.8V低电压区域 后备供电区域 电压调节器 上电复位和掉电复位 可编程电压检测器(PVD) 低功耗 睡眠模式(只有CUP(老板)睡眠) 进入睡眠模式 退出睡眠模式 停机(停止)模式(只留核心区域(上班)) 进入停…

欧几里得距离在权重矩阵中的物理意义

欧几里得距离在权重矩阵中的物理意义 目录 欧几里得距离在权重矩阵中的物理意义**衡量神经元差异程度**:**反映模型变化程度**:**聚类和分组的依据**:自然语言处理中的模型更新:**神经网络聚类分组**:欧几里得距离在权重矩阵中的物理意义衡量神经元差异程度: 在神经网络中…

pytorch中nn.Conv2d详解及参数设置原则

文章目录 基础参数1. in_channels (输入通道数)2. out_channels (输出通道数)3. kernel_size (卷积核大小)4. stride (步幅)5. padding (填充)6. dilation (膨胀)7. groups (分组卷积)8. bias (偏置) 如何设置参数&#xff1f;1. **in_channels 和 out_channels&#xff08;输入…

GolangWeb开发- net/http模块

文章目录 Golang开发-案例整理汇总一、net/http介绍二、HTTP客户端Get请求Post请求三、HTTP服务端总结Golang开发经典案例,点击下方链接 Golang开发-案例整理汇总 一、net/http介绍 Go语言内置的net/http包提供了HTTP客户端和服务端的实现。 文档链接: https://pkg.go.dev/n…

内蒙古水系详细很全shp格式arcgis软件无偏移坐标下载后内容测评

标题中的“内蒙古水系详细很全shp格式arcgis软件无偏移坐标”指的是一个地理信息系统&#xff08;GIS&#xff09;数据集&#xff0c;该数据集详细记录了内蒙古地区的水系信息&#xff0c;并以ESRI公司的标准矢量数据格式——Shapefile&#xff08;.shp&#xff09;进行存储。S…

【Vim Masterclass 笔记07】S05L19:Vim 剪切、复制、粘贴操作同步练习

文章目录 S05L19 Vim 剪切、复制、粘贴操作同步练习&#xff08;Exercise 05 - Cut, Copy and Paste&#xff09;1 训练目标2 操作指令2.1 打开 dyp.txt 文件2.2 交换文件的头两行2.3 将文件首行 put 到文件其他为止2.4 练习在光标位置的上方粘贴文本行2.5 通过交换字符顺序更正…

【Rust自学】10.6. 生命周期 Pt.2:生命周期的语法与例子

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 10.6.1. 生命周期标注语法 生命周期的标注并不会改变引用的生命周期长度。如果某个函数它制定了泛型生命周期参数&#xff0c;那么它就可…

HTML 显示器纯色亮点检测工具

HTML 显示器纯色亮点检测工具 相关资源文件已经打包成html等文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Html相关程序案例&#xff0c;秉着开源精神的想法&#xff0c;望大家喜欢&#…

服务器虚拟化:现代 IT 基础架构的核心技术

服务器虚拟化&#xff1a;现代 IT 基础架构的核心技术 随着云计算和大规模数据中心的快速发展&#xff0c;服务器虚拟化已成为现代 IT 基础架构中的核心技术。通过虚拟化&#xff0c;企业可以在同一台物理服务器上运行多个虚拟机&#xff08;VM&#xff09;&#xff0c;从而提…