标准是9600波特。那只是标准。使用Arduino Uno SMD R2,我可以达到的最高实用波特率是多少?
大胆的奖励点:您将如何创建一个错误检查机制,然后将波特率提高到荒谬的高水平以获得高传输率?
laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca
。它使用CH340芯片进行USB通信。
标准是9600波特。那只是标准。使用Arduino Uno SMD R2,我可以达到的最高实用波特率是多少?
大胆的奖励点:您将如何创建一个错误检查机制,然后将波特率提高到荒谬的高水平以获得高传输率?
laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca
。它使用CH340芯片进行USB通信。
Answers:
这里有几个因素:
所有这些因素都与确定最大可实现的波特率有关。ATmega328P使用时钟频率的硬件除数来生成串行接口的基本时钟。如果主时钟与所需波特率的位时间之间没有整数比,则MCU将无法精确产生所需速率。这可能会导致潜在的问题,因为某些设备对波特率不匹配的敏感性要比其他设备高得多。
基于FTDI的接口可以容忍波特率不匹配,误差高达百分之几。但是,我与专门的嵌入式GPS模块一起使用,这些模块甚至无法处理0.5%的波特率错误。
通用串行接口可承受〜5%的波特率误差。但是,由于每个端都可以关闭,因此更常见的规格是+ -2.5%。这样,如果一端的速度是2.5%,另一端的速度是2.5%,则您的总体错误仍然只有5%。
无论如何。Uno使用ATmega328P作为主要MCU,使用ATmega16U2作为USB串行接口。我们在这里还幸运的是,这两个MCU都使用类似的Harware USART,以及16 Mhz时钟。
由于两个MCU具有相同的硬件和时钟速率,因此它们在相同方向上都将具有相同的波特率错误,因此我们可以在功能上忽略波特错误问题。
无论如何,对这个问题的“适当”答案将涉及挖掘ATmega16U2的来源,并从那里计算出可能的波特率,但是由于我很懒,我认为简单的经验测试会起作用。
快速浏览一下ATmega328P数据表,可获得下表:
因此,考虑到最大波特率为2 Mbps,我编写了一个快速测试程序:
void setup(){};
void loop()
{
delay(1000);
Serial.begin(57600);
Serial.println("\r\rBaud-rate = 57600");
delay(1000);
Serial.begin(76800);
Serial.println("\r\rBaud-rate = 76800");
delay(1000);
Serial.begin(115200);
Serial.println("\r\rBaud-rate = 115200");
delay(1000);
Serial.begin(230400);
Serial.println("\r\rBaud-rate = 230400");
delay(1000);
Serial.begin(250000);
Serial.println("\r\rBaud-rate = 250000");
delay(1000);
Serial.begin(500000);
Serial.println("\r\rBaud-rate = 500000");
delay(1000);
Serial.begin(1000000);
Serial.println("\r\rBaud-rate = 1000000");
delay(1000);
Serial.begin(2000000);
Serial.println("\r\rBaud-rate = 2000000");
};
然后使用串行终端查看相关的串行端口:
因此,看来硬件可以以2,000,000波特的速度运行而没有问题。
请注意,此波特率仅使MCU 64每字节80个时钟周期,因此要保持串行接口繁忙将非常具有挑战性。尽管各个字节的传输速度非常快,但是当接口仅处于空闲状态时,可能会花费很多时间。
编辑:实际测试!
2 Mbps是真实的:
每个位时间为500 ns,与期望的时间完全匹配。
性能问题!数据包总长度:
500 Kbaud:
1 Mbaud:
2 Mbaud:
注意:明显的过冲是由于示波器探头的接地方式不良所致,可能不是真实的。我使用的是接地探针,这是我的示波器探头的一部分,而导线电感可能是大多数过冲的原因。
如您所见,0.5、1、2 Mbaud的总传输长度是相同的。这是因为将字节存储在串行缓冲区中的代码没有得到优化。这样,除非编写自己的串行库,否则您将永远无法获得比有效 500 Kbaud 更好的任何东西。Arduino的库都很差优化,因此它可能不会是太困难得到适当的2波特,至少在突发传输,如果你花了一点时间就可以了。
Arduino串行监视器窗口将您限制为115200,但这并不是最高的波特率。您可以阅读Atmel和FT232(或您正在使用的任何产品)数据表以找到最大值,但我能够成功使用230400(是Arduino Serial Monitor支持的最大值的两倍)。
如果要在计算机上查看结果,则需要另一个支持其他波特率选项的串行监视器。我喜欢CoolTerm和Termite。
请注意,这也很大程度上取决于您的时钟速度。
这是一个计算器,可帮助您计算可能的结果。
这可能是el-Cheapo主板与原始主板不同的几个方面之一。最大串行传输速率几乎仅受板卡质量及其布局的限制。串行数据输入AVR或USB接口芯片后,将对数据进行不同于串行UART协议的处理。
请记住,尽管微控制器具有一些基本硬件,可将串行数据移入/移出IO引脚,但绝对最大速率限于16MHz时钟(对于AVR)。一旦将字节移至串行缓冲区,UART硬件将接管并自行推出/拉入位。AVR最多每秒可达到16M指令,并且用于填充串行缓冲区的中断会有一些开销(中断处理至少需要8个时钟滴答+保存当前状态的指令+实际填充缓冲区的几条指令)。在给定的比特率下,协议将以每秒n位的速度运行,但是您的控制器需要更多的时间来填充串行缓冲区,而不是实际输出数据所需要的时间,从而导致平均吞吐量低于您的预期和UART空闲相对较长的时间。
要记住的另一个效果是,将数据推送到UART(或将其拉入)所需的所有开销都不能用在您的实际程序中,这又会影响平均实际吞吐量。每个指令周期只能使用一次,用于填充缓冲区或计算主循环。
因此,最大吞吐量取决于您使用的应用程序(生成/计算/准备好从串行缓冲区移入/移出数据的速度)和实际的“物理”比特率仅是设计决策的一小部分。
U2Xn = 1
在USART中,往往会导致不匹配的问题。