模拟IIC——关于模拟IIC的IO口的配置选取推挽输出还是开漏输出,以及是否需要更改IO口输入输出模式和是否需要对IO配置上拉

news2025/1/13 7:35:56

问题如下

当时我以为引脚配错了,原理图明明是B引脚,为何程序是C呢
在这里插入图片描述
在这里插入图片描述

查了一下资料,顿悟了

https://blog.csdn.net/m0_62243928/article/details/125779308

在使用模拟IIC的时候,观看别人的程序的时候发现了程序之间的一些不一样的地方

——————————————————————————————————代码1————————————————————————————————————
 
//IO方向设置
#define SDA_IN()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}	//PB9输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} //PB9输出模式
//IO操作函数	 
#define IIC_SCL    PBout(8) //SCL
#define IIC_SDA    PBout(9) //SDA	 
#define READ_SDA   PBin(9)  //输入SDA 
———————————————————————————————————————————————————————————————————————————
——————————————————————————————————代码2————————————————————————————————————
 
#define BH1750_I2C_SCL_1()  GPIO_SetBits(GPIOB, GPIO_Pin_6)		/* SCL = 1 */
#define BH1750_I2C_SCL_0()  GPIO_ResetBits(GPIOB, GPIO_Pin_6)	/* SCL = 0 */
	
#define BH1750_I2C_SDA_1()  GPIO_SetBits(GPIOB, GPIO_Pin_7)		/* SDA = 1 */
#define BH1750_I2C_SDA_0()  GPIO_ResetBits(GPIOB, GPIO_Pin_7)	/* SDA = 0 */
	
#define BH1750_I2C_SDA_READ()  GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)	
/* 读SDA口线状态 */
———————————————————————————————————————————————————————————————————————————

代码1中间有一个对SDA数据线的模式的配置, 也就是输入输出的设置;

在向从设备写数据的时候会先调用SDA_OUT(),将引脚配置为输出模式;

在向从设备写数据的时候会先调用SDA_IN(),将引脚配置为输入模式;

但是问题来了,代码2中间并没有对引脚的输入输出模式进行改变,代码2也能和从机进行正常的通信,这是为什么呢?模拟IIC通信时对引脚的输入输出模式的配置是否有必要呢?

我仔细对比了两份代码,发现两份代码在引脚的初始化部分不一样。

——————————————————————————————————代码1————————————————————————————————————
void SHT3x_Init(void)
{    
    RCC->APB2ENR|=1<<6;              //使能PORTE时钟					 
	GPIOE->CRL&=0XFF00FFFF;          //PE4,PE5
	GPIOE->CRL|=0X00330000;	         //推挽输出 
	GPIOE->ODR|=3<<4;                //将PE4、PE5设为1
}
——————————————————————————————————代码2————————————————————————————————————
 
static void I2C_BH1750_GPIOConfig(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
 
	RCC_APB2PeriphClockCmd(BH1750_RCC_I2C_PORT, ENABLE);	/* 打开GPIO时钟 */
 
	GPIO_InitStructure.GPIO_Pin = BH1750_I2C_SCL_PIN | BH1750_I2C_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  	    /* 开漏输出 */
	GPIO_Init(BH1750_GPIO_PORT_I2C, &GPIO_InitStructure);
 
	/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
	i2c_Stop();
}
RCC_APB2PeriphClockCmd(BH1750_RCC_I2C_PORT, ENABLE);	/* 打开GPIO时钟 */

GPIO_InitStructure.GPIO_Pin = BH1750_I2C_SCL_PIN | BH1750_I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  	    /* 开漏输出 */
GPIO_Init(BH1750_GPIO_PORT_I2C, &GPIO_InitStructure);

/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
i2c_Stop();

}

可以发现:推挽输出对应->需要切换输入输出模式;开漏输出对应->不需要切换输入输出模式;

我学习IIC的时候明明记得IIC需要使用开漏输出和接上拉电阻的;如果使用推挽输出,当多个设备

连接到一个总线上面时,如果一个设备输出低电平一个设备输出高电平就会出现短路的情况。而且

不能推挽输出实现线与。

为什么这里可以使用推挽呢?我猜测这是模拟IIC和硬件IIC的不同了。

我使用模拟IIC一般来说不会出现需要多个设备连接到一个总线上面情况,也就不会出现上面的短

路的可能以及线与的需求了。所以模拟IIC这里是可以使用推挽输出的。

那为什么推挽输出需要切换输入输出模式,开漏输出不需要切换输入输出模式呢?

我们首先需要了解到GPIO口的输入和输出模式有什么不同以及推挽输出和开漏输出的不同:

下面对于GPIO口的内容引用

GPIO口的输入,输出模式及其说明
https://blog.csdn.net/qq_42384937/article/details/82428812
在输入模式下只有红色圈出的部分处于工作状态,也就是说下半部分的输出电路,实际上是与端口处于隔离状态,不能工作,这个时候我们不能去读取端口的电平。
在这里插入图片描述
在输出模式下,图的上半部,施密特触发器处于开启状态,这意味着CPU可以在“输入数据寄存器”的另一端,随时监控I/O端口的状态;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以发现:

