当前位置: 首页 > article >正文

软件IIC和硬件IIC的主要区别,用标准库举例!

学习交流792125321,欢迎一起加入讨论!

在学习iic的时候,我们经常会遇到软件 I²C和硬件 I²C,它两到底有什么区别呢?

软件 I²C(模拟 I²C)和硬件 I²C(外设 I²C)是两种实现 I²C 总线通信的方式,核心区别在于 ​是否依赖微控制器(MCU)内置的硬件 I²C 外设。以下是详细对比及标准库(以 STM32 标准外设库为例)的实现差异:

1. 核心区别

特性软件 I²C硬件 I²C
实现方式通过 GPIO 引脚模拟 I²C 时序(软件控制)使用 MCU 内置的硬件 I²C 外设(硬件控制)
CPU 占用高(需 CPU 持续操作 GPIO)低(硬件自动完成时序,CPU 可处理其他任务)
时序精度依赖软件延时,精度较低由硬件时钟控制,精度高且稳定
开发复杂度简单(无需配置复杂寄存器)复杂(需初始化外设、处理中断/DMA)
灵活性高(可适配任意 GPIO 引脚)低(必须使用硬件 I²C 外设的固定引脚)
速度较慢(受限于软件延时)较快(支持标准模式 100kHz、快速模式 400kHz+)
兼容性通用性强(可适配不同 MCU)依赖具体 MCU 的硬件支持

2. 标准库实现对比(以 STM32F1 标准外设库为例)​

​(1) 硬件 I²C 实现

硬件 I²C 使用 STM32 内置的 I²C 外设,需配置时钟、引脚复用、中断/DMA 等。

代码示例:初始化硬件 I²C1(标准模式,100kHz)​

#include "stm32f10x_i2c.h"void I2C_Hardware_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;I2C_InitTypeDef I2C_InitStruct;// 使能时钟(I2C1 和 GPIOB)RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 配置 GPIOB6 (SCL) 和 GPIOB7 (SDA) 为复用开漏模式GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);// 配置 I2C1I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 占空比 16:9I2C_InitStruct.I2C_OwnAddress1 = 0xA0;          // 主机地址(可忽略)I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;        // 启用应答I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStruct.I2C_ClockSpeed = 100000;         // 100kHzI2C_Init(I2C1, &I2C_InitStruct);// 启用 I2C1I2C_Cmd(I2C1, ENABLE);
}// 发送数据函数(需处理状态标志和中断)
void I2C_WriteByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {I2C_GenerateSTART(I2C1, ENABLE);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Transmitter);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));I2C_SendData(I2C1, regAddr);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_SendData(I2C1, data);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_GenerateSTOP(I2C1, ENABLE);
}
​(2) 软件 I²C 实现

通过 GPIO 手动控制 SCL 和 SDA 引脚电平,模拟 I²C 时序。

代码示例:模拟 I²C 时序(使用 GPIOB8 和 GPIOB9)​

#include "stm32f10x_gpio.h"// 定义 SCL 和 SDA 引脚
#define SOFT_I2C_SCL_PIN    GPIO_Pin_8
#define SOFT_I2C_SDA_PIN    GPIO_Pin_9
#define SOFT_I2C_PORT       GPIOB// 初始化 GPIO
void Soft_I2C_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 配置 SCL 和 SDA 为开漏输出模式GPIO_InitStruct.GPIO_Pin = SOFT_I2C_SCL_PIN | SOFT_I2C_SDA_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SOFT_I2C_PORT, &GPIO_InitStruct);// 初始拉高 SCL 和 SDAGPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);
}// 微秒级延时函数(需根据实际时钟调整)
void Delay_us(uint32_t us) {us *= 72; // 假设主频为 72MHzwhile (us--) __NOP();
}// 发送起始信号
void Soft_I2C_Start(void) {GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);Delay_us(5);GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);
}// 发送停止信号
void Soft_I2C_Stop(void) {GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);Delay_us(5);GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);Delay_us(5);GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);
}// 发送一个字节
void Soft_I2C_WriteByte(uint8_t data) {for (int i = 0; i < 8; i++) {if (data & 0x80) {GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);} else {GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);}Delay_us(2);GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);Delay_us(5);GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);data <<= 1;}// 等待从机应答(省略应答检查)GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SDA_PIN);Delay_us(2);GPIO_SetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);Delay_us(5);GPIO_ResetBits(SOFT_I2C_PORT, SOFT_I2C_SCL_PIN);
}

