【问题标题】:How to handle asynchronous input and synchronous output?如何处理异步输入和同步输出?
【发布时间】:2021-07-15 23:54:27
【问题描述】:

我目前正在从事一个项目,我在 STM32 系统上具有 USART 输入和 SAI(串行音频接口,类似于 SPI)输出。

我创建了一个循环缓冲区,用作 pinpong 缓冲区(双缓冲区)结构。从 USART 接收的输入样本存储在头指针指向的缓冲区中。当 SAI 外设请求新数据时,会从该缓冲区的尾指针中提取数据。

在我的代码开始时,我等到一半的缓冲区被填满,然后激活 SAI。 SAI 以 40kHz 的恒定速率输出。输入样本以大约 40kHz 的相同速率从外部设备的 USART 接收。

理想情况下,我希望我的头指针和尾指针之间的差异是恒定的。

我还实现了一种保护机制,当两个指针指向同一位置时,它使 Tail 指针等待并从 SAI 输出最后一个样本,直到缓冲区的一半被填充。

代码在开始时工作。问题是当大约 2 分钟的时间过去时,我们会看到头部和尾部指针指向同一位置,这会在我们的样本中产生不连续性。这意味着一个指针比预期的慢或快。我确信 SAI 协议会不断输出 40kHz(我用示波器检查过)。但是,我不太确定 USART 计时的准确性。我无法修改外部 USART 设备的代码,也无法更改输出速率 40kHz,它必须是这个值。

是否有另一种方法(可能是乒乓缓冲方法除外)来处理异步输入和同步输出?

【问题讨论】:

  • 串行端口传输数据的速度是否可能比 SAI 输出的速度快?
  • @Steve 是的,更快或更慢可能是问题所在。我们的测量结果显示每秒有 22 个样本差异。
  • 因此,如果源每秒传输 22 个样本的速度比消耗的快,那么这表明您的内存缓冲区约为 2k 样本。如果这是音频,那么您可能会不时放下一个样本,因此可能有一种算法可以在听者不注意的情况下执行此操作。
  • 你能想到其他方法吗?因为 SAI 驱动一个射频调制器芯片,该芯片通过采样信号的相位发送信息。因此,丢弃样本会导致相位混乱。不幸的是,我不能放弃样品。
  • 嗯。我已经开始写一篇关于如何做到这一点的答案帖子,但如果你不能丢弃样本,那么你必须弄清楚为什么你的输入速度快了 0.05%,或者如果这些不是连续传输,则可能使用更大的环形缓冲区.这听起来是个棘手的问题。

标签: c asynchronous synchronization stm32 microcontroller


【解决方案1】:

如果您所说的是您正在从某个外部设备接收(连续)串行数据,然后您正在以某种速率将其转发到您自己的某个接口......基于您的时钟。即使数据格式相同且时钟“相同”,也会在某处发生缓冲区溢出。

如果 1) 以线路速率连续 2) 输入源和输出源是不同的时钟 3) 保证参考时钟存在差异,则以太网或任何其他源会发生同样的情况,如果输入源时钟稍微快一点,只要流保持连续和线速,那么你最终会溢出。

时钟会随着温度和电压而变化,因此增量会发生变化。

甚至可以减少从输入输出的数据的百分比,如果输入是连续的,仍然会溢出。取决于您的输出是否也是线路速率,或者您是否有余量,并且余量可以克服时钟的差异。

还请记住,uart 几乎不会以那个精确的速率运行,使用时钟分频器并接近,您可以让两台计算机以相同的速率使用 uart,并且增量可能相对较大,并且很快就会发生溢出。为了使 uart 工作,时钟必须足够好才能通过一个字符,因此即使振荡器非常好并且没有 pll 并且双方使用相同的参考时钟(但不是相同的 uart、时钟系统等)。

如果您提高输出速率或降低正在输出的数据以使其不处于线路速率,那么问题可能会消失,或者可能需要数小时或数天才能发生......

如果我误解了问题,请原谅我,我会删除这个答案。

【讨论】:

    猜你喜欢
    • 2016-06-29
    • 2019-04-16
    • 2011-07-17
    • 2016-01-18
    • 2015-01-06
    • 2011-11-26
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多