我目前正在做一个项目,我在 STM32 系统上有 USART 输入和 SAI(串行音频接口,类似于 SPI)输出。
我创建了一个循环缓冲区,用作 pinpong 缓冲区(双缓冲区)结构。从 USART 接收的输入样本存储在头指针指向的缓冲区中。当 SAI 外设请求新数据时,从该缓冲区的尾指针中拉取数据。
在我的代码开始时,我等到缓冲区填满一半,然后激活 SAI。 SAI 以 40kHz 的恒定速率输出。从外部设备的 USART 以大约相同的速率 40kHz 接收输入样本。
理想情况下,我希望头指针和尾指针之间的差异保持不变。
我还实现了一种保护机制,当两个指针指向同一位置时,它使尾部指针等待并输出来自 SAI 的最后一个样本,直到缓冲区的一半被填充。
代码在开始时有效。问题是,当大约 2 分钟后,我们看到头指针和尾指针指向同一位置,这在我们的样本中造成了不连续性。这意味着单指针比预期慢或快。我确信 SAI 协议会不断输出 40kHz(我用示波器检查过)。但是,我不太确定 USART 计时的准确性。我不能修改外部 USART 设备的代码,我不能改变输出速率 40kHz 它必须是这个值。
是否有另一种方法(可能除了乒乓缓冲方法)来处理异步输入和同步输出?
答案 0 :(得分:0)
如果你说的是你从某个外部设备接收(连续)串行数据,然后你以某种速率将它转发到你自己的某个接口......基于你的时钟。即使数据格式相同且时钟“相同”,也可能会在某处发生缓冲区溢出。
同样的事情发生在以太网或任何其他源上,如果 1) 以线速连续 2) 输入源和输出源是不同的时钟 3) 保证参考时钟存在差异,如果输入源时钟要快一点,只要流保持连续和线速,那么你最终会溢出。
时钟会随着温度和电压的变化而变化,因此增量会发生变化。
甚至可以减少从输入输出的数据的百分比,如果输入是连续的,仍然会溢出。取决于您的输出是否也是线速,或者您是否有余量,并且余量可以克服时钟差异。
还请记住,uarts 几乎不会以那个确切的速率运行,使用时钟分频器并接近,您可以让两台计算机以相同的速率使用 uarts,并且增量可能相对较大,并且溢出可能很快发生。要使 UART 正常工作,时钟必须足够好以通过一个字符,因此即使振荡器非常好并且没有 pll 并且双方使用相同的参考时钟(但不是相同的 UART、时钟系统等)。
如果您提高输出速率或减少输出数据以使其不在线路速率下,那么问题可能会消失,或者可能需要数小时或数天才能发生...
如果我误解了这个问题,请原谅我,我会删除这个答案。