无法通过UART传输所有字符

4
我正在使用stm32f0单片机。 我想要将从串口接收到的每个字节都传输出去。我会在每个从串口接收到的字节上启用中断。 我的代码非常简单。
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
    }
}

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


我认为在HAL重新初始化USART IRQ时,您错过了char。尝试将USART波特率显着降低2的幂次方。如果问题消失,则不要使用HAL来实现所需的MCU时钟频率和USART波特率,或更改其中一些时钟。 - imbearr
即使代码完全高效,也可能无法回显接收到的每个字符。波特率是从发射机的时钟派生出来的,这可能存在误差,并且除法也可能不精确。接收器通常会过采样,因此可以容忍数据稍微快或慢到达。但是,到达得太快的数据将以比UART传输半部分能够重复的速度生成字。在这种情况下,如果流入中没有暂停,迟早会丢失单词 - 或者如果您有一个多字缓冲区,您将开始填充并溢出它。 - Chris Stratton
3个回答

6
重新启用中断可能是低效的。通过进行一些修改,可以保持中断处于活动状态,而无需重新编写处理程序。请参见下面从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 */”注释中,并在我的代码后添加“return” - 这样默认的HAL处理程序就不会被执行。此外,编译器会忽略它,因为它没有“static”关键字。 - imbearr
init_gps() 静态函数是从哪里来的...它是否还有其他用途? - Aloy A Sen
init_gps() 启用了对 uart5 的中断,应该在 main() 开始时调用。 - Paulo Soares

2

您需要创建一个tx数组缓冲区,并且也要使用中断进行写入(如果第一次写入尚未启用,则应立即发送)。

有关此内容的STM32示例应该是可以找到的。


抱歉,我不太明白。为什么需要写入中断?根据wk_sg的回答,我使用HAL_UART_Transmit()测试代码,它不使用中断,但完全正常运行。 - guagay_wk
然后,您可以接收和发送数据,而无需担心缓冲区溢出的问题,这可能会在等待读取内部写入或反之亦然时发生。 - Stian Skjelstad
实际上,不,这并不能使你不再担心溢出问题。 - Chris Stratton

1
你应该交换两行代码:Transmit和Receive。Transmit函数等待超时才发送字符,同时会错过下一个接收的字符。

我尝试了你的答案。不幸的是,它没有起作用。问题仍然存在。 - guagay_wk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接