3. 适用场景

场景推荐方式原因
高速通信(>100kHz)硬件 I²C依赖硬件时序精度,避免软件延时误差
多任务系统硬件 I²C减少 CPU 占用,支持 DMA/中断
引脚资源紧张硬件 I²C必须使用固定引脚,避免浪费 GPIO
适配非标准 I²C 设备软件 I²C可灵活调整时序(如长延时、非标准协议)
硬件 I²C 外设不可用软件 I²C解决硬件资源冲突或兼容性问题

4. 常见问题

  • 硬件 I²C 初始化失败
    检查时钟配置、引脚复用、上拉电阻(硬件 I²C 需要外部上拉,通常 4.7kΩ)。

  • 软件 I²C 通信不稳定
    调整延时函数精度,确保 SCL/SDA 边沿时间符合设备要求。

  • 速度瓶颈
    软件 I²C 通常无法超过 100kHz,硬件 I²C 可支持 400kHz(Fast Mode)或更高。


总结

  • 硬件 I²C:适合高速、高稳定性场景,但开发复杂且依赖固定引脚。
  • 软件 I²C:灵活简单,但占用 CPU 资源且速度受限。
    根据项目需求选择合适方案:优先使用硬件 I²C 提升性能,若硬件资源不足或需要特殊时序,则用软件模拟。

相关文章:

软件IIC和硬件IIC的主要区别,用标准库举例!

学习交流792125321&#xff0c;欢迎一起加入讨论&#xff01; 在学习iic的时候&#xff0c;我们经常会遇到软件 IC和硬件 IC,它两到底有什么区别呢&#xff1f; 软件 IC&#xff08;模拟 IC&#xff09;和硬件 IC&#xff08;外设 IC&#xff09;是两种实现 IC 总线通信的方式…...

Codeforces Round 1006 Div3 A-E

A 题目描述 夏目章人&#xff08;Natsume Akito&#xff09;刚刚在一个新世界苏醒&#xff0c;便立即收到了他的第一个任务&#xff01;系统为他提供了一个包含 n 个零的数组 a&#xff0c;以及两个整数 k 和 p。在每次操作中&#xff0c;章人需要选择两个整数 i 和 x&#x…...

4个 Vue 路由实现的过程

大家好&#xff0c;我是大澈&#xff01;一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff0c;关注我&#xff0c;科技未来或许我能帮到你&#xff01; Vue 路由相信朋友们用的都很熟了&#xff0c;但是你知道 Vue 路由…...

git文件过大导致gitea仓库镜像推送失败问题解决(push failed: context deadline exceeded)

问题描述&#xff1a; 今天发现gitea仓库推送到某个镜像仓库的操作几个月前已经报错终止推送了&#xff0c;报错如下&#xff1a; 首先翻译报错提示可知是因为git仓库大小超过1G限制。检查本地.git文件&#xff0c;发现.git文件大小已达到1.13G。确定是.git文件过大导致&…...

简要分析NETLINK_ROUTE参数

NETLINK_ROUTE时Linux内核中Netlink协议族的一个子类型&#xff0c;专用于用户空间与内核网络子系统之间的通信&#xff0c;它是实现动态网络配置&#xff08;如路由表、网络接口、地址管理&#xff09;的核心机制&#xff0c;为现代网络管理工具&#xff08;如iproute2&#x…...

Java中default关键字

1. 在 switch 语句中作为默认分支 在 switch 语句里&#xff0c;default 用于定义当所有 case 标签的值都无法匹配 switch 表达式的值时要执行的代码块。它并非强制要求&#xff0c;但使用它可以增强代码的健壮性&#xff0c;处理未预见的情况。 public class SwitchDefaultE…...

怎么利用DeepSeek进行PCB设计?

最近在琢磨利用Deepseek改善PCB的细节设计&#xff0c;毕竟立创EDA里面没有集成DS&#xff0c;因此&#xff0c;如何让DS能识别图片成了重中之重。所幸最近腾讯元宝里面集成了R1的满血版&#xff0c;这个版本可以上传图片&#xff0c;于是让DS识别图片就可能了。 在原理图设计…...

详细介绍 Jupyter nbconvert 工具及其用法:如何将 Notebook 转换为 Python 脚本

nbconvert 是 Jupyter 提供的一个非常强大的工具&#xff0c;允许用户将 Jupyter Notebook 文件&#xff08;.ipynb&#xff09;转换成多种格式&#xff0c;包括 Python 脚本&#xff08;.py&#xff09;、HTML、PDF、LaTeX 等。你可以通过命令行来运行 nbconvert&#xff0c;也…...

