本帖最后由 Zhao_kar 于 2025-3-18 21:34 编辑
【STM32 H533RE】测评四_ADC和常见模拟输出模块的测试
备注:本节讲一下ADC的基本原理,以及cubemx部分如何进行单片机自带adc的基本配置,然后会用一个光照度计的模块,这个模块可以做模拟输出也可以做数字输出,这边会用模拟输出,然后adc采集信号,最后读出照度值。然后基于此可以进阶,比如开dma,然后采集波形,打印串口去显示也是可以的。
一、ADC的基本原理
1、本文以单片机自带的12位3.3v的adc为例子进行说明
首先是精度的概念,12位adc,也就是2的12次方,所以是4096,然后我们单片机的电压采集范围是0-3.3v,所以把这个分成4096层,算出来结果就是0.0008v一档,这个就是分辨率的概念,也就是说这个adc只能区分这个范围内的参数,比如0v的时候adc返回0,那么0.0008返回就是1,但是你要想区分0.004那就行不通了。了解了基础概念之后,直接给出一个公式

这边举个例子比较通俗易懂,比如adc测一个1.65v的电压,那么adc会返回一个数字信号给mcu,也就是4096乘0.5等于2048,那么单片机会接受到这个数字,然后再通过单片机编程就可以得到电压值。
然后采样率的概念也比较简单,比如一个1s的sin波,对他进行采样的话,我们是按照点来采集的,比如你用0,1s的采样率,那么1s的sin波你就可以采集到十个点,以此类推,为了得到更多的点,比如1s波形,1hz,你想采集100个点,尽可能复现波形,那么就用100hz的adc采样率来进行采集就可以了。然后这里会涉及一个特殊情况,当你的单片机频率不足以采集到高频的信号的时候,比如你的单片机最快也就2Mhz的采样,一个50mhz的波形压根不能采集,这个时候就有其他方法了,比如使用专门的adc模块,然后用iic或者spi通信与单片机通信;也可以用特俗采样方法来进行采集,也可以换性能更好的单片机(比较少用),一般都是有专门的adc来干这个事情的
二、cubemx部分配置
基础配置和串口部分就不细说了,之前有讲过,配置完之后直接来adc部分
这里可以使用定时器来触发,不过我这边只是做个小测试,就拿默认软件触发,然后选择之后可以看到右边的pa0打开
然后是时钟部分的设置,h5的时钟树和f4和f1有点不太一样,不过无所谓,时钟配置根据需求来就行,我这边就随便设个50,都行。
然后勾选配置,generate
生成之后就可以写代码了,接下来到第三部分
三、代码编写和函数使用
在编写代码之前,我们需要了解一个大致流程,我们要做的操作首先是设置一个函数变量,用来存adc采集到的电压值,然后我们要做adc的初始化,这一部分hal会自带,然后我们要做adc的校准,校准之后流程基本不变,如启动adc转换,然后等待转换,之后我们再把转换后的函数赋值给变量,最后把变量的参数打印出来看。
然后这部分不是死的,比如用dma的时候,那么就是HAL_ADC_Start_DMA这个函数,我们这边不需要,直接HAL_ADC_Start(&hadc1);这个函数就可以,代码如下
-
- HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
-
-
-
- HAL_ADC_Start(&hadc1);
- HAL_ADC_PollForConversion(&hadc1, 50);
-
-
- if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
- {
- ADC_Value = HAL_ADC_GetValue(&hadc1);
- printf("ADC1: %d \r\n",ADC_Value);
- printf("V: %.4f \r\n",ADC_Value*3.3f/4096);
- }
- HAL_Delay(2000);
-
- }
然后这里有一个地方要补充,关于下面这个校准函数,请自己去查看定义,每一代32芯片的库不是一样的
- HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
比如你在f1里面,压根就不需要这么复杂,他只需要这样
- HAL_ADCEx_Calibration_Start(&hadc1);
这边主要是adc配置部分,你想有一个单端输入 还是 差分输入,而h5会支持查分,所以这一部分需要说明,具体看下面
这边我只放一部分,stm32h5xx_hal_adc_ex.c你在这个文件即可找到,然后看一下函数就知道怎么用了
-
- HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
- {
- HAL_StatusTypeDef tmp_hal_status;
- __IO uint32_t wait_loop_index = 0UL;
-
-
- assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
- assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
配置完之后,我们来看一下实物图片。
补充一个东西:因为我的ide出了点问题,暂时没办法烧录,还没解决,为了演示,这边教大家使用别的烧录方法,下载programmer,也就是下面这个,可以直接把编译文件放进去烧录
实物就是一个光照度计,然后这个模块会根据不同照度输出adc值,强的时候大,我们接线部分只需要把模拟输出部分接到单片机的adc上即可,具体实物图片和视频放在最后,这边补一下串口接收到的值。
可以看到一开始值很小,然后把手机手电筒凑上去之后值会变大。
详细的视频见下,拍了两个小视频,一个打开手电筒后,可以明显看到值会变大。
播放器加载失败: 未检测到Flash Player,请到
安装
2
播放器加载失败: 未检测到Flash Player,请到
安装
1