当前位置:   article > 正文

HAL库 ADC超详细(查询、中断、DMA)_hal adc

hal adc

一、ADC的三种工作方式及优缺点

1.查询模式:查询模式下,占用CUP时间较多,cup效率较低。

2.中断模式:相比查询模式大大释放了cup,提高了cup的利用率。

3.DMA模式:该模式下基本不占用cup,能直接将ADC采集的数据存储到存储器。

二、ADC的转换方式

      转换方式需要根据情况搭配使用,分为扫描模式(Scan Conversion mode)、连续转换模式(Continuous Conversion Mode)和间断模式(Discontinuous Conversion Mode)。

ADC单通道转换:

  “单次转换模式,扫描模式关闭”:只进行一次转换,不过可以持续使能ADC达到不断采集的的。

  “连续转换模式,扫描模式关闭”:使能一次ADC后,能够连续转换。

ADC多通道转换:

 单次转换模式”,扫描模式开启”:每个通道转换完一次后结束转换,但可以通过持续使能ADC不断进行多通道连续采集。

 “连续转换模式”,扫描模式开启”:每个通道转换完之后还能继续循环转换,不需要反复使能ADC。

  多通道必须开启扫描模式。



三、ADC之查询模式(阻塞模式)

1、流程:

①开启ADC:调用HAL_ADC_Start(),开启ADC。

②等待EOC标志位:调用查询函数HAL_ADC_PollForConversion(),等待ADC转化结束,CUP在这段时间内不能干其他事,所以查询方式降低了CUP的使用率。

③读取寄存器数据:调用HAL_ADC_GetValue()。

2、STM32CUBEMX配置(ADC部分)

   使用的stm32f103zet6正点原子精英版,通过打开ADC1的通道1(PA1)。

 

Data Alignment : 可选左对齐或右对齐。

Conversion Mode:由于只使用了一个通道,关闭就行。

Continuous Conversion Mode:这里关闭,我们使用软件开启ADC。

Discontinuous Conversion Mode:单通道模式间断模式自动关闭,不可选。

Enable Regular Conversions:是否使能转换,开启规则转换。

Number Of Conversion:转换的通道数,单通道当然只能是1。

External Trigger Conversion Source:选择由软件触发采集。

Rank :每个通道的编号,

      每个Rank有如下参数配置:

      Channel:所选择的通道

      Sampling Time:每次采集ADC所需要的时间(采样周期),T = 采样周期 + 12.5个周期,(其中1周期为1/ADCCLK,设置的ADC时钟频率为12M),这里我设置的ADC的采样周期 为1.5Cycles,所以转化一次总的时间T=(1.5+12.5)/12=1.167us。补充:采样周期越长,越准确,这里存在一个竞争冒险的关系。

3、软件配置

在adc.h文件添加代码:

  1. /* USER CODE BEGIN 1 */
  2. 获取ADC的值
  3. uint16_t Get_adc(uint16_t ch)
  4. {
  5. HAL_ADC_Start(&hadc1); //先开启ADC
  6. HAL_ADC_PollForConversion(&hadc1,1);//查询函数,查询EOC标志位。每次采样,CUP在这里都要
  7. //等待采样完成才能进行下一步,这段时间CUP没有干其他
  8. //事,所以降低了CUP使用率
  9. return HAL_ADC_GetValue(&hadc1); //得到ADC的值
  10. }
  11. /获取times次采样值的平均值///
  12. uint16_t Get_ADC_Average(uint16_t ch,uint8_t times)
  13. {
  14. uint32_t ADC_Sum=0;
  15. uint8_t i;
  16. for(i=0;i<times;i++)
  17. {
  18. ADC_Sum+=Get_adc(ch);
  19. HAL_Delay(5);
  20. }
  21. return ADC_Sum/times; //times次样品值取平均,使采样值更加准确
  22. }
  23. /* USER CODE END 1 */

