Stm32 如何为可变长度数据实现UART Rx中断例程?

Stm32 如何为可变长度数据实现UART Rx中断例程?,stm32,uart,interrupt-handling,stm32f4,rs485,Stm32,Uart,Interrupt Handling,Stm32f4,Rs485,我有一个定制的STM32F4 MCU板。我需要从RS485 n/w中的主板接收不同类型的序列。要接收的数据长度是可变的,例如10字节、25字节等等。我必须处理每一个序列并做出相应的反应 如何正确使用HAL函数HAL\u UART\u Receive\u IT和HAL\u UART\u RxCpltCallback正确接收变量数据 我看到,HAL\u UART\u Receive\u IT的第三个参数正在寻找要固定的字节数,如图所示: HAL_UART_Receive_IT(&huart1

我有一个定制的STM32F4 MCU板。我需要从RS485 n/w中的主板接收不同类型的序列。要接收的数据长度是可变的,例如10字节、25字节等等。我必须处理每一个序列并做出相应的反应

如何正确使用HAL函数HAL\u UART\u Receive\u ITHAL\u UART\u RxCpltCallback正确接收变量数据

我看到,HAL\u UART\u Receive\u IT的第三个参数正在寻找要固定的字节数,如图所示:

HAL_UART_Receive_IT(&huart1, &uart1_rx_byte, no_of_bytes);
请建议一个好的实施方案

接收帧格式:
|开始字节|从地址|字节计数| Func。ID |数据1 |数据2 |……|数据n |校验和字节1 |校验和字节2|


其中字节计数=来自Func的字节数。校验和字节2的ID请查看本教程:

您必须对F4进行一点调整,用于计算RX缓冲区中数据的正确寄存器为

huart->hdmarx->Instance->NDTR

/wo“C”

如果您的通信速度相对于MCU时钟速度较慢,并且MCU没有更好的事情可做,那么您可以按照注释中@codo的建议进行两部分接收(前3个字节获得数据包长度,然后从数据包头接收n个字节)。如果您在繁忙的系统中寻找更高的速度,这将很快崩溃。另一个警告可能是数据包长度字节的位翻转会破坏消息

您坚持使用它并避免DMA似乎有点奇怪,因为它确实会使您的MCU在UART外围设备和它正在做的任何事情之间颤动(不要被“接收n字节”所愚弄)-它仍然在每个字节上生成IRQ,因为外围设备只有一个数据寄存器,只是IRQ处理和内存指针前进被HAL隐藏)。只有当整个数据包到达时,使用DMA接收才会触发IRQ。将DMA设置为最大数据包大小限制和UART_空闲或基于计时器的空闲检测(如果您的命令源没有提供精确计时的字节),允许您在数据包到达后处理整个数据包


我正在使用UART_IDLE IRQ,在180MHz上以8Mbaud进行DMA,使用FreeRTOS和其他一些对时间敏感的事情。在8Mbaud时,每个字节只有大约200个周期来处理消息,因此IT驱动的方法不能很好地工作(上下文切换、HAL开销等)。我也有包装结构,和你的类似。每个数据包根据长度和CRC进行验证。不幸的是,UART_IDLE IRQ处理是ST HAL中未实现的事情之一,因此您必须自己实现它。

是否有一个消息结束指示器可用于调度消息处理程序?然后中断处理程序可以将消息放入缓冲区。最后两个字节是校验和值,它们会随着其他数据字节的变化而变化。我建议将UART与DMA和循环缓冲区一起使用。然后每隔一毫秒(或更频繁)检查缓冲区中的数据是否包含完整的消息。缓冲区的处理方式类似于环形缓冲区。头部指针由DMA计数器给出,尾部位置由您的代码管理。@codo我不确定是否可以正确使用DMA。对于这个工作,我不想使用dma接口。如果数据字节不固定,如何知道缓冲区中是否有完整的消息?我的头是固定的,但每个序列的尾都会改变。从你的问题中我了解到,一旦你有了字节4,你就可以确定消息的大小。如果没有,我无法告诉您如何检测完整消息。毕竟,您并没有真正描述消息结构。使用循环缓冲区的DMA的优点是,您不需要像使用HAL_UART_Receive_IT那样指定特定的长度。。。请更具描述性。您可以使用教程1:1中的代码,通过STM32F4上的UART接收长度可变的消息。代码中唯一需要更改的是在RxCallback函数中使用寄存器“NDTR”而不是“CNDTR”