硬汉嵌入式论坛

 找回密码
 立即注册
查看: 331|回复: 10
收起左侧

[ADC] STM32H7 adc采样的值全为0

[复制链接]

4

主题

4

回帖

16

积分

新手上路

积分
16
发表于 2025-7-15 14:31:00 | 显示全部楼层 |阅读模式
使用STM32H7开启ADC1单端模式配合DMA,使用定时器触发,可以进入ADC中断函数,但是打印出来的数值全为0

int16_t adc_df_buf[ADC_DF_LEN];
uint8_t adc_flag=0;
void STM32_ADC_Init(void)
{
        //250MHz/2500=10kHz
        TIM3->PSC = 0;         
        TIM3->ARR = 250-1;     
        HAL_TIM_Base_Start_IT(&htim3);       
        HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_df_buf, ADC_DF_LEN);
        HAL_DMA_Init(&hdma_adc3);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
        if(hadc->Instance==ADC3)
        {
                adc_flag=1;
                for(int i = 0; i < ADC_DF_LEN; i++)
                {
                        printf("{adc3_df}%d\r\n", adc_df_buf);
                }                       
        }
}





回复

使用道具 举报

12

主题

53

回帖

89

积分

初级会员

积分
89
发表于 2025-7-15 14:48:54 | 显示全部楼层
     HAL_TIM_Base_Start_IT(&htim3);      
        HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_df_buf, ADC_DF_LEN);
        HAL_DMA_Init(&hdma_adc3);

顺序不对吧
回复

使用道具 举报

4

主题

4

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-7-15 14:55:43 | 显示全部楼层
好像是因为数组存储地址的问题,修改完地址后有数据了,但是数据也不正常
__attribute__((section(".ARM.__AT_0x24006000"))) int16_t adc_df_buf[ADC_DF_LEN];
C:\Users\23943\Downloads\PixPin_2025-07-15_14-55-30.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-16 09:44:03 | 显示全部楼层
穗风兰 发表于 2025-7-15 14:55
好像是因为数组存储地址的问题,修改完地址后有数据了,但是数据也不正常
__attribute__((section(".ARM._ ...

注意MPU Cache配置问题。

可以关闭AXI SRAM的Cache看下。
回复

使用道具 举报

4

主题

4

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-7-16 17:34:39 | 显示全部楼层
现在没有开启Cache,可以采集到数据了,但是数据很乱,我使用TIM6,设置采样率是100kHz,但是采样1KHz的信号就非常的杂乱
__attribute__((section(".ARM.__AT_0x24006000"))) uint16_t adc_df_buf[ADC_DF_LEN];
uint8_t adc_flag=0;
void STM32_ADC_Init(void)
{
        //250MHz/2500=10kHz
//        TIM3->PSC = 0;         
//        TIM3->ARR = 2500-1;     
       
        HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_df_buf, ADC_DF_LEN);
        HAL_TIM_Base_Start(&htim6);       
        HAL_DMA_Init(&hdma_adc1);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
        if(hadc->Instance==ADC1&&adc_flag==0)
        {
                adc_flag=1;       
                for(int i = 0; i < ADC_DF_LEN; i++)
                {
                        printf("{adc1_df}%d\r\n",adc_df_buf[i]);
                }                       
        }
}

昨天试了一下        调节这三个的顺序,可以采集了,但是现在又不行了,不太清楚是什么问题
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_df_buf, ADC_DF_LEN);
        HAL_TIM_Base_Start(&htim6);       
        HAL_DMA_Init(&hdma_adc1);
PixPin_2025-07-16_17-32-32.png
PixPin_2025-07-16_17-33-41.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-17 08:58:33 | 显示全部楼层
穗风兰 发表于 2025-7-16 17:34
现在没有开启Cache,可以采集到数据了,但是数据很乱,我使用TIM6,设置采样率是100kHz,但是采样1KHz的信 ...

你分享的代码不太全,DMA缓存大小多少,DMA是采用的Normal还是Circle模式,你当前的这种打印方式,适合用Normal模式
回复

使用道具 举报

4

主题

4

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-7-17 10:48:39 | 显示全部楼层
DMA缓存大小设置的1024,开启的DMA循环采样模式,使用定时器来触发ADC进行采样,目前采样频率是100kHz,采样10kHz频率的图就和上面一样,采样较低频率就有很多的毛刺,请问这种问题是不是DMA的问题?
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_TRGO;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.Oversampling.Ratio = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 2;
    PeriphClkInitStruct.PLL2.PLL2N = 16;
    PeriphClkInitStruct.PLL2.PLL2P = 2;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0.0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* ADC1 clock enable */
    __HAL_RCC_ADC12_CLK_ENABLE();

    __HAL_RCC_GPIOF_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PF11     ------> ADC1_INP2
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA1_Stream0;
    hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC12_CLK_DISABLE();

    /**ADC1 GPIO Configuration
    PF11     ------> ADC1_INP2
    */
    HAL_GPIO_DeInit(GPIOF, GPIO_PIN_11);

    /* ADC1 DMA DeInit */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);
  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
}
回复

使用道具 举报

4

主题

4

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-7-17 18:43:57 | 显示全部楼层
已找到原因,需要采集完一轮之后停止定时器
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
        if(hadc->Instance==ADC1&&adc_flag==0)
        {
                adc_flag=1;       
                HAL_TIM_Base_Stop(&htim6);
                for(int i = 0; i < ADC_DF_LEN; i++)
                {
                        printf("{adc1_df}%d\r\n",adc_df_buf[i]);
                }                       
        }
}
回复

使用道具 举报

6

主题

60

回帖

78

积分

初级会员

积分
78
发表于 2025-7-18 08:49:24 | 显示全部楼层
穗风兰 发表于 2025-7-17 18:43
已找到原因,需要采集完一轮之后停止定时器
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{ ...

有没有更详细的解释?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-18 09:06:17 | 显示全部楼层
穗风兰 发表于 2025-7-17 18:43
已找到原因,需要采集完一轮之后停止定时器
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{ ...

用NORMAL模式就可以了

hdma_adc1.Init.Mode = DMA_CIRCULAR;

你用的循环模式,传输完毕会一直传输。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-18 09:06:33 | 显示全部楼层
红烧鱼头 发表于 2025-7-18 08:49
有没有更详细的解释?

用NORMAL模式就可以了

hdma_adc1.Init.Mode = DMA_CIRCULAR;

他用的循环模式,传输完毕会一直传输
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 02:45 , Processed in 0.051929 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表