简体   繁体   English

STM32F404K8:HAL、ADC+DMA 在第一次读取后卡住

[英]STM32F404K8: HAL, ADC+DMA gets stuck after first reading

I'm trying to read ADC values from three different channels(right now, later it will be 6 channels, 3 on each ADC), and I would like to access my ADC buffer after some random time and send it forward using UART later on.我正在尝试从三个不同的通道读取 ADC 值(现在,稍后它将是 6 个通道,每个 ADC 上 3 个),并且我想在一些随机时间后访问我的 ADC 缓冲区并稍后使用 UART 将其发送. Right now they are just connected to +3.3V with a trimpotentiometer inbetween, resulting in different voltages on all three pins, which means I should be able to read the ADCs wuite often?现在它们只是连接到+3.3V,中间有一个微调电位器,导致所有三个引脚上的电压不同,这意味着我应该能够经常读取ADC吗? Anyway, to do this I'm using a STM32f303k8 board where I've set up ADC1 channel 2,4 & 11 to be used.无论如何,为此我使用的是 STM32f303k8 板,我已经在其中设置了要使用的 ADC1 通道 2,4 和 11。 I generated the code using STM32CubeMX, using HAL libraries, where I configured it to be using DMA in circular mode, scan conversion with continous conversion and different ranks.我使用 STM32CubeMX 生成代码,使用 HAL 库,我将其配置为在循环模式下使用 DMA,使用连续转换和不同等级的扫描转换。 Upon startup(using breakpoints), I can see that the init-part of the code works fine.启动时(使用断点),我可以看到代码的 init 部分工作正常。 The ADC is initialized and the DMA is started, I even get values into my buffer from ADC1 with correct values, channel1 != channel2 != channel3. ADC 已初始化,DMA 已启动,我什至将值从 ADC1 以正确的值(通道 1 != 通道 2 != 通道 3)进入我的缓冲区。 The problem is when proceeding, the process gets stuck in and infinite loop handler and does never reach my while(1) where I have some arbitrary statement.问题是在继续时,该进程陷入无限循环处理程序中,并且永远不会到达我的 while(1) 那里我有一些任意语句。 Code below.代码如下。

I've been following different guides to see if maybe I've set it up wrong.我一直在遵循不同的指南,看看我是否设置错了。 One of them being https://tunizem.blogspot.com/2014/09/using-adc-with-dma-on-stm32.html?showComment=1562660027777#c1229743050555367742 .其中之一是https://tunizem.blogspot.com/2014/09/using-adc-with-dma-on-stm32.html?showComment=1562660027777#c1229743050555367742 I've tried changing the sampletime from 1.5 all the way up to 601.5 cycles, also tried changing EOCSelection from single to sequential.我尝试将采样时间从 1.5 一直更改为 601.5 个周期,还尝试将 EOCSelection 从单个更改为顺序。

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}


/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DMAContinuousRequests = ENABLE;//ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;//OVERWRITTEN;
  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.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_61CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
     Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
     Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

 *
 *
 *


uint32_t adcValue1[60];

int main(void)
{
  /* MCU Configuration-----------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the 
Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  //MX_ADC2_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();

  //Start ADC writing to DMA on scan complete
  if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcValue1, 120) != HAL_OK)
      return 0;


  uint32_t stopwatch = HAL_GetTick();

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while(1)
  {
      if(((uint32_t)HAL_GetTick() - stopwatch) > 49)
      {
          stopwatch = HAL_GetTick();
          HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);

          sprintf((char*)buffer, "(%d)\t ADC1, (%d)\t ADC2, (%d)\t ADC3", 
adcValue1[0],
                  adcValue1[1], adcValue1[2]);

      }
  }
  /* USER CODE END 3 */
}
}

I've got a breakpoint at "uint32_t stopwatch = HAL_GetTick();"我在“uint32_t 秒表 = HAL_GetTick();”处有一个断点where I can see that adcValue1 is reading values.我可以看到 adcValue1 正在读取值。 Those are correct since there is 3.3V going into all three with the difference that the potentiometer is set to give out 2.2V at channel 2, ie it's lower than the other two.这些是正确的,因为三个电压都为 3.3V,不同之处在于电位计设置为在通道 2 输出 2.2V,即它低于其他两个。 But this is the only time I can see a reading being done since it get stuck in the infinite loop after this.但这是我唯一一次可以看到正在读取的内容,因为此后它陷入了无限循环。

enter code here

adcValue1   uint32_t [60]   0x20000220 <adcValue1>  
adcValue1[0]    uint32_t    2614    
adcValue1[1]    uint32_t    3638    
adcValue1[2]    uint32_t    3639    
adcValue1[3]    uint32_t    2612    
adcValue1[4]    uint32_t    3639    
adcValue1[5]    uint32_t    3637    
adcValue1[6]    uint32_t    2615    
adcValue1[7]    uint32_t    3642    
adcValue1[8]    uint32_t    3641    
adcValue1[9]    uint32_t    2616    
adcValue1[10]   uint32_t    3642    
adcValue1[11]   uint32_t    3638    
adcValue1[12]   uint32_t    2611    
adcValue1[13]   uint32_t    3637    
adcValue1[14]   uint32_t    3640    
adcValue1[15]   uint32_t    2614    
adcValue1[16]   uint32_t    3639    
adcValue1[17]   uint32_t    3639    
adcValue1[18]   uint32_t    2615    
adcValue1[19]   uint32_t    3643    


 * @brief  This is the code that gets called when the processor receives 
an
 *         unexpected interrupt.  This simply enters an infinite loop, 
preserving
 *         the system state for examination by a debugger.
 *
 * @param  None
 * @retval : None
 */

Default_Handler:
Infinite_Loop:  <--- STUCK HERE
    b   Infinite_Loop
    .size   Default_Handler, .-Default_Handler

Default_Handler is invoked when there is an interrupt for which no handler exists in the user code. Default_Handler在存在用户代码中不存在处理程序的中断时调用。 All addresses in the interrupt vector table point to this code, when you don't supply a handler for that interrupt.当您不为该中断提供处理程序时,中断向量表中的所有地址都指向该代码。

You can examine the VECTACTIVE bits in SCB->ICSR (see the STM32F4 programming manual ) to find out which interrupt vector is missing, then provide a proper handler in your code.您可以检查SCB->ICSRVECTACTIVE位(请参阅STM32F4 编程手册)以找出缺少哪个中断向量,然后在您的代码中提供适当的处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM