【问题标题】:Cannot transmit every characters through UART无法通过 UART 传输每个字符
【发布时间】:2016-09-14 19:18:50
【问题描述】:

我正在使用 stm32f0 MCU。

我想将从 uart 接收到的每一个字节传输到 uart 之外。我正在对从 uart 接收到的每个字节启用中断。

我的代码很简单。

uint8_t Rx_data[5]; 

//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)  //current UART
    {
        HAL_UART_Transmit(&huart1, &Rx_data[0], 1, 100);        
        HAL_UART_Receive_IT(&huart1, Rx_data, 1);   //activate UART receive interrupt every time on receiving 1 byte
    }
}

我的电脑将 ASCII 12345678 传输到 stm32。如果一切正常,PC 应该会收到 12345678 回复。但是,PC 会收到 1357。代码有什么问题?

【问题讨论】:

  • 我认为您在 HAL 重新初始化 USART IRQ 时错过了 char。尝试将 USART 波特率显着降低 2 次方。如果问题会消失,请不要将 HAL 用于所需的 MCU 时钟频率和 USART 波特率或更改其中一些时钟。
  • 即使使用非常高效的代码,也可能无法回显接收到的每个字符。波特率来自发送器的时钟,它可能有误差,而且分频也可能不精确。接收器通常会过采样,因此可以容忍到达有点快或慢的数据。但是,快速到达的数据会以比 UART 的发送一半重复的速度更快的速度生成字。在这种情况下,迟早,如果流入没有停顿,您将丢弃单词 - 或者如果您有一个多单词缓冲区,您将开始将其填满并溢出。

标签: interrupt stm32 uart stm32f0 stm32-hal


【解决方案1】:

重新启用中断可能效率低下。通过一些修改,可以保持中断处于活动状态,而无需重新编写处理程序。请参阅下面从 stm32cubemx 生成器更改的示例。

/**
* @brief This function handles USART3 to USART6 global interrupts.
*/
void USART3_6_IRQHandler(void)
{
  InterruptGPS(&huart5);
}

void InterruptGPS(UART_HandleTypeDef *huart) {
    uint8_t rbyte;
    if (huart->Instance != USART5) {
        return;
    }
    /* UART in mode Receiver ---------------------------------------------------*/
    if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) == RESET) || (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) == RESET)) {
        return;
    }
    rbyte = (uint8_t)(huart->Instance->RDR & (uint8_t)0xff);
    __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);

    // do your stuff

}

static void init_gps() {
    __HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE);
}

【讨论】:

  • 也有可能使用这样的解决方案而不改变 stm32cubemx 生成的代码。我只是在/*USER CODE BEGIN irq name */ cmets 中添加我的代码并在我的代码之后添加return - 所以默认HAL 的处理程序永远不会被执行。编译器忽略了它,因为它没有 static 关键字。
  • 从 init_gps() 静态函数的来源...是否需要用于任何其他目的??
  • init_gps() 启用对 uart5 的中断,它应该在 main() 开始时调用。
【解决方案2】:

你也应该做一个 tx 数组缓冲区,并使用中断进行写入(如果尚未启用第一次写入,则应立即发送)。

STM32 周围应该有这样的例子。

【讨论】:

  • 对不起,我不太明白。为什么需要中断写入?我使用不使用中断的 HAL_UART_Transmit() 测试代码,根据 wk_sg 的回答,它工作得非常好。
  • 然后您可以接收和发送,而不必担心等待写入内部读取时发生的缓冲区溢出,反之亦然
  • 实际上,不,这不会让您不必担心超支。
【解决方案3】:

您可能应该切换两行:发送和接收。 Transmit 函数等待超时发送字符,同时错过下一个接收到的字符。

【讨论】:

  • 我试过你的答案。不幸的是,它不起作用。问题依旧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多