找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1048|回复: 2
收起左侧

STM32F4单片机定时器触发adc采样 DMA传输长度1024个数 缓存区内只有一半数据问题

[复制链接]
ID:973561 发表于 2023-5-29 19:28 | 显示全部楼层 |阅读模式
STM32F4 定时器触发adc采样 DMA传输长度1024个数  aADCxConvertedData缓存区内只有一半数据 前512是ad模拟量 后一半全是0

  1. void MX_ADC1_Init(void)
  2. {

  3.   /* USER CODE BEGIN ADC1_Init 0 */

  4.   /* USER CODE END ADC1_Init 0 */

  5.   ADC_ChannelConfTypeDef sConfig = {0};

  6.   /* USER CODE BEGIN ADC1_Init 1 */

  7.   /* USER CODE END ADC1_Init 1 */

  8.   /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  9.   */
  10.   hadc1.Instance = ADC1;
  11.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV6;  //6分频 最小采样周期2.5 + 12.5固定周期 采样一次1微秒
  12.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  13.   hadc1.Init.ScanConvMode = DISABLE;
  14.   hadc1.Init.ContinuousConvMode = DISABLE;   //ENABLE
  15.   hadc1.Init.DiscontinuousConvMode = DISABLE;
  16.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  17.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
  18.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  19.   hadc1.Init.NbrOfConversion = 1;
  20.   hadc1.Init.DMAContinuousRequests = ENABLE;
  21.   hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV ;
  22.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
  23.   {
  24.     Error_Handler();
  25.   }

  26.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  27.   */
  28. //  sConfig.Channel = ADC_CHANNEL_2;
  29. //  sConfig.Rank = 1;
  30. //  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;
  31. //  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  32. //  {
  33. //    Error_Handler();
  34. //  }

  35.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  36.   */
  37. //  sConfig.Channel = ADC_CHANNEL_3;
  38. //  sConfig.Rank = 2;
  39. //  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  40. //  {
  41. //    Error_Handler();
  42. //  }

  43.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  44.   */
  45. //  sConfig.Channel = ADC_CHANNEL_1;
  46. //  sConfig.Rank = 3;
  47. //  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  48. //  {
  49. //    Error_Handler();
  50. //  }

  51.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  52.   */
  53. //  sConfig.Channel = ADC_CHANNEL_12;
  54. //  sConfig.Rank = 4;
  55. //  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  56. //  {
  57. //    Error_Handler();
  58. //  }

  59.   /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  60.   */
  61.   sConfig.Channel = ADC_CHANNEL_13;
  62.         sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
  63.   sConfig.Rank = 1;
  64.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  65.   {
  66.     Error_Handler();
  67.   }
  68.   /* USER CODE BEGIN ADC1_Init 2 */

  69.   /* USER CODE END ADC1_Init 2 */
  70. //          HAL_DMA_Abort_IT(&hdma_adc1);
  71.     __HAL_DMA_ENABLE_IT(&hdma_adc1,DMA_IT_TC);    //开启传输完成中断
  72. //    HAL_ADC_Start_IT(&hadc1);



  73. }


  74. void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
  75. {

  76.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  77.   if(adcHandle->Instance==ADC1)
  78.   {
  79.   /* USER CODE BEGIN ADC1_MspInit 0 */

  80.   /* USER CODE END ADC1_MspInit 0 */
  81.     /* ADC1 clock enable */
  82.     __HAL_RCC_ADC1_CLK_ENABLE();

  83.     __HAL_RCC_GPIOC_CLK_ENABLE();
  84.     __HAL_RCC_GPIOA_CLK_ENABLE();
  85.     /**ADC1 GPIO Configuration
  86.     PC2     ------> ADC1_IN12
  87.     PC3     ------> ADC1_IN13
  88.     PA1     ------> ADC1_IN1
  89.     PA2     ------> ADC1_IN2
  90.     PA3     ------> ADC1_IN3
  91.     */
  92.     GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
  93.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  94.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  95.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  96.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  97.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  98.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  99.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  100.     /* ADC1 DMA Init */
  101.     /* ADC1 Init */
  102.     hdma_adc1.Instance = DMA2_Stream0;
  103.     hdma_adc1.Init.Channel = DMA_CHANNEL_0;
  104.     hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  105.     hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  106.     hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  107.     hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  108.     hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  109.     hdma_adc1.Init.Mode = DMA_NORMAL; //一般模式 DMA_NORMAL    //DMA_CIRCULAR  循环模式
  110.     hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
  111.     hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  112.     if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  113.     {
  114.       Error_Handler();
  115.     }

  116.     __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  117.   /* USER CODE BEGIN ADC1_MspInit 1 */
  118.     /* ADC1 interrupt Init */
  119. //    HAL_NVIC_SetPriority(ADC_IRQn, 5, 0);
  120. //    HAL_NVIC_EnableIRQ(ADC_IRQn);
  121.   /* USER CODE END ADC1_MspInit 1 */
  122.   }
  123. }








  124. void DMA2_Stream0_IRQHandler(void)
  125. {
  126. /* USER CODE BEGIN 2 */
  127. //           HAL_ADC_Stop_DMA(&hadc1);

  128. /* USER CODE BEGIN 2 */     //需要判断DMA是否传输完成 如果传输完成在继续
  129. //    if(__HAL_DMA_GET_FLAG(&hdma_adc1,DMA_FLAG_TCIF0_4)!=RESET)//DMA传输完成
  130. //                {
  131. //        __HAL_DMA_CLEAR_FLAG(&hdma_adc1,DMA_FLAG_TCIF0_4);//清除DMA传输完成中断标志位
  132.                
  133.                          HAL_TIM_Base_Stop (&htim3);
  134.                         
  135.                          ADC_Conver_flag = 1; //传输完成标志位
  136.                         
  137.                          ADConve_CNT++;
  138.                         
  139.                          if(ADConve_CNT > 1024)
  140.                          {
  141.                            ADConve_CNT = 0;
  142.                          }
  143.                         
  144. //                }
  145.                
  146.                   HAL_DMA_IRQHandler(&hdma_adc1);
  147.                         

  148.                         
  149. }


  150. void Task1_AdcConverted(void)   //任务1  ->   adc采集任务
  151. {
  152.         float adc_VreValue1 = 0;
  153.         float adc_result1 = 0;
  154.         float adc_VreValue2 = 0;
  155.         float adc_power_value = 0;
  156.         static u16 i = 0;
  157.   if(ADC_Conver_flag == 1)                           //转化完成标志位
  158.                 {                                                  
  159.        printf("***************adc转化成功**********************\r\n");
  160.                          ADC_Conver_flag = 0;                          ////转化完成标志位   
  161.        //抽取数据
  162. //                         Get_AdcVaule_arry(aADCxConvertedData,ADC_POWER_Value,ADC_1_Value_DMA,ADC_CONVERTED_DATA_BUFFER_SIZE) ;  //抽取数据
  163.                         
  164. //                         adc_VreValue1 = MedianFilteringForSensor(ADC_POWER_Value,1024);  //中值滤波
  165.                         
  166. //                         adc_result1 = moving_average_filtre(adc_VreValue1);  //滑动滤波算法
  167.                                  
  168. //                         adc_power_value = (float) adc_VreValue1*(float)3.3/4096;
  169.                           

  170.          for(i = 0;i < 1024 ; i++)
  171.                                  {
  172.                                    printf("%d \r\n ", aADCxConvertedData[i]);
  173. //                                         printf("%d \r\n ", i);
  174.            delay_ms(30);                                 
  175.                                  }
  176.                         
  177.                            
  178. //                           printf("基准电压power = %0.2f\r\n ", adc_power_value);
  179. ////                         printf("ad_value = %0.2f\r\n ", adc_VreValue2);
  180. //                           printf("转换次数= %d \r\n ", ADConve_CNT);
  181. //                         clean_buff(aADCxConvertedData ,ADC_CONVERTED_DATA_BUFFER_SIZE );
  182.                                                          
  183. //       HAL_TIM_Base_Start(&htim3);  //使用定时器3启动adc采样
  184.        delay_ms(1000);
  185.                    printf("*************************************\r\n");
  186. //                                
  187. //      Get_AdcVaule_arry(u16 * INPUT_pDst,ADC_POWER_Value,u16 * OUTPUT_BUF2,u16 nums) ;
  188. //                           
  189.                                                                                    
  190.                 }
  191. }



  192. int main(void)
  193. {
  194.   /* USER CODE BEGIN 1 */
  195. //   u16 i = 0;
  196.    u8 sys_cnt = 0;
  197.   /* USER CODE END 1 */

  198.   /* MCU Configuration--------------------------------------------------------*/
  199.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  200.   HAL_Init();

  201.   /* USER CODE END Init */
  202.   /* Configure the system clock */
  203.   SystemClock_Config();
  204.   /* USER CODE BEGIN SysInit */
  205.   /* USER CODE END SysInit */
  206.   /* Initialize all configured peripherals */
  207.   MX_GPIO_Init();
  208.           /* USER CODE BEGIN SysInit */
  209.   MX_DMA_Init();
  210.           /* USER CODE BEGIN SysInit */
  211.   MX_ADC1_Init();
  212.         /* USER CODE BEGIN SysInit */
  213.   MX_TIM3_Init();   //触发ADC 的时钟
  214.         /* USER CODE BEGIN SysInit */
  215.   MX_TIM4_Init();   //通用定时器1ms中断
  216.         /* USER CODE BEGIN SysInit */
  217.   MX_UART5_Init();  //485接口
  218.         /* USER CODE BEGIN SysInit */
  219.   MX_USART1_UART_Init();//备用
  220.         /* USER CODE BEGIN SysInit */
  221.   MX_IWDG_Init(64,1000);//分频数为64,重载值为500,溢出时间为1s  1000为两秒
  222.   /* USER CODE END 2 */
  223.   TIM2_PWM_Init(1000-1,84-1);            //84M/84=1M的计数频率,自动重装载为 ARR,那么PWM频率为   1M /ARR =  f HZ
  224.           /* USER CODE BEGIN 2 */
  225.         HAL_TIM_Base_Start(&htim3);  //使用定时器3启动adc采样
  226.         //adc启动DMA采样
  227.         HAL_ADC_Start_DMA(&hadc1,(uint32_t *)aADCxConvertedData,1024);

  228.         printf("********RUN*******\r\n");
  229.         delay_ms(100);
  230.   /* Infinite loop */
  231.   /* USER CODE BEGIN WHILE */
  232.   while (1)
  233.   {
  234.                         /* USER CODE END WHILE */
  235.                         Task1_AdcConverted();   //任务1  ->   adc采集任务

  236.                         /* USER CODE END WHILE */
  237. //                        Task2_Modubus();     //任务2  ->   Modubus任务
  238.                
  239.             /* USER CODE END WHILE */ //本次任务结束
  240.                   sys_cnt++;               
  241.                   if(sys_cnt > 20)
  242.                         {
  243.                            sys_cnt = 0;
  244.                         }
  245.                
  246.                         delay_ms(100);                        
  247. //                        printf("***************程序运行中**********************\r\n");
  248.                   
  249.     /* USER CODE BEGIN 3 */
  250.   }
  251.   /* USER CODE END 3 */
  252. }
复制代码
回复

使用道具 举报

ID:298093 发表于 2023-9-13 20:14 | 显示全部楼层
我也遇到同样问题,不知道你解决了没
回复

使用道具 举报

ID:883242 发表于 2023-9-13 21:02 | 显示全部楼层
赶脚你对DMA的认识有非常大的误解,ADConve_CNT是进行了多少次DMA传输的意思,但是你理解成每次ADC结束后都要进入一次DMA传输完成中断(TC)。你应该把DMA那部分内容读一遍。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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