在输出模式下,施密特触发器处于开启状态,这意味着CPU可以在“输入数据寄存器”的另一端,随时监控I/O端口的状态,也就是可以读取IO口的值;

但是对于推挽输出而言:推挽输出是强输出电流模式,在此模式下的输出通道上的推挽结构MOS管,属于强上拉和强下拉的,这会影响读取IDR时的值,强上拉意味着会将来自外部的低电平输入强制置高,强下拉意味着会将来自外部的高电平输入强制置低

在开漏模式下,实现了虚拟的I/O端口双向通信:只要CPU输出逻辑“1”,由于N-MOS管处于关闭状态,I/O端口的电平将完全由外部电路决定,因此,CPU可以在“输入数据寄存器”读到外部电路的信号,而不是它自己输出的逻辑“1”。

了解stm32的双向io口

请问STM32F4的GPIO管脚可以同时配置成输入、输出模式吗
详细一点的内容可以看这两个链接

现在我们可以分析两个代码的差异:推挽输出对应->需要切换输入输出模式;开漏输出对应->不需要切换输入输出模式;

因为设置为推挽输出时 输出通道上的推挽结构MOS管,属于强上拉和强下拉的,这会影响读取IDR时的值,强上拉意味着会将来自外部的低电平输入强制置高,强下拉意味着会将来自外部的高电平输入强制置低。所以我们去读取IO口的值会是输出的值,并不能得到外部电路的值。所以在IIC通信时需要读取外部数据的时候需要将IO的模式配置成输入模式;

但是对于开漏输出来说,只要CPU输出逻辑“1”,由于N-MOS管处于关闭状态,I/O端口的电平将完全由外部电路决定,因此,CPU可以在“输入数据寄存器”读到外部电路的信号,而不是它自己输出的逻辑“1”。所以不需要去将IO口的模式配置成输入模式

这也就造成了上面两个代码的差异。

上拉电阻:查看F4的中文参考手册可以知道
在这里插入图片描述
IO口配置成上拉的时候可以解决推挽输出输出高电平时高阻态没办法拉高电平的情况。

注意:
使用开漏输时,如果需要读取电平值,最好输出高电平,由于N-MOS管处于关闭状态,I/O端口的电平将完全由外部电路决定,这时读到的才是外部电路的电平值。

每个线上加了4.7K的上拉电阻【上拉电阻具体数值需要计算和测试,基本选择10K往下】

对于MCU和EE单对单的:1.SCL并不是加了上拉电阻就得用推挽输出;2.SCL可以用推挽也可以用开漏,SDA必须用开漏输出;3.对于主从电平不一致的情况,SCL需要做上拉用开漏,将电平拉到从电平。

不会存在所谓的线与,IO口短路。SDA采用推挽,有可能会出现高电平被下拉,大概率是驱动负载过大的原因。

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

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

相关文章

RabbitMQ工作流程详解

1 生产者发送消息的流程 (1)生产者连接RabbitMQ&#xff0c;建立TCP连接(Connection)&#xff0c;开启信道(Channel) (2)生产者声明一个Exchange (交换器)&#xff0c;并设置相关属性&#xff0c;比如交换器类型、是否持久化等 (3)生产者声明一个队列井设置相关属性&#xf…

2023国赛数学建模B题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

2023国赛数学建模A题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

安卓:网络框架okhttp

目录 一、okhttp介绍 1. OkHttpClient类&#xff1a; 常用方法&#xff1a; 2. Request类&#xff1a; 常用方法&#xff1a; 3. Response类&#xff1a; 常用方法&#xff1a; 4. Call类&#xff1a; 常用方法&#xff1a; 5. Interceptor接口&#xff1a; 常用方法&…

Web 服务器 -【Tomcat】的简单学习

Tomcat1 简介1.1 什么是Web服务器 2 基本使用2.1 下载2.2 安装2.3 卸载2.4 启动2.5 关闭2.6 配置2.7 部署 3 Maven创建Web项目3.1 Web项目结构3.2 创建Maven Web项目 4 IDEA使用Tomcat4.1 集成本地Tomcat4.2 Tomcat Maven插件 Tomcat 1 简介 1.1 什么是Web服务器 Web服务器是…

【MySQL】并发执行事务可能存在的问题, 事务的四种隔离级别

文章目录 前言一、并发执行事务可能存在的问题1, 脏读问题2, 不可重复读3, 幻读 二、MySQL 的四种隔离级别1, READ UNCOMMITTED 读未提交2, READ COMMITTED 读已提交3, REPEATABLE READ 可重复读 (MySQL 的默认事务隔离级别)4, SERIALIZABLE 串行化 总结 前言 各位读者好, 我是…

Mac如何打开隐藏文件中Redis的配置文件redis.conf

