0

我有以下代码,其中大部分是由 STM32CubeMX 生成的。(我省略了生成的大量评论,以使其可读。)

volatile int txDoneFlag = 0;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
    txDoneFlag = 1;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();

  while (1)
  {
    LD2_GPIO_Port->BSRR = (uint32_t)LD2_Pin;
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"1: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart2, (uint8_t*)"2: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)"3: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_Delay(100);
    LD2_GPIO_Port->BSRR = (uint32_t)LD2_Pin << 16U;
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"1: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart2, (uint8_t*)"2: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)"3: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_Delay(100);
  }
}

DMA 是在 STM32CubeMX 生成器中设置的,所以应该是正确的。

当我运行这段代码时,它一开始就陷入无限循环while(!txDoneFlag);,这意味着它HAL_UART_TxCpltCallback()永远不会被调用。

这让我觉得我需要做一些进一步的事情来启用 D​​MA。

我怎样才能HAL_UART_Transmit_DMA()工作?

我已经尝试对生成的MX...调用重新排序,所以MX_DMA_Init()在 s 之前调用它...UART_Init()

--

更新:请求的代码。所有三个MX_USARTn_UART_Init()函数都有相同的主体(除了 uart 编号。

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* DMA1_Channel4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
  /* DMA1_Channel6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}
4

1 回答 1

1

确保在您的 STM32Cube ioc 文件中检查您正在使用的 UART 外设的全局中断是否为所有三个,根据芯片组合一些 IRQ。

它们位于您的 stm32F1xx_it.c 文件中。如果需要,设置断点并确保触发这些中断。在 ISR 内部,您可以看到正在调用哪个回调(如果有的话)(如果缺少某些配置)。您的 MX_DMA_Init() 和 UART_INIT() 中的配置是什么样的?你能分享那些吗?否则,您可以确保自己连接好所有东西。虽然,我可能会提醒您不要将这种技术与 DMA 一起使用,但 DMA 的全部意义在于能够在 CPU 上执行其他指令,而 DMA 则与内存联系并处理内存操作。

由于所有三个 UART 外设都发送消息和 DMA,您应该能够在回调中使用一些标志并使用 if 语句而不是使用 while 循环阻塞。

HAL 中的回调是弱类型的,因此您需要确保符号具有正确定义的路径,即.. extern 或明确的包含路径,以便在此处的主文件中将正确的内存地址分配给您的回调。这样,当从 ISR 发出回调时,主文件中的回调将是它的目标。

于 2020-01-10T20:46:52.493 回答