windows上传uniapp打包的ipa文件到app store构建版本

uniapp是一个跨平台的框架&#xff0c;使用windows电脑也可以开发ios软件&#xff0c;因为uniapp的打包是在云端实现的&#xff0c;本地电脑无需使用mac电脑即可完成打包。 但是打包后的ipa文件需要上架到app store的构建版本上&#xff0c;没有mac电脑&#xff0c;又如何上架…...

PySide(PyQT),QGraphicsItem的pos()和scenePos()区别

在QGraphicsItem中&#xff0c;pos()和scenePos()是两个重要的方法&#xff0c;用于描述图形项的位置&#xff0c;但它们的含义和用途有所不同。理解它们的区别对于正确操作和管理QGraphicsItem的位置至关重要。 1. pos()方法 • 定义&#xff1a;pos()返回的是QGraphicsItem在…...

idea 快捷键 Reformat code

Reformat code...

Spring Boot 项目中使用责任链模式实现复杂接口解耦和动态编排(带示例)

目录 责任链模式概述 解耦 动态编排 运用场景 代码示例 1. 定义请求和响应对象 2. 定义处理者接口和抽象处理者类 3. 实现具体的处理者类 4. 配置责任链 5. 控制器类调用责任链 代码解释 责任链模式概述 责任链模式是一种行为设计模式,它允许你将请求沿着处理者链…...

消防设施操作员考试备考:以技巧为翼,翱翔知识天空​

消防设施操作员考试的备考过程中&#xff0c;掌握实用技巧能让学习事半功倍。以下为您介绍一系列备考技巧&#xff0c;助您在知识的天空中自由翱翔。​ 记忆技巧&#xff1a;化繁为简​ 消防知识众多&#xff0c;记忆难度较大。可以采用多种记忆方法&#xff0c;如口诀记忆法…...

qt之No executable specified

在Qt中遇到文件复制操作时出现“No executable specified”错误&#xff0c;通常与程序编译或运行环境配置问题相关&#xff0c;而非文件操作本身的问题。以下是可能的原因及解决方案&#xff1a; 项目配置文件损坏 现象&#xff1a; 在执行文件操作前&#xff0c;程序无法启动…...

物联网商业模式

物联网商业模式是一种战略规划&#xff0c;它融合了物联网技术来创造价值并获取收入。它与传统商业模式的不同之处在于&#xff0c;它利用互联设备来改善运营、提升客户体验以及优化服务项目。在当今由科技驱动的世界中&#xff0c;这种商业模式通过利用实时数据来提供创新服务…...

解决ElementPlus对话框el-dialog中关闭事件重复触发问题

问题背景 在使用ElementPlus的el-dialog组件时&#xff0c;发现点击取消按钮会触发两次关闭事件&#xff1a; 1. 第一次参数为PointerEvent&#xff08;事件对象&#xff09; 2. 第二次参数为undefined 需要确保点击取消按钮时仅触发一次有效关闭事件&#xff0c;并传递正确…...

【RabbitMQ】事务

事务的简单配置及使用 配置事务管理器声明队列生产者代码测试 RabbitMQ是基于AMQP协议实现的&#xff0c;该协议实现了事务机制&#xff0c;因此RabbitMQ也支持事务机制. SpringAMQP也提供了对事务相关的操作.RabbitMQ事务允许开发者确保消息的发送和接收是原子性的&#xff0c…...

算法刷题--贪心算法

要点 其实也没啥要点&#xff0c;就是求局部最优解&#xff0c;完事了将局部最优解汇总、筛选、max\min之类的&#xff0c;获得全局最优解&#xff0c;每一次都选择最优的&#xff0c;这个就是贪心算法。 例题 分发饼干-中等 大概就是一堆小孩g,每个人都有一个胃口g[i]&…...

MVCC的理解(Multi-Version Concurrency Control,多版本并发控制)

1.事务特性(ACID) 原子性&#xff1a;事务要么全部成功&#xff0c;否则全部回滚 一致性&#xff1a;保证逻辑完整性&#xff08;关联表删除&#xff09; 隔离性&#xff1a;事务并发隔离&#xff08;行锁&#xff0c;间隙锁&#xff09; 持久性&#xff1a;已提交的事务永…...

CCF-CSP第24次认证第2题 --《序列查询新解》

4281. 序列查询新解 - AcWing题库 上一题“序列查询”中说道&#xff1a; A[A0,A1,A2,⋯,An]A[A0,A1,A2,⋯,An] 是一个由 n1n1 个 [0,N)[0,N) 范围内整数组成的序列&#xff0c;满足 0A0<A1<A2<⋯<An<N0A0<A1<A2<⋯<An<N。 基于序列 AA&#…...

Webpack 打包详细教程

Webpack 是一个现代 JavaScript 应用的静态模块打包工具&#xff0c;它可以处理 JavaScript、CSS、图片等资源&#xff0c;并优化它们以提高性能。以下是 Webpack 从基础到进阶的详细教程。 1. Webpack 基础概念 Webpack 的核心概念包括&#xff1a; Entry&#xff08;入口&a…...

每日一题----------集合

数组&#xff1a; &#xff08;1&#xff09;长度开始必须指定&#xff0c;而且一但指定&#xff0c;不能修改。 &#xff08;2&#xff09;保存的必须为同一类型的元素。 &#xff08;3&#xff09;使用数组进行增加元素的代码--比较麻烦。 如果要添加数据则需要&#xff…...

滑动窗⼝(同向双指针)---最⼤连续1的个数III

题目链接 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1,0,0,0,1,1,1,1,0], K 2 输出&#xff1a;6 解释&#xff1a;[1,1,1,0,0,…...

《几何原本》命题I.30

《几何原本》命题I.30 平行于同一直线的两条直线互相平行。 设 l 1 ∥ l 2 , l 1 ∥ l 3 l_1\parallel l_2,l_1\parallel l_3 l1​∥l2​,l1​∥l3​ 则 ∠ 1 ∠ 2 , ∠ 1 ∠ 3 \angle 1\angle 2,\angle 1\angle 3 ∠1∠2,∠1∠3 则 ∠ 2 ∠ 3 \angle 2\angle 3 ∠2∠3…...

蓝桥杯 k倍区间

题目描述 给定一个长度为 NN 的数列&#xff0c;A1,A2,⋯ANA1​,A2​,⋯AN​&#xff0c;如果其中一段连续的子序列 Ai,Ai1,⋯AjAi​,Ai​1,⋯Aj​ ( i≤ji≤j ) 之和是 KK 的倍数&#xff0c;我们就称这个区间 [i,j][i,j] 是 K 倍区间。 你能求出数列中总共有多少个 KK 倍区间…...

dify-SQL查询

第1节 DIFY 编排流程 1.1 步骤 1.开始&#xff1a;用户输入分析需求 2.LLM-SQL 专家&#xff1a;大模型根据用户输入需求生成 SQL 查询 3.SQL查询&#xff1a;执行查询并获取数据 4.结束&#xff1a;输出查询结果集 1.2 工作流 第2节 组件配置 2.1 开始 新建一个开始组件&am…...

【制作PPT的AI工具】

制作PPT的AI工具&#xff1a; 1. Gamma&#xff1a; 特点&#xff1a; 无需下载&#xff0c;支持网页、移动端及iPad使用。提供多种模板和主题&#xff0c;支持一键生成PPT大纲、排版和配图。优点&#xff1a; 操作简单&#xff0c;适合快速制作演示文稿。 2. Beautiful.ai&…...

贪心算法精解:用C++征服最优解问题

贪心算法精解&#xff1a;用C征服最优解问题 一、贪心算法的本质&#xff1a;当下最优即全局最优 贪心算法如同下棋高手&#xff0c;每一步都选择当前最优的走法。它的核心思想是&#xff1a;通过局部最优选择的叠加&#xff0c;最终得到全局最优解。这种算法在时间复杂度上往…...

《程序员的自我修养—链接、装载与库》-- 对书中常见段的讲解总结

1. 核心段的作用与特点 (1) .text 段&#xff08;代码段&#xff09; 内容&#xff1a;存放程序的可执行指令&#xff08;机器码&#xff09;&#xff0c;例如函数的实现代码。特点&#xff1a; 通常是只读的&#xff08;防止程序意外修改指令&#xff09;。在程序运行前已确…...

一文了解汽车图像传感器

2024年底,安森美做了题为"How Automotive Image Sensors Transform the Future of Autonomous Driving"的演讲,这里结合其内容对自动驾驶图像传感器做一个介绍。 当前的自动驾驶感知技术主要有两大技术路线:一种是仅使用摄像头作为传感器进行信息采集的纯…...