• 蓝桥杯嵌入式国赛笔记(4):多路AD采集


    1、前言

    蓝桥杯的国赛会遇到多路AD采集的情况,这时候之前的单路采集的方式就不可用了,下面介绍两种多路采集的方式。

    以第13届国赛为例

    2、方法一(配置通道)

    2.1 使用CubeMx配置 

    设置IN13与IN17为Single-ended

    在Parameter Settings中

            设置Clock Prescaler为Asynchronous clock mode divided by 2

    设置Rank-Sampling Time为640.6 Cycles

    2.2 bsp_adc.h代码编写

    1. #include "main.h"
    2. extern ADC_HandleTypeDef hadc2;
    3. void ADC2_Init(void);
    4. uint32_t Get_Adc(void);
    5. uint32_t Get_PA4(void);
    6. uint32_t Get_PA5(void);

    2.3 bsp_adc.c代码编写

    每次进行adc采集之前,重新配置一遍参数

    1. ADC_ChannelConfTypeDef sConfig = {0};
    2. sConfig.Channel = ADC_CHANNEL_17;
    3. sConfig.Rank = ADC_REGULAR_RANK_1;
    4. sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    5. sConfig.SingleDiff = ADC_SINGLE_ENDED;
    6. sConfig.OffsetNumber = ADC_OFFSET_NONE;
    7. sConfig.Offset = 0;
    8. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    9. {
    10. Error_Handler();
    11. }
    12. GPIO_InitTypeDef GPIO_InitStruct = {0};
    13. GPIO_InitStruct.Pin = GPIO_PIN_4;
    14. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    15. GPIO_InitStruct.Pull = GPIO_NOPULL;
    16. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    记住不要重复进行RCC的配置,否侧会卡死

    1. //这两个,不用加了
    2. __HAL_RCC_ADC12_CLK_ENABLE();
    3. __HAL_RCC_GPIOA_CLK_ENABLE();

    2.3.1 完整代码

    1. #include "ADC/bsp_adc.h"
    2. /**
    3. ******************************************************************************
    4. * @file adc.c
    5. * @brief This file provides code for the configuration
    6. * of the ADC instances.
    7. ******************************************************************************
    8. * @attention
    9. *
    10. *

      © Copyright (c) 2024 STMicroelectronics.

    11. * All rights reserved.
    12. *
    13. * This software component is licensed by ST under BSD 3-Clause license,
    14. * the "License"; You may not use this file except in compliance with the
    15. * License. You may obtain a copy of the License at:
    16. * opensource.org/licenses/BSD-3-Clause
    17. *
    18. ******************************************************************************
    19. */
    20. /* Includes ------------------------------------------------------------------*/
    21. /* USER CODE BEGIN 0 */
    22. /* USER CODE END 0 */
    23. ADC_HandleTypeDef hadc2;
    24. /* ADC2 init function */
    25. void ADC2_Init(void)
    26. {
    27. /* USER CODE BEGIN ADC2_Init 0 */
    28. /* USER CODE END ADC2_Init 0 */
    29. ADC_ChannelConfTypeDef sConfig = {0};
    30. /* USER CODE BEGIN ADC2_Init 1 */
    31. /* USER CODE END ADC2_Init 1 */
    32. /** Common config
    33. */
    34. hadc2.Instance = ADC2;
    35. hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
    36. hadc2.Init.Resolution = ADC_RESOLUTION_12B;
    37. hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    38. hadc2.Init.GainCompensation = 0;
    39. hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
    40. hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    41. hadc2.Init.LowPowerAutoWait = DISABLE;
    42. hadc2.Init.ContinuousConvMode = DISABLE;
    43. hadc2.Init.NbrOfConversion = 1;
    44. hadc2.Init.DiscontinuousConvMode = DISABLE;
    45. hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    46. hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    47. hadc2.Init.DMAContinuousRequests = DISABLE;
    48. hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    49. hadc2.Init.OversamplingMode = DISABLE;
    50. if (HAL_ADC_Init(&hadc2) != HAL_OK)
    51. {
    52. Error_Handler();
    53. }
    54. /** Configure Regular Channel
    55. */
    56. sConfig.Channel = ADC_CHANNEL_17;
    57. sConfig.Rank = ADC_REGULAR_RANK_1;
    58. sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    59. sConfig.SingleDiff = ADC_SINGLE_ENDED;
    60. sConfig.OffsetNumber = ADC_OFFSET_NONE;
    61. sConfig.Offset = 0;
    62. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    63. {
    64. Error_Handler();
    65. }
    66. /* USER CODE BEGIN ADC2_Init 2 */
    67. /* USER CODE END ADC2_Init 2 */
    68. }
    69. void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
    70. {
    71. GPIO_InitTypeDef GPIO_InitStruct = {0};
    72. if(adcHandle->Instance==ADC2)
    73. {
    74. /* USER CODE BEGIN ADC2_MspInit 0 */
    75. /* USER CODE END ADC2_MspInit 0 */
    76. /* ADC2 clock enable */
    77. __HAL_RCC_ADC12_CLK_ENABLE();
    78. __HAL_RCC_GPIOA_CLK_ENABLE();
    79. /**ADC2 GPIO Configuration
    80. PA4 ------> ADC2_IN17
    81. PA5 ------> ADC2_IN13
    82. */
    83. GPIO_InitStruct.Pin = GPIO_PIN_4;
    84. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    85. GPIO_InitStruct.Pull = GPIO_NOPULL;
    86. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    87. /* USER CODE BEGIN ADC2_MspInit 1 */
    88. /* USER CODE END ADC2_MspInit 1 */
    89. }
    90. }
    91. void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
    92. {
    93. if(adcHandle->Instance==ADC2)
    94. {
    95. /* USER CODE BEGIN ADC2_MspDeInit 0 */
    96. /* USER CODE END ADC2_MspDeInit 0 */
    97. /* Peripheral clock disable */
    98. __HAL_RCC_ADC12_CLK_DISABLE();
    99. /**ADC2 GPIO Configuration
    100. PA4 ------> ADC2_IN17
    101. PA5 ------> ADC2_IN13
    102. */
    103. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
    104. /* USER CODE BEGIN ADC2_MspDeInit 1 */
    105. /* USER CODE END ADC2_MspDeInit 1 */
    106. }
    107. }
    108. uint32_t Get_Adc(void)
    109. {
    110. uint32_t Adc_Value;
    111. HAL_ADC_Start(&hadc2);
    112. HAL_Delay(1);
    113. Adc_Value = HAL_ADC_GetValue(&hadc2);
    114. return Adc_Value;
    115. }
    116. uint32_t Get_PA4(void)
    117. {
    118. ADC_ChannelConfTypeDef sConfig = {0};
    119. sConfig.Channel = ADC_CHANNEL_17;
    120. sConfig.Rank = ADC_REGULAR_RANK_1;
    121. sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    122. sConfig.SingleDiff = ADC_SINGLE_ENDED;
    123. sConfig.OffsetNumber = ADC_OFFSET_NONE;
    124. sConfig.Offset = 0;
    125. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    126. {
    127. Error_Handler();
    128. }
    129. GPIO_InitTypeDef GPIO_InitStruct = {0};
    130. /**ADC2 GPIO Configuration
    131. PA4 ------> ADC2_IN17
    132. PA5 ------> ADC2_IN13
    133. */
    134. GPIO_InitStruct.Pin = GPIO_PIN_4;
    135. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    136. GPIO_InitStruct.Pull = GPIO_NOPULL;
    137. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    138. return Get_Adc();
    139. }
    140. uint32_t Get_PA5(void)
    141. {
    142. ADC_ChannelConfTypeDef sConfig = {0};
    143. sConfig.Channel = ADC_CHANNEL_13;
    144. sConfig.Rank = ADC_REGULAR_RANK_1;
    145. sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    146. sConfig.SingleDiff = ADC_SINGLE_ENDED;
    147. sConfig.OffsetNumber = ADC_OFFSET_NONE;
    148. sConfig.Offset = 0;
    149. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    150. {
    151. Error_Handler();
    152. }
    153. GPIO_InitTypeDef GPIO_InitStruct = {0};
    154. /**ADC2 GPIO Configuration
    155. PA4 ------> ADC2_IN17
    156. PA5 ------> ADC2_IN13
    157. */
    158. GPIO_InitStruct.Pin = GPIO_PIN_5;
    159. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    160. GPIO_InitStruct.Pull = GPIO_NOPULL;
    161. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    162. return Get_Adc();
    163. }
    164. /* USER CODE BEGIN 1 */
    165. /* USER CODE END 1 */
    166. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

    2.4 测试

     

    测试结果表明实验成功。  

    3、方法二(扫描模式)

    3.1 使用CubeMx配置

    设置IN13与IN17为Single-ended

    在Parameter Settings中

            设置Clock Prescaler为Synchronous clock mode divided by 2

    这里要将Number Of Conversion设置为2

    这样就可以采集两个不同的通道了 

     

    3.2 bsp_adc.h代码编写

    因为需要循环采集两个ADC值,所以GetADC函数的参数是一个uint32_t指针类型 

    1. #include "main.h"
    2. extern ADC_HandleTypeDef hadc2;
    3. void ADC2_Init(void);
    4. void GetADC(uint32_t *ADC_Val);

    3.3 bsp_adc.c代码编写

    HAL_ADC_Start之后,在for循环内进行连续的HAL_ADC_GetValue,在这之前先等待一下不然可能出现通道AD对应错误的情况。

    1. void GetADC(uint32_t *ADC_Val)
    2. {
    3. HAL_ADC_Start(&hadc2);
    4. int i;
    5. for(i=0;i<2;i++)
    6. {
    7. HAL_Delay(1);
    8. ADC_Val[i] = HAL_ADC_GetValue(&hadc2);
    9. }
    10. }

    3.3.1 完整代码

    1. #include "ADC/bsp_adc.h"
    2. ADC_HandleTypeDef hadc2;
    3. void ADC2_Init(void)
    4. {
    5. /* USER CODE BEGIN ADC2_Init 0 */
    6. /* USER CODE END ADC2_Init 0 */
    7. ADC_ChannelConfTypeDef sConfig = {0};
    8. /* USER CODE BEGIN ADC2_Init 1 */
    9. /* USER CODE END ADC2_Init 1 */
    10. /** Common config
    11. */
    12. hadc2.Instance = ADC2;
    13. hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
    14. hadc2.Init.Resolution = ADC_RESOLUTION_12B;
    15. hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    16. hadc2.Init.GainCompensation = 0;
    17. hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
    18. hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    19. hadc2.Init.LowPowerAutoWait = DISABLE;
    20. hadc2.Init.ContinuousConvMode = DISABLE;
    21. hadc2.Init.NbrOfConversion = 2;
    22. hadc2.Init.DiscontinuousConvMode = DISABLE;
    23. hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    24. hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    25. hadc2.Init.DMAContinuousRequests = DISABLE;
    26. hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    27. hadc2.Init.OversamplingMode = DISABLE;
    28. if (HAL_ADC_Init(&hadc2) != HAL_OK)
    29. {
    30. Error_Handler();
    31. }
    32. /** Configure Regular Channel
    33. */
    34. sConfig.Channel = ADC_CHANNEL_17;
    35. sConfig.Rank = ADC_REGULAR_RANK_1;
    36. sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    37. sConfig.SingleDiff = ADC_SINGLE_ENDED;
    38. sConfig.OffsetNumber = ADC_OFFSET_NONE;
    39. sConfig.Offset = 0;
    40. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    41. {
    42. Error_Handler();
    43. }
    44. /** Configure Regular Channel
    45. */
    46. sConfig.Channel = ADC_CHANNEL_13;
    47. sConfig.Rank = ADC_REGULAR_RANK_2;
    48. if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
    49. {
    50. Error_Handler();
    51. }
    52. /* USER CODE BEGIN ADC2_Init 2 */
    53. /* USER CODE END ADC2_Init 2 */
    54. }
    55. void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
    56. {
    57. GPIO_InitTypeDef GPIO_InitStruct = {0};
    58. if(adcHandle->Instance==ADC2)
    59. {
    60. /* USER CODE BEGIN ADC2_MspInit 0 */
    61. /* USER CODE END ADC2_MspInit 0 */
    62. /* ADC2 clock enable */
    63. __HAL_RCC_ADC12_CLK_ENABLE();
    64. __HAL_RCC_GPIOA_CLK_ENABLE();
    65. /**ADC2 GPIO Configuration
    66. PA4 ------> ADC2_IN17
    67. PA5 ------> ADC2_IN13
    68. */
    69. GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
    70. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    71. GPIO_InitStruct.Pull = GPIO_NOPULL;
    72. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    73. /* USER CODE BEGIN ADC2_MspInit 1 */
    74. /* USER CODE END ADC2_MspInit 1 */
    75. }
    76. }
    77. void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
    78. {
    79. if(adcHandle->Instance==ADC2)
    80. {
    81. /* USER CODE BEGIN ADC2_MspDeInit 0 */
    82. /* USER CODE END ADC2_MspDeInit 0 */
    83. /* Peripheral clock disable */
    84. __HAL_RCC_ADC12_CLK_DISABLE();
    85. /**ADC2 GPIO Configuration
    86. PA4 ------> ADC2_IN17
    87. PA5 ------> ADC2_IN13
    88. */
    89. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_5);
    90. /* USER CODE BEGIN ADC2_MspDeInit 1 */
    91. /* USER CODE END ADC2_MspDeInit 1 */
    92. }
    93. }
    94. void GetADC(uint32_t *ADC_Val)
    95. {
    96. HAL_ADC_Start(&hadc2);
    97. int i;
    98. for(i=0;i<2;i++)
    99. {
    100. HAL_Delay(1);
    101. ADC_Val[i] = HAL_ADC_GetValue(&hadc2);
    102. }
    103. }

    3.4 测试

     

    测试结果表明实验成功。 

    4、总结

    本文介绍了两种不同的AD多通道采集的办法,并实现了相关代码以及进行了验证,效果表明成功实现了多路的AD采集功能。 

  • 相关阅读:
    NFTScan | 10.02~10.08 NFT 市场热点汇总
    对3D建模师,你到底了解多少?
    【Axure 答疑】页面滚动到一定位置显示功能按钮
    ORB-SLAM2 ---- ORBextractor::operator()仿函数
    Docker搭建RabbitMQ集群_开启MQTT插件后连接不上
    在windows服务器上部署一个单机项目以及前后端分离项目
    2022/6/30学习总结
    表压0.1~0.6MPa范围内0.1%超高精度压力控制解决方案及其考核试验结果
    python爬虫分析基于python图书馆书目推荐数据分析与可视化
    认识WebSocket 以及怎么使用WebSocket
  • 原文地址:https://blog.csdn.net/weixin_42937740/article/details/138726833