C UART帧控制器的实现

C UART帧控制器的实现,c,data-structures,interrupt,stm32,dma,C,Data Structures,Interrupt,Stm32,Dma,我在STM32板上编程,对如何使用外围设备感到困惑:轮询、中断、DMA、DMA中断 实际上,我编写了一个UART模块来发送基本数据,它在轮询、中断和DMA模式下工作 但我希望能够发送和接收具有可变长度的特定帧,例如: [启动| LGTH |命令| ID |数据(LGTH)| CRC] 我也有传感器,我希望在这些UART帧中接收到的数据与传感器进行交互 所以,我不明白的是: 如何编程UART模块以“帧”模式工作?(缓冲区?循环DMA?中断?何时何地…) 当我能够使用UART发送或接收帧时,与传

我在STM32板上编程,对如何使用外围设备感到困惑:轮询、中断、DMA、DMA中断

实际上,我编写了一个UART模块来发送基本数据,它在轮询、中断和DMA模式下工作

但我希望能够发送和接收具有可变长度的特定帧,例如:
[启动| LGTH |命令| ID |数据(LGTH)| CRC]


我也有传感器,我希望在这些UART帧中接收到的数据与传感器进行交互

所以,我不明白的是:

  • 如何编程UART模块以“帧”模式工作?(缓冲区?循环DMA?中断?何时何地…)


  • 当我能够使用UART发送或接收帧时,与传感器交互的最佳方式是什么?(在带有外部变量的状态机中的定时器中断内)

将来,我们的想法是在freertos中实现这个应用程序


谢谢大家!

在DMA中绝对可用

您有一个大的(好的解决方案是循环的)缓冲区,您只需从一侧写入数据。如果DMA尚未工作,则使用缓冲区启动DMA

若DMA工作,您只需将数据写入缓冲区,然后等待DMA传输完成中断

稍后在这个中断中,您将增加缓冲区的读取指针(因为您已经发送了一些数据),并检查是否有任何数据可以通过DMA发送。将内存地址设置为DMA和要发送的缓冲区中的字节数

同样,当DMA TC IRQ发生时,再次执行该进程

不支持帧,但只支持普通字节。这意味着您必须“发明”自己的帧协议,并在应用程序中使用它

稍后,当您希望通过UART发送该帧时,您必须:

  • 将开始字节写入缓冲区
  • 写入其他头字节
  • 写入实际数据
  • 写入停止字节/CRC/任何内容
  • 检查DMA是否不工作,如果不工作,则启动它
通常,我使用这个框架概念:


[开始、地址、命令、长度、数据、CRC、停止]

  • 开始:表示帧开始的开始字节
  • 地址:总线上使用多个设备时的设备地址
  • 命令ID
  • LEN:2字节表示数据长度
  • 数据:以可变长度字节为单位的实际数据
  • CRC:2字节用于CRC,包括:地址、cmd、len、数据
  • 停止:表示帧结束的停止字节

这就是我在每个项目中所做的必要工作。这不使用CPU发送数据,只需设置DMA并开始传输

从应用程序的角度来看,您只需创建
send\u send(data,len)
函数,该函数将创建帧并将其放入缓冲区进行传输

缓冲区大小必须足够大,以满足您的要求:

  • 在特定时间有多少数据(是连续数据还是小时间有大量数据)
  • UART波特率

对于特定的问题,请提问,也许我可以提供我的库中的一些代码示例作为参考。

在这种情况下,您需要实现该协议,我可能会使用普通中断,并且在处理程序中,使用逐字节状态机将传入的字节解析到帧缓冲区中

只有在收到完整、有效的帧后,才有必要发送信号量/事件并重新测试调度程序的运行,否则,您可以根据需要处理任何协议错误-可能会发送一些“错误重复”消息并重置状态机以等待帧buyte的nexx启动

如果您使用DMA进行此操作,那么可变帧长度将非常棘手,您仍然需要迭代接收到的数据以验证协议:(

DMA听起来不太适合这个,对我来说


编辑:如果没有先发制人的多任务程序,那么忘记上面所有的信号量:)不过,检查布尔“validFrameRx”标志比解析DMA块数据更容易。

如果你有DMA,那么你会使用中断的唯一原因是当你有硬实时要求时。否则,请避免它们。对于接收到的串行数据,循环DMA缓冲区可能最有意义。你只需要确保你经常阅读它,这样它就永远不会溢出。“什么是与传感器交互的最佳方式?”是一个非常广泛的问题,可能无法回答。“最佳”导致基于意见的答案。UART不在“框架”中工作。它们只发送一些数据位的字符,周围有开始位和停止位。听起来您有一些更高级的协议,您希望通过UART链接使用,这很好。您只需将框架分解为构成它们的各个角色,然后逐个发送它们。在另一端,逐个接收并解码数据包。您的UART驱动程序可以是中断驱动、轮询和/或DMA驱动,这取决于您的应用程序的需要。@Lundin:仍然使用中断与DMA协同工作是很常见的,例如,为了让您知道DMA何时完成,以便您可以根据需要重新加载其源/目标地址寄存器。@Lundin:我不同意“避免中断”的笼统说法。即使在非硬实时系统中,它们也一直在使用。这看起来不像一个健壮的串行协议。1)
开始
停止
将是一件痛苦的事情,除非数据受到限制,因此它不能包含任何一个,因为中断的帧将导致错误的重新同步数据。2)
CMD
是特定于应用程序的,应该位于更高的层,而不是框架中。3) 在多点总线实现中,您需要的不仅仅是
地址
,但这些通常会产生一些硬件影响,例如时隙或握手(如RS232上的RTS/CTS)。4) 即使是
CRC
也可能有点太多,除非您的连接嘈杂且容易出错。谢谢您的评论。我很高兴给你答案。1) 一开始