Redis下载(通过⬇️博客下载的Redis默认路径为&#xff1a;/usr/local/etc) Redis下载 1.打开终端进入/usr文件夹 cd /usr 2.打开/local/文件夹 open local 3.找到redis.conf并打开,即可修改配置信息

MATLAB算法实战应用案例精讲-【图像处理】图像分类模型Swin TrasnformerViT

目录 Swin Trasnformer 1. 模型介绍 2. 模型结构 3. 模型实现 4. 模型特点 5. 模型效果 ViT( Vision Transformer) 模型介绍 模型结构与实现 1. 图像分块嵌入 2. 多头注意力 3. 多层感知机&#xff08;MLP&#xff09; 4. DropPath 5. 基础模块 6. 定义ViT网络 …

gulimall-缓存-缓存使用

文章目录 前言一、本地缓存与分布式缓存1.1 使用缓存1.2 本地缓存1.3 本地模式在分布式下的问题1.4 分布式缓存 二、整合redis测试2.1 引入依赖2.2 配置信息2.3 测试 三、改造三级分类业务3.1 代码改造 四、高并发下缓存失效问题4.1 缓存穿透4.2 缓存雪崩4.3 缓存击穿 五、分布…

零售行业供应链管理核心KPI指标(一) – 能力、速度、效率和成本

有关零售行业供应链管理KPI指标的综合性分享&#xff0c;涉及到供应链能力、速度、效率和成本总共九大指标&#xff0c;是一个大框架&#xff0c;比较核心也比较综合。 衡量消费品零售企业供应链管理效率和水平的核心KPI通常有哪些&#xff1f; 图片来源-派可数据&#xff08;…

OPENCV C++(十二)模板匹配

正常模板匹配函数 matchTemplate(img, templatee, resultMat, 0);//模板匹配 这里0代表的是方法&#xff0c;一般默认为0就ok img是输入图像 templatee是模板 resultmat是输出 1、cv::TM_SQDIFF&#xff1a;该方法使用平方差进行匹配&#xff0c;因此最佳的匹配结果在结果为…

【java】递归

java递归 递归的概念求135...19求阶乘 递归的概念 所谓的递归就是&#xff0c;方法调用自身&#xff0c;称之为递归方法 求135…19 public class Java16_Object_Recursion {public static void main(String[] args) {// 1 3 5 7 9... 19int result computeAP( 10 );Sys…

【移动机器人运动规划】04 ——轨迹生成

文章目录 前言相关代码整理: 介绍Minimum Snap OptimizationDifferential Flatness(微分平坦)Minimum-snapSmooth 1D TrajectorySmooth Multi-Segment TrajectoryOptimization-based Trajectory Generation Convex Optimization&#xff08;凸优化&#xff09;凸函数和凸集凸优…

第3章:线性模型

线性回归 优点&#xff1a;简单、基本、可理解性好。 适用于处理数值型数据。编码&#xff1a;序关系&#xff08;衣服号码s、m、l等等&#xff09;独热编码&#xff08;00010&#xff09; 求解 求偏导让导数为0&#xff1f;为什么&#xff1f; 希望找到极值点&#xff0c;即…

vector【1】介绍与使用(超详解哦)

vector 引言vector介绍接口使用默认成员函数迭代器容量元素访问数据修改 总结 引言 在string部分&#xff0c;我们详细的介绍了各个接口的使用&#xff0c;虽然其不属于STL的一部分&#xff0c;但是接口与STL中的容器相似&#xff0c;所以我们在学习使用vector等STL容器的使用…

最强自动化测试框架Playwright(7)- 使用cookie避免重复登录

playwright在称为浏览器上下文的隔离环境中执行测试。这种隔离模型提高了可重复性&#xff0c;并防止了级联测试失败。测试可以加载现有的经过身份验证的状态。这消除了在每次测试中进行身份验证的需要&#xff0c;并加快了测试执行速度。 每次测试前登录 以下示例登录到 Git…

工单管理系统有什么优点?工单系统是如何提高企业服务质量和运营效率的?

工单管理系统是一款基于云平台打造的高效报修工单管理系统&#xff0c;为企业报修管理、维保流程优化和后勤决策分析提供全面支持。通过应用工单管理系统&#xff0c;企业能够轻松提升报修效率&#xff0c;降低人工成本&#xff0c;同时提高后勤管理的质量和效益。系统利用先进…

【数据结构•堆】堆排序(理论基础)

堆的定义  • 堆是一个完全二叉树   –所有叶子在同一层或者两个连续层   –最后一层的结点占据尽量左的位置  • 堆性质   –为空, 或者最小元素在根上   –两棵子树也是堆 存储方式  • 最小堆的元素保存在heap[1..hs]内   – 根在heap[1]   –K的左儿子是2k,…

C++语法中bitset位图介绍及模拟实现

一、位图的引入 先来看下边一道面试题&#xff1a; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。 经过我们之前的学习&#xff0c;我们可能会有以下的思路&#xff1a; 对这些数进行排序&#xff…

Openlayers实战:列表与图层双向信息提示

在Openlayers的实际项目中,经常会在左侧列出信息列表,右边的地图上显示的是对应的图层内容,两边是一一对应的,为了看出来选择的是哪一个,就需要两边互相提示,本示例就很好的展示了这种效果,具体的方法请参考源代码。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhu…