[其他ST产品] stm32 adc dma

[复制链接]
1527|33
 楼主| 梅花香自123 发表于 2023-11-25 14:21 | 显示全部楼层 |阅读模式
AD, ADC, DM, DMA, ST
ADC采集电压,使用DMA传输到内存
一,ADC设置

85936561927772365.png



 楼主| 梅花香自123 发表于 2023-11-25 14:22 | 显示全部楼层
1,Mode。
460906561928aa35fe.png
这里我们使用ADC的独立模式。
 楼主| 梅花香自123 发表于 2023-11-25 14:22 | 显示全部楼层
2,时钟分频

49634656192a2d9cee.png

ADCCLK由 PCLK2分频得到,最大时钟频率36M。ADC 时钟太快,采样可能不够准确,误差大。
 楼主| 梅花香自123 发表于 2023-11-25 14:22 | 显示全部楼层
3,采样分辨率
43120656192b71d740.png
分辨率不一样,最小转换时间也不一样,分辨率小可以提高转换时间。

注意触发时间一定要大于转换时间,保证每次转换完成。
 楼主| 梅花香自123 发表于 2023-11-25 14:23 | 显示全部楼层
4,数据对齐

27150656192c8c5cf0.png
 楼主| 梅花香自123 发表于 2023-11-25 14:23 | 显示全部楼层
 楼主| 梅花香自123 发表于 2023-11-25 14:23 | 显示全部楼层
 楼主| 梅花香自123 发表于 2023-11-25 14:23 | 显示全部楼层
5,扫描转换模式。

66336656192e606354.png

当由多个通道采集时,可以组成常规组序列,如果开启扫描模式,就进行轮流采样。
 楼主| 梅花香自123 发表于 2023-11-25 14:24 | 显示全部楼层
6,连续转换模式。
CR2中:

73161656192fc388ed.png

持续转换模式,我的理解是,指ADC是单次转换还是连续转换,连续转换的话,比如软件触发一次转换的话,转换完成,会自动进行下一次转换,不许程序上再次触发。这样的话,ADC会持续不断的进行采样。
 楼主| 梅花香自123 发表于 2023-11-25 14:24 | 显示全部楼层
比如初始化种程序开始ADC了采样

HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC1_DMA_BUFFER, 10);
ADC会一直采样下去,数据也正常。
 楼主| 梅花香自123 发表于 2023-11-25 14:24 | 显示全部楼层
下面,是我添加了,HAL_ADC_Stop_DMA(&hadc1)函数,发现,ADC还是继续采集,只是,发现转换结果,只有第一次转换有数据,其余都变为0了。

830806561931d0a56c.png
 楼主| 梅花香自123 发表于 2023-11-25 14:24 | 显示全部楼层
 楼主| 梅花香自123 发表于 2023-11-25 14:24 | 显示全部楼层
7,不连续转换模式。
CR1中:
276106561933048610.png

 楼主| 梅花香自123 发表于 2023-11-25 14:25 | 显示全部楼层
参考程序可能更好懂一些,可是,还是不太明白

319426561933dedbdb.png
 楼主| 梅花香自123 发表于 2023-11-25 14:25 | 显示全部楼层
官方解释

  1. uint32_t ContinuousConvMode;           /*!< Specifies whether the conversion is performed in single mode (one conversion) or continuous mode for regular group,
  2.                                               after the selected trigger occurred (software start or external trigger).
  3.                                               This parameter can be set to ENABLE or DISABLE. */
  4.   
  5.   FunctionalState DiscontinuousConvMode; /*!< Specifies whether the conversions sequence of regular group is performed in Complete-sequence/Discontinuous-sequence (main sequence subdivided in successive parts).
  6.                                               Discontinuous mode is used only if sequencer is enabled (parameter 'ScanConvMode'). If sequencer is disabled, this parameter is discarded.
  7.                                               Discontinuous mode can be enabled only if continuous mode is disabled. If continuous mode is enabled, this parameter setting is discarded.
  8.                                               This parameter can be set to ENABLE or DISABLE. */

 楼主| 梅花香自123 发表于 2023-11-25 14:25 | 显示全部楼层
