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

ADC和GPIO的关系

总结:

ADC:模拟输入,输入连续的信号,也就是一个连续变化的电压值,将他们转换成一个数字代码(比如说12位二进制数),需要借助GPIO引脚,因为ADC位于芯片内部,需要GPIO引脚与外界连接。

GPIO:数字输入,输入离散的信号,整个过程只需要知道高低(比如说LED亮灭,按键开关),将他们转换成0 1,不需要ADC参与。

物理上ADC,和GPIO是一个二选一的过程,一个时间只能使用一个,如果非要一起使用,可以用分时复用。

 

二、特殊场景:如何“既使用ADC又使用GPIO数字功能”

虽然不能同时使用,但我们可以通过分时复用的方式,在不同时间让同一个引脚服务于不同的目的。这就需要程序来动态地切换GPIO的模式。

场景一:智能省电的传感器读取

这是一个非常经典的应用。

  1. 需求:一个电池供电的设备,连接了一个耗电量较大的模拟传感器(比如某些气体传感器)。你只需要在特定条件下才读取它的高精度模拟值。

  2. 操作

    • 大部分时间:将引脚配置为数字输入。你可以用一个简单的GPIO_ReadPin()来持续、快速地、低功耗地监测这个引脚的电平。

    • 当数字输入检测到某种变化(例如,引脚电平变高,表示“有事件发生”)时,软件动态地将引脚模式重新配置为模拟输入

    • 然后启动ADC,进行一次精确的电压测量,获取详细的数据。

    • 测量完成后,再次将引脚配置回数字输入模式,继续低功耗监控。

  3. 好处:极大地降低了系统功耗。数字输入电路的功耗远低于让ADC持续工作的功耗。

代码逻辑示意:

c
// 初始化:先配置为数字输入,用于唤醒监测
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(SENSOR_GPIO_Port, &GPIO_InitStruct);while(1) {// 低功耗模式,等待数字信号唤醒if (HAL_GPIO_ReadPin(SENSOR_GPIO_Port, SENSOR_Pin) == GPIO_PIN_SET) {// 切换到模拟模式进行精确测量GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(SENSOR_GPIO_Port, &GPIO_InitStruct);HAL_ADC_Start(&hadc);value = HAL_ADC_GetValue(&hadc); // 获取ADC值HAL_ADC_Stop(&hadc);// 处理ADC数据...// 处理完后,切回数字输入模式,继续监听GPIO_InitStruct.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(SENSOR_GPIO_Port, &GPIO_InitStruct);}
}

场景二:硬件故障诊断或通道切换

  • 需求:系统有多个信号源可能连接到同一个ADC通道(通过外部模拟开关选择)。你需要先确认哪个信号源是“活跃的”(有电压)。

  • 操作

    1. 先配置为数字输入,快速扫描所有可能的来源。如果读到高电平,说明那条线路上有信号。

    2. 然后控制外部模拟开关,将那条“活跃的”线路接通。

    3. 最后再将MCU引脚切换为模拟输入,进行精确的ADC采样。

场景三:识别设备类型(不常见但很巧妙)

  • 需求:一个接口可以插入两种设备:一种输出数字信号(如开关),一种输出模拟信号(如电位器)。

  • 操作

    1. 先配置为数字输入并上拉。读取引脚状态。

    2. 如果读到的值是稳定的01,则判断为数字设备。

    3. 如果读到的值不稳定(因为模拟电压可能处在数字门槛电压附近,导致读值抖动),或者不符合数字特征,则切换为模拟输入,读取ADC值来判断是哪种模拟设备。


重要提醒

  1. 模式切换有开销:频繁在数字和模拟模式之间切换会消耗CPU时间,并且配置GPIO模式本身需要几个时钟周期。

  2. 稳定性:切换后需要一小段时间的稳定(通常很短,但需考虑),让内部电路稳定到新的状态,才能进行可靠的ADC采样或数字读取。

  3. 外设影响:切换模式时,要确保ADC没有正在对该通道进行采样,否则可能导致采样错误。

结论

有没有既需要ADC又需要GPIO输入功能的情况?

  • 从“同时”的角度看:没有。 硬件上不允许。

  • 从“在同一个引脚上分时实现两种功能”的角度看:有! 这是一种高级的嵌入式设计技巧,常用于智能省电、故障诊断和接口复用等场景。它体现了软件和硬件协同工作的灵活性。

http://www.hskmm.com/?act=detail&tid=11750

相关文章:

  • 使用Docker Compose工具进行容器编排的教程
  • 模拟输入的过程
  • 基于Redisson和自定义注解的分布式锁实现策略
  • CCPC2025网络赛 游记
  • 知行合一
  • Manim实现水波纹特效
  • 深入解析:解锁AI智能体:上下文工程如何成为架构落地的“魔法钥匙”
  • JS之使用for...of赋值失败的原因分析
  • String
  • Linux /lib/modules/$(uname -r)/ 目录功能作用详解
  • 《建筑的永恒之道》第 27 章:道之核心
  • 软件工程第二次作业_个人项目
  • Linux命令大全(档案管理)
  • 小狼毫雾凇拼音安装部署
  • Chapter 3 Resize and Cropping
  • 详细介绍:java中常见的几种排序算法
  • 使用FFmpeg转换m4a
  • 提升多屏监控体验/新增辅屏预览功能/轻松实现跨屏实时监控/支持高达500路多个屏幕同时显示
  • [Java SE/文件系统/IO] 核心源码精讲:java.io.File
  • Linux 内核整体架构详解
  • atoi() - 字符串( ASCLL )转换为整数( int )
  • 02.Python:Flash初步使用
  • 解决Kubernetes集群中master节点无法与node节点通信的策略
  • 从高版本的sqlserver向低版本的sqlserver上复制表和数据的方法
  • 在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境
  • 【php】带数组的文件列表生成,返回数组
  • 配置Nginx以支持Websocket连接的方法
  • Extundelete工具恢复数据
  • 重新理解12306:它卖的从来不是“库存”,而是“状态”
  • 基于Python+Vue开发的房产销售管理系统源码+运行步骤