单片机入门---ADC采样

51单片机+ADC0809数字电压表Proteus仿真:从零搭建到精度调优(附完整代码) 本文详细介绍了使用51单片机和ADC0809模数转换器构建数字电压表的完整过程,包括硬件连接、软件编程和精度调优。通过Proteus仿真实现0-5V电压测量,精度可达0.01V,适合嵌入式初学者学习模拟信号采集与数字处理技术。附完整代码,帮助开发者快速掌握数字电压表的设计与实现。 阅读详情

ADC:analogy-digital converter 模拟-数字转换器。
首先可以参考这篇文章,对ADC采样有个正确的认识。https://blog.youkuaiyun.com/euxnijuoh/article/details/81066739

在ADC的初始化过程中,有两个很有意思的参数:

  hadc.Init.ContinuousConvMode = DISABLE;
  hadc.Init.DiscontinuousConvMode = ENABLE;

按照字面意思,我们会认为如果选择相反的设定的话,这两个功能不就是完全相同的吗?然鹅,实际上并不是这样的。下面我们从代码入手,结合寄存器描述来看一下:

  /* Configuration of ADC:                                                    */
  /*  - Resolution                                                            */
  /*  - Data alignment                                                        */
  /*  - Scan direction                                                        */
  /*  - External trigger to start conversion                                  */
  /*  - External trigger polarity                                             */
  /*  - Continuous conversion mode                                            */
  /*  - DMA continuous request                                                */
  /*  - Overrun                                                               */
  /*  - AutoDelay feature                                                     */
  /*  - Discontinuous mode                                                    */
  hadc->Instance->CFGR1 &= ~(ADC_CFGR1_ALIGN   |
                             ADC_CFGR1_SCANDIR |
                             ADC_CFGR1_EXTSEL  |
                             ADC_CFGR1_EXTEN   |
                             ADC_CFGR1_CONT    |
                             ADC_CFGR1_DMACFG  |
                             ADC_CFGR1_OVRMOD  |
                             ADC_CFGR1_AUTDLY  |
                             ADC_CFGR1_AUTOFF  |
                             ADC_CFGR1_DISCEN   );
  
  hadc->Instance->CFGR1 |= (hadc->Init.DataAlign                             |
                            ADC_SCANDIR(hadc->Init.ScanConvMode)             |
                            ADC_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)    |
                            ADC_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests) |
                            hadc->Init.Overrun                               |
                            __HAL_ADC_CFGR1_AutoDelay(hadc->Init.LowPowerAutoWait) |
                            __HAL_ADC_CFGR1_AUTOFF(hadc->Init.LowPowerAutoPowerOff));
  
  /* Enable external trigger if trigger selection is different of software  */
  /* start.                                                                 */
  /* Note: This configuration keeps the hardware feature of parameter       */
  /*       ExternalTrigConvEdge "trigger edge none" equivalent to           */
  /*       software start.                                                  */
  if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
  {
    hadc->Instance->CFGR1 |= hadc->Init.ExternalTrigConv |
                             hadc->Init.ExternalTrigConvEdge;
  }
  
  /* Enable discontinuous mode only if continuous mode is disabled */
  if (hadc->Init.DiscontinuousConvMode == ENABLE)
  {
    if (hadc->Init.ContinuousConvMode == DISABLE)
    {
      /* Enable the selected ADC group regular discontinuous mode */
      hadc->Instance->CFGR1 |= (ADC_CFGR1_DISCEN);
    }
    else
    {
      /* ADC regular group discontinuous was intended to be enabled,        */
      /* but ADC regular group modes continuous and sequencer discontinuous */
      /* cannot be enabled simultaneously.                                  */
      
      /* Update ADC state machine to error */
      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
      
      /* Set ADC error code to ADC peripheral internal error */
      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
    }
  }

上 面 是 stm32l0xx_hal_adc.c 文 件 中 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);函数的定义,这个函数中对配置寄存器ADC configuration register 1 (ADC_CFGR1)进行了设置。从上面的代码中可以看到:

hadc->Instance->CFGR1 &= ~(ADC_CFGR1_ALIGN |
ADC_CFGR1_SCANDIR | ADC_CFGR1_EXTSEL | ADC_CFGR1_EXTEN | ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | ADC_CFGR1_OVRMOD | ADC_CFGR1_AUTDLY | ADC_CFGR1_AUTOFF | ADC_CFGR1_DISCEN );

首先清除了bit16,即ADC_CFGR1_DISCEN 。
从spec上看,此处的定义在CFGR1寄存器中表述如下:
在这里插入图片描述
可以看到如果设定为0的情况下是关闭了非连续模式。但是并没有打开连续采样模 式。接着往下看代码

hadc->Instance->CFGR1 |= (hadc->Init.DataAlign		| ADC_SCANDIR(hadc->Init.ScanConvMode)	| ADC_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) | ADC_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests) | hadc->Init.Overrun	|
    HAL_ADC_CFGR1_AutoDelay(hadc->Init.LowPowerAutoWait) |
    HAL_ADC_CFGR1_AUTOFF(hadc->Init.LowPowerAutoPowerOff));

此处对ContinuousConvMode这个参数进行了解读和设置,设置部分的代码如下:

/**
*@brief Enable ADC continuous conversion mode.
*@param _CONTINUOUS_MODE_ Continuous mode.
*@retval None
*/
#define ADC_CONTINUOUS(_CONTINUOUS_MODE_) ((_CONTINUOUS_MODE_) << 13U)

可以看出是对bit13进行了设置,而对这个寄存器的描述在spec中表述如下:
在这里插入图片描述

从以上描述中可以看出,这个位是单次转换还是连续直到被清除。也就是这样的设置 跟是否连续设置是没有关系的。是两个完全不同的寄存器的设置。但是两处的描述中 都明确提示不能同时设置两个寄存器为1。
接着往下看,

/* Enable discontinuous mode only if continuous mode is disabled */ if (hadc->Init.DiscontinuousConvMode == ENABLE)
{
if (hadc->Init.ContinuousConvMode == DISABLE)
{
/* Enable the selected ADC group regular discontinuous mode */ hadc->Instance->CFGR1 |= (ADC_CFGR1_DISCEN);
}
else
{
/* ADC regular group discontinuous was intended to be enabled,	*/
/* but ADC regular group modes continuous and sequencer discontinuous */
/* cannot be enabled simultaneously.	*/

/* Update ADC state machine to error */
SET_BIT(hadc->State,   HAL_ADC_STATE_ERROR_CONFIG);

/* Set ADC error code to ADC peripheral internal error */ SET_BIT(hadc->ErrorCode,   HAL_ADC_ERROR_INTERNAL);
}
}

上面的代码有意思的是,你不能够在cubeMX同时设置如下两个参数,但是如果你采 用人工手写代码的方式可以同时enable这两个参数,这时候就走到上面代码的else 分支中,会设定错误状态。
在这里插入图片描述

如何使用ADC获取正确的值呢?
首先在使用前,对ADC进行一下校准:

HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
for (i = 0; i < 10; i++) {
		  HAL_ADC_Start(&hadc);
		  HAL_ADC_PollForConversion(&hadc, 10);

		  if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC)) {
			  ADC_Buf[i] = HAL_ADC_GetValue(&hadc);
		  }
	  }