8,DMA持续请求
128036561936088b74.png
  1. FunctionalState DMAContinuousRequests; /*!< Specifies whether the DMA requests are performed in one shot mode (DMA transfer stop when number of conversions is reached)
  2.                                               or in Continuous mode (DMA transfer unlimited, whatever number of conversions).
  3.                                               Note: In continuous mode, DMA must be configured in circular mode. Otherwise an overrun will be triggered when DMA buffer maximum pointer is reached.
  4.                                               Note: This parameter must be modified when no conversion is on going on both regular and injected groups (ADC disabled, or ADC enabled without continuous mode or external trigger that could launch a conversion).
  5.                                               This parameter can be set to ENABLE or DISABLE. */



**********如果禁止的话,DMA只发送一次*****************
 楼主| 梅花香自123 发表于 2023-11-25 14:28 | 显示全部楼层
9,结束转换选择 (End of conversion selection)

51241656193fab4e60.png
 楼主| 梅花香自123 发表于 2023-11-25 14:28 | 显示全部楼层
 楼主| 梅花香自123 发表于 2023-11-25 14:29 | 显示全部楼层
10,规则通道转换模式:
Number Of Conversion。
转换通道数,根据这个数量,下方出现几个RANK,对各个通道进行配置。

外部触发转换源。
可分软件触发和外部触发。

软件触发,指控制寄存器触发一次ADC转换。

外部触发,可以通过外部事件(例如,定时器捕获、EXTI 中断线)触发转换,使用定时器触发属于外部触发。

外部触发边沿选择。

Rank,通道 ,采样时间。
 楼主| 梅花香自123 发表于 2023-11-25 14:29 | 显示全部楼层
14,注入通道转换模式。
二,程序。
1,ADC和DMA设置


  1. /* ADC1 init function */
  2. void MX_ADC1_Init(void)
  3. {

  4.   /* USER CODE BEGIN ADC1_Init 0 */

  5.   /* USER CODE END ADC1_Init 0 */

  6.   ADC_ChannelConfTypeDef sConfig = {0};

  7.   /* USER CODE BEGIN ADC1_Init 1 */

  8.   /* USER CODE END ADC1_Init 1 */

  9.   /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  10.   */
  11.   hadc1.Instance = ADC1;
  12.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  13.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  14.   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  15.   hadc1.Init.ContinuousConvMode = ENABLE;
  16.   hadc1.Init.DiscontinuousConvMode = DISABLE;
  17.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  18.   hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  19.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  20.   hadc1.Init.NbrOfConversion = 1;
  21.   hadc1.Init.DMAContinuousRequests = DISABLE;
  22.   hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  23.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
  24.   {
  25.     Error_Handler();
  26.   }

  27.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  28.   */
  29.   sConfig.Channel = ADC_CHANNEL_2;
  30.   sConfig.Rank = ADC_REGULAR_RANK_1;
  31.   sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  32.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  33.   {
  34.     Error_Handler();
  35.   }
  36.   /* USER CODE BEGIN ADC1_Init 2 */

  37.   /* USER CODE END ADC1_Init 2 */

  38. }

  39. void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
  40. {

  41.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  42.   if(adcHandle->Instance==ADC1)
  43.   {
  44.   /* USER CODE BEGIN ADC1_MspInit 0 */

  45.   /* USER CODE END ADC1_MspInit 0 */
  46.     /* ADC1 clock enable */
  47.     __HAL_RCC_ADC1_CLK_ENABLE();

  48.     __HAL_RCC_GPIOA_CLK_ENABLE();
  49.     /**ADC1 GPIO Configuration
  50.     PA2     ------> ADC1_IN2
  51.     */
  52.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  53.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  54.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  55.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  56.     /* ADC1 DMA Init */
  57.     /* ADC1 Init */
  58.     hdma_adc1.Instance = DMA2_Stream0;
  59.     hdma_adc1.Init.Channel = DMA_CHANNEL_0;
  60.     hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  61.     hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  62.     hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  63.     hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  64.     hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  65.     hdma_adc1.Init.Mode = DMA_CIRCULAR;
  66.     hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
  67.     hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  68.     if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  69.     {
  70.       Error_Handler();
  71.     }

  72.     __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  73.   /* USER CODE BEGIN ADC1_MspInit 1 */

  74.   /* USER CODE END ADC1_MspInit 1 */
  75.   }
  76. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

1216

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部