本帖最后由 LiuDW091 于 2025-7-18 13:41 编辑
#每日话题# #申请原创# #有奖活动# #申请开发板#[url=home.php?mod=space&uid=760190]@21小跑堂 @21小跑堂
书接上回,这会来玩一玩ADC采集,中间遇到的问题、以及解决方面一并呈上。
一、首先通原理图、数据手册,找到自己需要的ADC端口,以及连接到的外部管脚
我这边选了ADC2的通道2,即ADC2_IN 2,对应的通道PC3
二、IDE软件开始配置
debug配置、RCC配置就不在累赘了,如果不会,可以看我前面的测评内容
ADC2配置如下:
1、ADCs_Common_Settings (ADC模式设置)
Mode ADC_Mode_Independent 设置为独立模式
独立模式模式下,每个ADC接口独立工作。
2、ADC_Settings ADC参数设置
Resolution(分辨率)
ADC精度选择,目前选12位,这与最后你计算ADC实际电压值有关。
Gain Compensation 补偿,补偿
Scan Conversion Mode( 扫描模式 ) DISABLE
目前只用了一个通道的话,DISABLE就可以了(也只能DISABLE),如果使用了多个通道的话,会自动设置为ENABLE,即开启扫描模式。
End Of Conversion Selection(结束转换的选择)
有End of single conversion(EOC) 与 End of sequence of conversion(EOS)两种选择。
这两个事件会触发中断与DMA。
选择EOS,代表等所有通道转换完毕后,产生中断后将全部数据取出来,或者使用DMA将全部数据取出来
Low Power Auto Wait (低功耗自动等待)
目前没用,禁止就行
Continuous Conversion Mode(连续转换模式) DISABLE就行
ENABLE,即连续转换。连续转换直到所有的数据转换完成后才停止转换。
DISABLE,即单次转换。只转换一次数据就停止,要再次触发转换才可以进行转换
Discontinuous Conversion Mode(间断模式) DISABLE
Overrun behaviour (溢出处理行为)
默认就好
Conversion Data Managerment Mode(转换数据管理模式)
默认就好
3、ADC Regular ConversionMode
Enable Regular Conversions (启用常规转换模式) ENABLE
使能它才能采集各个通道上的模拟量
Enable Regular Oversamping(使能规则过采样)默认禁止
Oversamping Ratio(过采样率) 默认
Number OF Conversion(转换通道数) 1
用到几个通道就设置为几
External Trigger Conversion Soure(触发转换的外部来源)软件触发就好
①Regular Conversion launched by software (软件触发)
②Timer 1 Capture Compare 1 event (定时器1捕获比较事件1)
③Timer 1 Capture Compare 2 event(定时器1捕获比较事件2)
等等等等
External Trigger Conversion Edge(触发转换的外部沿)
如果选择定时器,就需要选择此项,是上升沿还是下降沿以及上升下降沿
Left Bit Shift(左移位数)不需要
4、ADC Injected Conversion Mode ( ADC注入转换模式)先不管
5、Analog Watchdog 先不管
DMA配置如下:
NVIC配置如下:
配置好后,进行代码生成
三、代码调试
1、usart.c中增加如下代码
#include <stdio.h>
/* USER CODE BEGIN 1 */
#ifdef _GNUC_ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);//阻塞方式打印
return ch;
}
/* USER CODE END 1 */
2、main.c中增加如下代码
#include <string.h>
#include <stdio.h>
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //AD校准
HAL_ADC_Start(&hadc2); //启动ADC转换
HAL_ADC_PollForConversion(&hadc2, 50); //等待转换完成,50为最大等待时间,单位为ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2), HAL_ADC_STATE_REG_EOC))
{
ADC_Value = HAL_ADC_GetValue(&hadc2); //获取AD值
printf("21ic论坛ADC测试\r\n");
printf("ADC2 Reading(码值) : %d \r\n",ADC_Value);
printf("ADC2 Voltage(电压值) : %.1fv \r\n",ADC_Value*3.3f/4096);//除以4096是因为我们分辨率选的是12位,2的12次方即4096
}
HAL_Delay(1000);
四、踩坑
原来用过STM32F系列的,ADC校准是如下函数
HAL_ADCEx_Calibration_Start(&hadc2); //AD校准
写入此代码,编译报错,../Core/Src/main.c:99:3: error: too few arguments to function 'HAL_ADCEx_Calibration_Start'
99 | HAL_ADCEx_Calibration_Start(&hadc2); //AD校准
这就是经验主义害人
发现还需要添加个参数,于是度娘查询,代码如下,编译正常。
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //AD校准
将程序下载进入demo板,测量电压
串口数据如下:
返回查询代码,发现此处有点小问题,百度后得知是浮点数的问题。
解决措施如下:
代码正常:
重新下载即可
五、运行效果
视频如下:
代码:
代码Core.rar
(22.69 KB, 下载次数: 0)
致此,ADC实验结束。
这只是简单的ADC实现,如果觉得精度不够,还有在程序里面添加滤波算法。大家有兴趣可以自行添加。
|
|