STM32L051的ADC的ContinuousConvMode和DiscontinuousConvMode的理解 先上ADC配置函数: /* ADC init function */ void MX_ADC_Init(void) { ADC_ChannelConfTypeDef sConfig; /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conver... 阅读详情

相关推荐

STM32CubeIDE STM32H743实现TIM定时触发ADC实现多通道DMA方式采样

STM32CubeIDE STM32H743实现TIM定时触发ADC实现多通道DMA方式采样1. ADC设置2. DMA设置3. TIM设置4. 代码如下:5. 测试代码6. 说明1. ScanConvMode2. ContinuousConvMode3. DiscontinuousConvModeNbrOfDiscConversionExternalTrigConvExternalTrigConvEdgeConversionDataManagement 在STM32CubeIDE 1.4.0环境下测试通过

TrueLink的博客 9367

STM32 ContinuousConvMode和DiscontinuousConvMode的组合方式

ContinuousConvMode ,DiscontinuousConvMode这两个参数,乍一看只需要一个就好了,只要决定是不是连续转换就可以了。但实际上这两个参数是为了配置出更多的模式。公式:Vref = (1.2 / (adc_vref / 4095 * 3.3)) * 3.3。其中adc_vref为adc内部参考电压通道的数值。实际电压 = Vref * Vch / 4095。(Vch是通道采集的adc的值)

qq_25727979的博客 3370

STM32 hal库使用笔记(五)ADC—单通道/双通道DMA传输

STM32 hal库使用ADC—单通道/双通道DMA传输的简单测试,串口打印。

hdh546的博客 4280

STM32F1xx HAL库 中文详解 之 ADC篇

本文主要从ADC中用到的结构体、函数以及用法讲解。 一、结构体 1.ADC_InitTypeDef typedef struct { uint32_t DataAlign uint32_t ScanConvMode uint32_t ContinuousConvMode uint32_t NbrOfConversion uint32_t DiscontinuousConvMode uint32_t NbrOfDiscConversion uint32_t Extern

逆行者Fy的博客 1万+

STC8G1K08单片机ADC从入门到精通:配置、滤波与多通道采样实战

模数转换器(ADC)是嵌入式系统中连接模拟世界与数字世界的核心接口,其原理基于对连续模拟信号的采样与量化。在单片机应用中,内置ADC模块能有效简化硬件设计,其技术价值在于以低成本实现传感器信号、电池电压等关键参数的数字化采集。对于广泛使用的51内核单片机,如STC8G1K08,掌握其ADC的稳定驱动与性能优化是嵌入式开发的基础技能。本文聚焦于**ADC采样**的工程实践,深入探讨**参考电压**选择、软件滤波算法实现以及多通道轮询等关键应用场景,旨在提供一套从寄存器配置到系统级优化的完整解决方案,帮助开发者

weixin_29195615的博客 229

第20.2章-电磁杆在磁轨道的测试 零基础入门智能车竞赛 智能车竞赛 电磁杆原理图 电磁循迹小车 智能车电磁组 STM32电磁小车 电磁循迹小车 电磁循迹算法 智能车环岛 智能车比赛规则 智能车竞赛

V3.3.0-STM32智能小车视频:

m0_46373735的博客 1208

ADC采样原理入门:单片机如何读取模拟信号

由于多通道扫描会产生大量数据,工程上几乎总是配合DMA使用——ADC每转换完一个通道,DMA就自动把结果搬运到内存数组里,等全部通道都转换完毕,CPU直接去数组里取数就行了,全程几乎不需要CPU插手。在单片机内部,ADC是一个外设模块(就像定时器、串口一样),它接收引脚上的模拟电压(通常是0V ~ 3.3V或0V ~ 5V),经过一系列内部处理,最终输出一个整型数字(比如0、1024、2048、4095),供CPU读取和使用。分辨率越高,测量越精细,另外分辨率越高,转换时间通常越长,成本和功耗也越高。

teach2004的博客 212

从光敏电阻到数码管:51单片机驱动ADC0804实现环境光照实时监测

本文详细介绍了如何使用51单片机驱动ADC0804模数转换器和光敏电阻实现环境光照强度的实时监测,并通过数码管显示结果。从硬件选型、电路设计到软件逻辑和数据处理,提供了完整的解决方案和优化技巧,适合电子爱好者学习和实践。

weixin_29163857的博客 163

基于51单片机数字电压表设计(Proteus仿真+Keil源码等)adc0809 附下载链接!

设计一个基于51单片机数字电压表的设计,通过控制单片机,实现adc0809模数转换,数码管显示。

wangpan0330的博客 386

用STC89C52单片机+ADC0832做个智能台灯:从光敏电阻采集到PWM调光的保姆级教程

本文详细介绍了如何使用STC89C52单片机和ADC0832模数转换器制作智能光控台灯,涵盖硬件搭建、固件开发和系统调试全流程。通过光敏电阻采集环境光线,结合PWM调光技术实现自动亮度调节,提供从原理图设计到代码实现的保姆级教程,助力电子爱好者掌握智能家居开发核心技能。

weixin_30689307的博客 204

51单片机高精度电流测量方案:ADS1110与串口通信实战

在嵌入式系统与物联网应用中,电流测量是监测设备功耗、电池状态及系统健康的关键技术。其核心原理基于欧姆定律,通过采样电阻将电流信号转换为电压信号,再经模数转换器(ADC)量化处理。高精度ADC技术,如16位Δ-Σ架构,能显著提升测量分辨率与稳定性,解决传统方案中读数跳变、量程不足等痛点。结合串口通信,可实现数据的可靠传输与远程监控,极大拓展了在智能硬件、毕业设计及工业监测等场景的应用价值。本文以51单片机驱动ADS1110 ADC芯片为例,深入解析I2C通信配置与采样电阻选型,并融入串口数据传输协议设计,为构

weixin_34121304的博客 324

20.2-电磁杆在磁轨道的测试 零基础入门智能车竞赛 智能车竞赛 电磁杆原理图 电磁循迹小车 智能车电磁组 STM32电磁小车 电磁循迹小车 电磁循迹算法 智能车环岛 智能车比赛规则 智能车竞赛

**功能介绍放开头, 使用便捷无需愁。** **这是全网最详细、性价比最高的STM32实战项目入门教程,通过合理的硬件设计和详细的视频笔记介绍,硬件使用STM32F103主控资料多方便学习,通过3万字笔记、12多个小时视频、20多章节代码手把手教会你如何开发和调试。让你更快掌握嵌入式系统开发。** **从焊接组装->LED点灯->FreeRTOS带您从零完成 循迹、避障、跟随、遥控、PID速度控制、PID循迹、角度闭环控制、视觉循迹、FreeRTOS、电磁循迹等等还在更新中...**

2501_91769822的博客 798

51单片机+ADS1110打造高精度电流表:从I2C通信到串口数据采集全解析

在嵌入式系统与数据采集领域,模数转换器(ADC)是将现实世界连续模拟信号转换为数字系统可处理离散数据的关键器件。其工作原理基于采样与量化,通过逐次逼近或Δ-Σ等技术实现高精度转换。ADC的技术价值在于为微控制器(MCU)提供了感知电压、电流、温度等物理量的能力,是物联网节点、智能仪表和工业控制系统的感知前端。典型应用场景包括传感器信号采集、电池管理系统和精密测量仪器。本文聚焦于**高精度ADC**与经典**51单片机**的协同应用,详细阐述了如何利用ADS1110这款16位Δ-Σ ADC芯片,通过I2C总线

weixin_34163553的博客 316

51单片机实验箱系统+LabVIEW虚拟仪器综合实验平台一体化系统面向实验教学实验优势和特点

比如在ADC采集实验中,传统实验只能通过数码管看到离散的电压数值,而搭配LabVIEW后,学生可以直接在屏幕上看到连续变化的电压波形,直观理解采样率、量化误差这些核心概念,调试时不用反复烧录程序,直接在界面上就能调整参数观察效果,单节实验课的有效实操效率能提升60%以上。创新实践阶段:模块化的硬件设计加上LabVIEW的快速开发能力,学生可以在短时间内完成智能温控系统、环境监测站、小型工业测控平台这类课程设计、电子竞赛项目,不用把大量时间耗费在底层驱动和界面开发上,能把精力集中在创新方案的验证上。

185

[CH582M入门第三步]ADC配置

ADC名为模数转换,也是单片机最基础的东西。尤其是做电压电流采样这样项目。这就是CH582M的ADC的一些基本配置。对比STM32来说配置还是很简单的。

sinat_58149788的博客 1519

STC89C52单片机+ST7565驱动12864液晶屏的实时波形显示方案

提供一套可直接上手的51单片机简易示波器实现方案,核心控制器为STC89C52,搭配ST7565芯片驱动128×64点阵LCD12864液晶屏,支持模拟信号采集与实时波形刷新显示。资源包内含完整硬件设计文件(原理图.SchDoc、PCB.PcbDoc)、Keil uVision工程(含main.c及LCD驱动代码)、编译配置文件(.uvproj/.uvopt)、调试批处理脚本(keilkilll.bat)以及详细说明文档(ss.md)。所有代码已在真实硬件平台验证通过,无需修改即可烧录运行;PCB采用标准双

nginx7reverse的博客 212

单片机——ADC采样

ADC是指将模拟信号转换成数字信号的过程。通俗理解ADC采样就是采集电路中的电压,通过数值的方式表现出来。以STM32F103系列为例,它可以反应0~4095,换句话说,它采集的电压数值上表现为0~4095,也就是12位ADC(2^12)。

nolate_chen的博客 2万+

养龙虾经验:OpenClaw用户必看的3个“省token”救命配置

本文分享了3个优化OpenClaw使用成本的配置方案:1)启用上下文压缩功能,可选择全局或单个代理设置,支持safeguard/adaptive两种压缩模式;2)修改SOUL.md提示词,要求模型回答简洁直接;3)限制对话历史长度。方案一效果最佳,可减少长对话的token消耗,但可能影响连贯性。三种方案可单独或组合使用,需根据实际场景调整参数。文章最后邀请读者分享使用痛点,将针对高频问题撰写解决方案。

