【stm32】hal库学习笔记-ADC模数转换(超详细)
本篇章介绍了ADC实现电压检测的三种方式
ADC原理及选型
ADC将连续的模拟电压信号转换为二进制的数字信号
选型参数
速度(采样频率)
功耗
精度
转换原理
ADC hal库驱动函数
普通通道检测电压
CubeMX图形化配置
导入TFT_LCD配置(配置方法见上一篇博客)
时钟树配置
打开外部时钟
FSMC配置
ADC配置
将Time base的优先级调为0 打开中断
代码实现
/* USER CODE BEGIN 2 */
lcd_init();
// lcd_show_str(10, 40, 24, "ADC1-IN5 channel", RED);
// lcd_show_str(10, 70, 24, "Please set jumper at first", RED);
// lcd_show_str(10,100, 24, "Tune potentiometer for input", RED);
lcd_show_str(10,130, 24, "ADC 12-bits Value = ", RED);
lcd_show_str(10,190, 24, "Voltage(mV) = ", RED);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 200) == HAL_OK) {
uint32_t val = HAL_ADC_GetValue(&hadc1);
lcd_show_num(50, 160, val, 4, 24, RED);
uint32_t Volt = 3300 * val >> 12;
lcd_show_num(50, 220, Volt, 4, 24, RED);
}
//HAL_ADC_Stop(&hadc1);
HAL_Delay(500);
/* USER CODE END WHILE */
实现效果
每0.5秒采样一次(不精确)
外部中断触发检测电压
CubeMX图形化配置
打开外部中断触发
修改时钟树
设置TIM3
参数设置原理见博客定时器篇章
更改中断优先级
代码实现
/* USER CODE BEGIN 2 */
lcd_init();
lcd_show_str(10,160, 24, "ADC 12-bits Value = ", RED);
lcd_show_str(10,220, 24, "Voltage(mV) = ", RED);
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim3);
/* USER CODE END 2 */
重写回调函数
/* USER CODE BEGIN 4 */
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if (hadc->Instance == ADC1) {
uint32_t val = HAL_ADC_GetValue(&hadc1);
lcd_show_num(50, 190, val, 4, 24, RED);
uint32_t Volt = 3300 * val >> 12;
lcd_show_num(50, 250, Volt, 4, 24, RED);
}
}
/* USER CODE END 4 */
实现效果
每0.5秒采样一次(较精确)
DMA和多通道传输
设置三个输入通道
使用扫描转换模式
利用DMA方式传输数据
CubeMX图形化配置
DMA设置
ADC设置
代码实现
#define BATCH_DATA_LEN 3
uint32_t dmaDataBuffer[BATCH_DATA_LEN];
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
lcd_init();
// lcd_show_str(10, 40, 24, "Conversion triggered by", RED);
// lcd_show_str(10, 70, 24, "TIM3 with interval of 500ms", RED);
lcd_show_str(10,100, 24, "Channel 5 Voltage(mV) = ", RED);
lcd_show_str(10,160, 24, "Reference Voltage(mV) = ", RED);
lcd_show_str(10,220, 24, "Battery Voltage(mV) = ", RED);
HAL_ADC_Start_DMA(&hadc1, dmaDataBuffer, BATCH_DATA_LEN);
HAL_TIM_Base_Start(&htim3);
/* USER CODE END 2 */
重写回调函数
/* USER CODE BEGIN 4 */
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
uint32_t adcValue = 0, Volt;
for (uint8_t i = 0; i < BATCH_DATA_LEN; ++i) {
adcValue = dmaDataBuffer[i];
Volt = 3300 * adcValue >> 12;
if (i % 3 == 0) {
lcd_show_num(50, 130, Volt, 4, 24, RED);
} else if (i % 3 == 1) {
lcd_show_num(50, 190, Volt, 4, 24, RED);
} else if (i % 3 == 2) {
lcd_show_num(50, 250, Volt, 4, 24, RED);
}
}
}
/* USER CODE END 4 */