在main..c的初始化代码段定义一个uint16_t ADC_Value1;在while中添加一下代码(串口自己配置,可参考串口通信

  1. /* USER CODE BEGIN 1 */
  2. uint16_t ADC_Value1; //
  3. /* USER CODE END 1 */
  4. /* Configure the system clock */
  5. SystemClock_Config();
  6. /* USER CODE BEGIN SysInit */
  7. /* USER CODE END SysInit */
  8. /* Initialize all configured peripherals */
  9. MX_GPIO_Init();
  10. MX_USART1_UART_Init();
  11. MX_ADC1_Init();
  12. /* USER CODE BEGIN 2 */
  13. HAL_ADCEx_Calibration_Start(&hadc1);//开启ADC之前校准一下
  14. /* USER CODE END 2 */
  15. while (1)
  16. {
  17. ADC_Value1=Get_ADC_Average(ADC_CHANNEL_1,10);//得到10次采样值的均值
  18. printf("ADC:%d\n",ADC_Value1);
  19. HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
  20. HAL_Delay(1);
  21. }

ADC查询模式小总结:在关闭间断模式的情况下,多通道采集尽量不使用ADC查询模式进行,不然采样值容易出错,如果要用一定要开启间断采样模式。

四、多通道查询模式

1.STM32CUBEMX配置

  开启ADC1的四个通道 

 2.软件配置

在main.c中添加:

  1. int main(void)
  2. {
  3. /* USER CODE BEGIN 1 */
  4. uint16_t ADC_Value1,i;
  5. uint16_t adcbuf[4]; //四个通道采样数据存储的数组
  6. /* USER CODE END 1 */
  7. /* MCU Configuration--------------------------------------------------------*/
  8. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  9. HAL_Init();
  10. /* USER CODE BEGIN Init */
  11. /* USER CODE END Init */
  12. /* Configure the system clock */
  13. SystemClock_Config();
  14. /* USER CODE BEGIN SysInit */
  15. /* USER CODE END SysInit */
  16. /* Initialize all configured peripherals */
  17. MX_GPIO_Init();
  18. MX_USART1_UART_Init();
  19. MX_ADC1_Init();
  20. /* USER CODE BEGIN 2 */
  21. HAL_ADCEx_Calibration_Start(&hadc1); //开启adc前校准一下ADC
  22. /* USER CODE END 2 */
  23. /* Infinite loop */
  24. /* USER CODE BEGIN WHILE */
  25. while (1)
  26. {
  27. for(i=1;i<5;i++)
  28. {
  29. HAL_ADC_Start(&hadc1); //由于没有开启连续转换,每次转换前需要软件开启adc
  30. HAL_ADC_PollForConversion(&hadc1,10);//轮询等待ADC转换完成
  31. adcbuf[i]=HAL_ADC_GetValue(&hadc1); //将四个通道的采样值存在数组里
  32. printf("adc_ch%d: %d \n\r",i,adcbuf[i]);
  33. }
  34. HAL_ADC_Stop(&hadc1);//关闭ADC
  35. HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
  36. HAL_Delay(100);
  37. /* USER CODE END WHILE */
  38. /* USER CODE BEGIN 3 */
  39. }
  40. /* USER CODE END 3 */
  41. }

五、ADC之中断模式(单通道)

1、流程

①启动ADC,使能中断

②等待中断触发

③在中断中读取寄存器数据

2、STM32CUBEMX配置(ADC部分)

ADC的中断模式和单通道采样一样,只是多使能了一下adc中断。

 3、软件配置

只需在while()的上面校准adc和开启ADC。 

  1. HAL_ADCEx_Calibration_Start(&hadc1); 
  2. HAL_ADC_Start_IT(&hadc1);

在ADC的回调函数里面添加:

  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)//回调函数
  2. {
  3. uint16_t Adc_Value;
  4. Adc_Value=HAL_ADC_GetValue(&hadc1);
  5. printf("adc_value:%d\n",Adc_Value);
  6. }

 六、ADC之DMA(多通道)

1、流程

启动ADC

②配置DMA缓冲区

③读取缓冲区数据

2、STM32CUBEMX配置(ADC部分)

开启ADC1的通道1和2。

 

 3、软件配置

main.c

  1. int main(void)
  2. {
  3. /* USER CODE BEGIN 1 */
  4. uint16_t ADC_Value1,i;
  5. uint16_t AD_Buf[2]={0};//两个通道采集数据存在这个数组里面
  6. /* USER CODE END 1 */
  7. /* MCU Configuration--------------------------------------------------------*/
  8. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  9. HAL_Init();
  10. /* USER CODE BEGIN Init */
  11. /* USER CODE END Init */
  12. /* Configure the system clock */
  13. SystemClock_Config();
  14. /* USER CODE BEGIN SysInit */
  15. /* USER CODE END SysInit */
  16. /* Initialize all configured peripherals */
  17. MX_GPIO_Init();
  18. MX_USART1_UART_Init();
  19. MX_DMA_Init();
  20. MX_ADC1_Init();
  21. /* USER CODE BEGIN 2 */
  22. HAL_ADCEx_Calibration_Start(&hadc1);
  23. HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&AD_Buf,2);//开启ADC的DMA,采集的数据直接放入
  24. AD_Buf这个数组里,操作简单。
  25. /* USER CODE END 2 */
  26. while (1)
  27. {
  28. printf("AD1=%d\n\r",AD_Buf[0]);
  29. printf("AD2=%d\n\r",AD_Buf[1]);
  30. HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
  31. HAL_Delay(20);
  32. }
  33. }

ADC的DMA模式小总结:DMA模式最简单,并且采样过程基本不会影响CPU,一般使用ADC的DMA模式进行采样。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/997466
推荐阅读
相关标签
  

闽ICP备14008679号