wpplvhq的专栏 1418

单片机ADC采样算法----有效值采样法

在使用单片机ADC功能采样数据时,通常情况下用平均值计算就够了,但是在计算功率时就需要用有效值来计算真正做功的情况。如果是标准的正弦波的话,正弦波的峰值是有效值得1.414倍,可以通过峰值来计算有效值。但是实际应用中波形往往会发生畸变,如果按照1.414这个比例计算的话,误差往往会比较大。所以必须通过计算正弦波的面积来求有效值。 有效值又叫均方根值,对数据的平方和取平...

HXYDJ的博客 3万+

快速了解Spyder

一 面板介绍菜单栏:放置所有功能工具栏:放置快捷菜单,可以通过菜单栏中的View的Toolbars的复选框来勾选工作区:写代码的地方属性页的标题栏:可以显示当前代码的名字和位置查看栏:查看文件、调试时的对象及变量输出栏:查看程序的输出信息,也可以作为shell终端来输入Python语句状态栏:用来显示当前文件权限、编码,光标指向位置和系统内存二 注释功能注释功能为编写代码很常用功能,下面介绍Spy...

实践求真知 1万+

如何利用VS2017创建一个简单的窗口

#如何利用VS2017创建一个简单的窗口 1、新建->Windows桌面向导 2、应用程序类型->桌面应用程序,点击确定 3、点击调试->开始调试 可建立如下图的窗口 4、可以在生成的项目文件的中找到windows17_2的应用程序,打开界面如下: 注:新建空白项目也可以,注意在解决方案资源器中添加.cpp文件,如源.cpp文件,下载代码见博文 ...

weixin_46894139的博客 2914
上一篇: 单片机入门---最重要的外设控制(GPIO)
下一篇: 单片机入门---I2C通信
野-百-合
博客等级 码龄17年 308粉丝 118原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值