STM32L0开发系列——01 ADC采集
前言
使用芯片:STM32L051C8T6
软件平台:KEIL V5、STM32CubeL0
库函数:HAL
一、原理图
本文介绍在STM32上使用ADC1的第1通道,对电池电量进行采集。
二、ADC通道与引脚对应关系
通道 | 引脚 |
---|---|
PA0 | ADC_IN0 |
PA1 | ADC_IN1 |
PA2 | ADC_IN2 |
PA3 | ADC_IN3 |
PA4 | ADC_IN4 |
PA5 | ADC_IN5 |
PA6 | ADC_IN6 |
PA7 | ADC_IN7 |
PB0 | ADC_IN8 |
PB1 | ADC_IN9 |
PC0 | ADC_IN10 |
PC1 | ADC_IN11 |
PC2 | ADC_IN12 |
PC3 | ADC_IN13 |
PC4 | ADC_IN14 |
PC5 | ADC_IN15 |
PC5 | ADC_IN15 |
PC5 | ADC_IN15 |
内部温度传感器 (VSENSE) | ADC_IN16 |
内部参考电压 (VREFINT) | ADC_IN17 |
监视外部 VLCD 电源针脚 | ADC_IN18 |
三、ADC相关
1、 ADC 可由 APB 时钟或 HSI16 时钟提供。
2、 ADC 转换时间: 12 位分辨率对应的转换时间为 0.87 µs (1.14 MHz), 10 位分辨率
对应的转换时间为 0.81 µs,若降低分辨率,可进一步缩短转换时间。
四、实验步骤
1、系统时钟配置
//******************************************************************************
//name: SystemClock_Config
//introduce: 系统时钟配置
//parameter: none
//return: none
//changetime: 2019.05.21
//******************************************************************************
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
RCC_OscInitTypeDef RCC_OscInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON; //ADC的时钟源
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
__SYSCFG_CLK_ENABLE();
}
注意:一开始程序中没有配置HSI时钟,采集不到电压
2、ADC文件
#include "main.h"
ADC_HandleTypeDef hadc;
GPIO_InitTypeDef GPIO_InitStruct;
ADC_ChannelConfTypeDef sConfig;
//******************************************************************************
//name: ADC_Init
//introduce: ADC初始化
//parameter: none
//return: none
//changetime: 2019.05.21
//******************************************************************************
void ADC_Init(void)
{
uint32_t Calibration=0;
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
HAL_ADC_Init(&hadc) ;
//启动ADC校验功能
HAL_ADCEx_Calibration_Start(&hadc,ADC_SINGLE_ENDED);
//获取校验值
Calibration = HAL_ADC_GetValue(&hadc);
// 清除之前通道
sConfig.Channel = ADC_CHANNEL_1|ADC_CHANNEL_2|ADC_CHANNEL_3;
sConfig.Rank = ADC_RANK_NONE; // 清除通道属性
HAL_ADC_ConfigChannel(&hadc, &sConfig);
}
//******************************************************************************
//name: GET_ADC
//introduce: 单通道采集ADC的值
//parameter: CH:ADC采集通道
//return: ADC采集值
//changetime: 2019.05.21
//******************************************************************************
uint32_t GET_ADC(uint32_t CH)
{
uint32_t adc_conv_var;
sConfig.Channel = CH;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; // 设置通道
HAL_ADC_ConfigChannel(&hadc, &sConfig);
// 启动转换
HAL_ADC_Start(&hadc);
// 等待转换结束
HAL_ADC_PollForConversion(&hadc,20);// 超时20ms
// 读取结果
adc_conv_var = HAL_ADC_GetValue(&hadc);
// 清除通道
sConfig.Rank = ADC_RANK_NONE; // 清除通道
HAL_ADC_ConfigChannel(&hadc, &sConfig);
return adc_conv_var;
}
//******************************************************************************
//name: Get_Adc_Average
//introduce: 多次采集求平均值
//parameter: CH:ADC采集通道
//return: ADC采集值
//changetime: 2019.05.21
//******************************************************************************
void Get_Adc_Average(uint32_t *ch,uint32_t *adcx,uint8_t times)
{
uint32_t temp_val[9]={0};
uint8_t t,i;
for(t=0;t<times;t++)
{
for(i=0;i<9;i++)
{
temp_val[i]+=GET_ADC(ch[i]);
HAL_Delay(5);
}
}
for(i=0;i<9;i++)
{
adcx[i] = temp_val[i]/times;
}
}
3、main中测试
while(1)
{
BATTER_VALUE = GET_ADC(ADC_CHANNEL_1);
temp=(float)BATTER_VALUE*(3.3/4096)*2;
printf("temp=%0.2f\r\n",temp);
HAL_Delay(100);
}
四、实验结果
由于ADC的精度是12bit(4096)、参考电压为3.3V,因此实际读出的电量值为BATTER_VALUE3.3/40962.
试验成功
今天的文章STM32L0系列之ADC采集分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/7234.html