[STM32L0]

STM32L0系列之ADC采集

[复制链接]
408|2
手机看帖
扫描二维码
随时随地手机跟帖
海滨消消|  楼主 | 2023-6-12 16:15 | 显示全部楼层 |阅读模式
STM32L0开发系列——01 ADC采集
前言
使用芯片:STM32L051C8T6
软件平台:KEIL V5、STM32CubeL0
库函数:HAL

一、原理图
本文介绍在STM32上使用ADC1的第1通道,对电池电量进行采集。
270076486d3ef93b56.png
二、ADC通道与引脚对应关系
848866486d4062f197.png
三、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 style="font-style: italic;">+=GET_ADC(ch);

  •                  </i> HAL_Delay(5);

  •                 }


  •         }


  •         for(i=0;i<9;i++)

  •                 {

  •                         adcx = temp_val/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.
试验成功

41606486d42311985.png

使用特权

评论回复
guijial511| | 2023-6-12 19:48 | 显示全部楼层
ST的ADC还是很稳的。

使用特权

评论回复
Henryko| | 2023-6-12 21:27 | 显示全部楼层
guijial511 发表于 2023-6-12 19:48
ST的ADC还是很稳的。

有人说STM32的ADC效果不好,跳变很大;有人说STM32的ADC效果很好,波动可以做到2-3个跳变。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

221

主题

1548

帖子

2

粉丝