学习目标:使用ADC采集电压
通过配置ADC1_IN1通道,结合ADC模数转换函数,将电压模拟量转换为数字量,并将数据通过串口打印输出。
CubeMX配置
参数配置
在 Analog 中选择 ADC1 设置,并选择 IN1 通道1,选择 IN1 Single-ended单通道。
ADC具体配置参数下图所示
需要配置的参数已在图中框出,其他只需要保持默认就可以。
ADC_Settings:
Clock Prescaler:
Asynchronous clock mode divided by 1 1分频
Resolution
ADC 12-bit resolution 12位分辨率
Data Alignment
Right alignment 转换结果数据右对齐,一般选择右对齐模式。
Scan Conversion Mode
Disabled 禁止扫描模式。单通道使用 DISABLE。
Enabled 自动连续转换。
Continuous Conversion Mode:
Disabled 单次转换。只转换一次。
Enabled 自动连续转换。
DiscontinuousConvMode:
Disabled 禁止间断模式。在某个事件触发下,开启转换。
Enabled 开启间断模式。
DMA Continuous Requests
Disabled DMA请求是以单次模式执行,达到转换次数时,DMA传输停止。
Enabled 连续模式执行,无论转换次数多少,DMA传输无限制。
ADC_Regular_ConversionMode:
Enable Regular Conversions 是否使能规则转换。
Number Of Conversion ADC 转换通道数目,有几个写几个就行 。
External Trigger Conversion Source 外部触发选择。一般采用软件触发方式。
Rank:
Channel ADC 转换通道
Sampling Time 采样周期选择,采样周期越短,ADC数据输出周期短 精度低,采样周期越长,ADC数据输出周期长 精度高。
ADC_Injected_ConversionMode:
Enable Injected Conversions 是否使能注入转换。注入通道只有在规则通道存在时才会出现。
WatchDog:
Enable Analog WatchDog Mode 是否使能模拟看门狗中断。当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。
这里有些参数我也没使用过所以参数并不全。
配置ADC时钟,这里时钟不要超过14M,否则ADC采集电压有偏差。
ADC 的转换时间跟 ADC 的输入时钟和采样时间有关。
公式为:Tconv = 采样时间 + 12.5 个周期。当 ADCLK = 14MHZ (最高),采样时间设置为 1.5 周期(最快),那么总的转换时间(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
接下来配置USART1。
这里就列出来了,串口配置以及程序可以参考直接写过的 STM32L4 CubeMAX之USART
接下来生成代码后到KEIL MDK V5工程中继续新增用户控制逻辑。
完成用户控制逻辑
添加电压值转换
模拟电压经过 ADC 转换后,是一个 12 位的数字值,如果通过串口以 16 进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。
我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在:0~3.3v,因为 ADC 是 12 位的,那么 12 位满量程对应的就是 3.3V,12 位满量程对应的数字值是:2^12。数值 0 对应的就是 0V。如果转换后的数值为 X ,X 对应的模拟电压为 Y,那么会有这么一个等式成立: 2^12 / 3.3 = X / Y,=》 Y = (3.3 * X ) / 2^12。
// CoreIncmain.c
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
int adc_value=0;
float vol=0,num=0;
char buf[20];
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
if(HAL_UART_Receive_IT(&huart1, &usart1_buf.aRxBuff, 1) != HAL_OK)
{
Error_Handler();
}
printf(“ADCn”);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_MspInit(&hadc1);
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准
HAL_ADC_Start(&hadc1); //启动ADC单次转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待ADC转换完成
adc_value = HAL_ADC_GetValue(&hadc1); //读取ADC转换数据
vol =((double)adc_value/4096)*3.3;
printf(“adc_value = %d, vol = %.2fV.n”, adc_value, vol);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
下载编译程序观察串口调试助手,ADC采集电压
使用万用表实际电压,还是精度还可以。
总结
一开始发现AD读出来的电压值总是会有0.1V的偏差,最后找到原因是ADC采样数据与实际数据相差比较大,小了很多。
解决办法
配置adc的时候,采样周期设置大一些。
采样周期太小,会导致采样不准确,采样周期越大越准确。
采样周期太大会影响采样时间,因为我实验中采集的VBAT电池分压之后的电压,所以我设置的采样周期最大。采样时间大家可以自己去试。
计算公式:
采样时间(us) = (12.5+SamplingTime ) / ADC时钟(MHZ)
还有一点就是最好在写程序的加上HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准这句话。
以上。
学习目标:使用ADC采集电压
通过配置ADC1_IN1通道,结合ADC模数转换函数,将电压模拟量转换为数字量,并将数据通过串口打印输出。
CubeMX配置
参数配置
在 Analog 中选择 ADC1 设置,并选择 IN1 通道1,选择 IN1 Single-ended单通道。
ADC具体配置参数下图所示
需要配置的参数已在图中框出,其他只需要保持默认就可以。
ADC_Settings:
Clock Prescaler:
Asynchronous clock mode divided by 1 1分频
Resolution
ADC 12-bit resolution 12位分辨率
Data Alignment
Right alignment 转换结果数据右对齐,一般选择右对齐模式。
Scan Conversion Mode
Disabled 禁止扫描模式。单通道使用 DISABLE。
Enabled 自动连续转换。
Continuous Conversion Mode:
Disabled 单次转换。只转换一次。
Enabled 自动连续转换。
DiscontinuousConvMode:
Disabled 禁止间断模式。在某个事件触发下,开启转换。
Enabled 开启间断模式。
DMA Continuous Requests
Disabled DMA请求是以单次模式执行,达到转换次数时,DMA传输停止。
Enabled 连续模式执行,无论转换次数多少,DMA传输无限制。
ADC_Regular_ConversionMode:
Enable Regular Conversions 是否使能规则转换。
Number Of Conversion ADC 转换通道数目,有几个写几个就行 。
External Trigger Conversion Source 外部触发选择。一般采用软件触发方式。
Rank:
Channel ADC 转换通道
Sampling Time 采样周期选择,采样周期越短,ADC数据输出周期短 精度低,采样周期越长,ADC数据输出周期长 精度高。
ADC_Injected_ConversionMode:
Enable Injected Conversions 是否使能注入转换。注入通道只有在规则通道存在时才会出现。
WatchDog:
Enable Analog WatchDog Mode 是否使能模拟看门狗中断。当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。
这里有些参数我也没使用过所以参数并不全。
配置ADC时钟,这里时钟不要超过14M,否则ADC采集电压有偏差。
ADC 的转换时间跟 ADC 的输入时钟和采样时间有关。
公式为:Tconv = 采样时间 + 12.5 个周期。当 ADCLK = 14MHZ (最高),采样时间设置为 1.5 周期(最快),那么总的转换时间(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
接下来配置USART1。
这里就列出来了,串口配置以及程序可以参考直接写过的 STM32L4 CubeMAX之USART
接下来生成代码后到KEIL MDK V5工程中继续新增用户控制逻辑。
完成用户控制逻辑
添加电压值转换
模拟电压经过 ADC 转换后,是一个 12 位的数字值,如果通过串口以 16 进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。
我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在:0~3.3v,因为 ADC 是 12 位的,那么 12 位满量程对应的就是 3.3V,12 位满量程对应的数字值是:2^12。数值 0 对应的就是 0V。如果转换后的数值为 X ,X 对应的模拟电压为 Y,那么会有这么一个等式成立: 2^12 / 3.3 = X / Y,=》 Y = (3.3 * X ) / 2^12。
// CoreIncmain.c
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
int adc_value=0;
float vol=0,num=0;
char buf[20];
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
if(HAL_UART_Receive_IT(&huart1, &usart1_buf.aRxBuff, 1) != HAL_OK)
{
Error_Handler();
}
printf(“ADCn”);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_MspInit(&hadc1);
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准
HAL_ADC_Start(&hadc1); //启动ADC单次转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待ADC转换完成
adc_value = HAL_ADC_GetValue(&hadc1); //读取ADC转换数据
vol =((double)adc_value/4096)*3.3;
printf(“adc_value = %d, vol = %.2fV.n”, adc_value, vol);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
下载编译程序观察串口调试助手,ADC采集电压
使用万用表实际电压,还是精度还可以。
总结
一开始发现AD读出来的电压值总是会有0.1V的偏差,最后找到原因是ADC采样数据与实际数据相差比较大,小了很多。
解决办法
配置adc的时候,采样周期设置大一些。
采样周期太小,会导致采样不准确,采样周期越大越准确。
采样周期太大会影响采样时间,因为我实验中采集的VBAT电池分压之后的电压,所以我设置的采样周期最大。采样时间大家可以自己去试。
计算公式:
采样时间(us) = (12.5+SamplingTime ) / ADC时钟(MHZ)
还有一点就是最好在写程序的加上HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准这句话。
以上。
举报