硬汉嵌入式论坛

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

[ADC] 请教:AD采集的点个数不对

[复制链接]
回帖奖励 8 个金币 回复本帖可获得 1 个金币奖励! 每人限 1 次

18

主题

92

回帖

146

积分

初级会员

积分
146
QQ
发表于 2024-8-6 19:50:38 | 显示全部楼层 |阅读模式
请教大家一个问题:就是我程序设定外部触发中断,然后进行AD采集,一次只采集1024个点,ADC的时钟我设置的最大是50MHZ,但是实际采集出来一组的点远远超过1024是为什么呢?

下面是我关于ADC的一些配置:

#define ADC_DATA_LENGTH 1024 //定义采集数据长度为1024
uint8_t g_adc3_dma_data1[ADC_DATA_LENGTH];//定义adc3采集数据存放数组
uint8_t g_adc3_dma_complete_flag = 0;        //adc3数据dma采集完成标志,在dma采集完成回调函数设置

ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc3;

void MX_ADC3_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  hadc3.Instance = ADC3;
  hadc3.Init.Resolution = ADC_RESOLUTION_8B;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;//一组结束后给标志
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = ENABLE;//开启连续转换
  hadc3.Init.NbrOfConversion = 1;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件触发
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  //一旦 ADC 转换完成,通过 DMA 将数据传输到内存中
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
//  最新采集的数据不会覆盖旧数据
  hadc3.Init.Overrun = OVR_DATA_PRESERVED;
  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc3.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_1;
  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(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(adcHandle->Instance==ADC3)
  {
                GPIO_InitTypeDef GPIO_InitStruct = {0};
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL3.PLL3M = 25;
    PeriphClkInitStruct.PLL3.PLL3N = 200;
    PeriphClkInitStruct.PLL3.PLL3P = 4;
    PeriphClkInitStruct.PLL3.PLL3Q = 4;
    PeriphClkInitStruct.PLL3.PLL3R = 2;
    PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_0;
    PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL3;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
    /* ADC3 clock enable */
    __HAL_RCC_ADC3_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**ADC3 GPIO Configuration
    PC3_C     ------> ADC3_INP1
    */
                GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG ;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
               
    HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_OPEN);
    /* ADC3 DMA Init */
    /* ADC3 Init */
    hdma_adc3.Instance = DMA1_Stream2;
    hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
    hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_adc3.Init.Mode = DMA_CIRCULAR;//DMA循环模式
    hdma_adc3.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);
  }
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
  if(adcHandle->Instance==ADC3)
  {
    __HAL_RCC_ADC3_CLK_DISABLE();
    /* ADC3 DMA DeInit */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);
  }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) // 处理GPIO_PIN_1的中断事件
{
    if (GPIO_Pin == GPIO_PIN_1)
    {
                g_adc3_dma_complete_flag = 1;
    }
}

//ADC回调函数,ADC采集完成后进入回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{       
        if(hadc->Instance==ADC3)
        {       
                g_adc3_dma_complete_flag = 2;//采集完成标志       
                HAL_ADC_Stop_DMA(&hadc3);
        }
}
void ADC_Caiji(void)
{
        if(g_adc3_dma_complete_flag == 1)//检测到上升沿开始启动ADC_DMA
                        {
//                                HAL_Delay(1);
                                HAL_ADC_Start_DMA(&hadc3,(uint32_t *)g_adc3_dma_data1,ADC_DATA_LENGTH);//ADC的dma开始采集
                                if(g_adc3_dma_complete_flag == 2)
                                {
                                        for(int j=0;j<ADC_DATA_LENGTH;j++)
                                        {
                                                //采集到的值传到上位机串口,注意用仿真器的串口容易死机。
                                                printf("%d\r\n",g_adc3_dma_data1[j]);
                                        }
                        memset(g_adc3_dma_data1,0,ADC_DATA_LENGTH);//清除数据
                        g_adc3_dma_complete_flag = 0;       
                        }       
                }
}





将近2000个点.png
回复

使用道具 举报

95

主题

529

回帖

829

积分

金牌会员

积分
829
发表于 2024-8-7 07:59:43 | 显示全部楼层

回帖奖励 +1 个金币

你看看触发一次外部中断,g_adc3_dma_complete_flag==2这个条件里面的代码是不是不止进入一次?
共产主义一定胜利!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-7 09:14:03 | 显示全部楼层

回帖奖励 +1 个金币

设置成NORMAL,有效解决仅采集一次的问题。

hdma_adc3.Init.Mode = DMA_CIRCULAR;//DMA循环模式
回复

使用道具 举报

18

主题

92

回帖

146

积分

初级会员

积分
146
QQ
 楼主| 发表于 2024-8-7 09:46:47 | 显示全部楼层
会飞的猪_2020 发表于 2024-8-7 07:59
你看看触发一次外部中断,g_adc3_dma_complete_flag==2这个条件里面的代码是不是不止进入一次?

谢谢 我修改试一下
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-29 03:22 , Processed in 0.253349 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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