最近做了一个通过串口给stm32烧写程序的小项目,目的很简单,通过支持多种波特率9600、115200、25600、460800,来实现对其升级程序。最终460800在传输文件包数是2048byte/每帧时速度达到满意的10s以内。于是很开心的发布了。2天之内,下面测试人员反馈,用9600波特率升级失败。
多次测试发现是9600发输文件包数是2048byte/每帧才必出,然后果断调到512byte/每帧。果然没出了,我怀疑是9600传输速度太慢了,但是没证据。于是用监视串口的工具看,发现一个很奇怪的现象。我先用accessport监视,发现我组的帧一共2062个字节,是分多次下去的,先下去4包,每包512字节,染色下去了4包的时候看到下位机给的nak帧,接着在下一个发送包里,我要发送的剩余字节连着下一个包的头部一起下去了。看到这里,我是懵逼的,我明明是一起下去的,咋还没发完就收到了下位机的nak呐!
一方面怀疑串口监视工具有问题,一方面又怀疑自己代码出来bug。这样纠结了一会儿,没想明白。于是改用逻辑分析仪,看看世界数据和时序。果然发现连包了,只是和监视串口现象不同的是,是第一包肯定是先下去了,然后没有任何间隔的重发了该包,在重发包发送中间的时候,收到了nak否认帧。其实这里冷静下来想一下就很明了了,不过我就没明白为什么上位机会连包。于是又下载commonitor看监视数据,这次看的现象和逻辑分析仪对得上。果然是发完一帧后和重发帧无间隔的下去了,接着收到了nak。
commonitor很醒目的发送时间一下子让我意识到,9600传输速度慢!首先串口传输是异步的,也就是说上位机write数据,只是把数据交给系统就返回了,当我用9600时,我的超时计时器并不是从串口实际发送数据结束的时候开始计时的,而是更早,可以把它当做从串口开始发送第一包的时候开始计时的。如果9600传输速度慢到超过我的超时时间,那么定时结束超时就会重发下一包。而这个时候串口实际数据还没传输完成!这就解释了通过逻辑分析仪看到的现象,第一包和重发包无间隔,因为在串口发送第一包的时候已经超时了!
我是9600、偶校验、8位数据位、1位停止位。传输的时候都带一个开始位。那么实际串口发送码元的大小是:1+8+1+1=11bit。
串口波特率9600的单位实际是9600bit/s.那么该速度下传输的有效字节速度是:9600/11 = 872byte。
由于我文件包大小是2048,一帧是2062.那么当传输完该帧的时间是:2062/872 = 2.3646s.上位机默认超时时间:2s。果然是超时了。我又用逻辑分析仪测了下发送到结束的时间,也是2.36s。这下石锤了,9600波特率时,用大数据包传输,直接导致该未完成时就超时了。解决办法:调大超时时间,更换更大的波特率,采用小包传输文件(512)、串口同步传输。
我用的方法更直接,直接把9600该项去掉了。因为这个东西速度很慢,上面的解决办法,除了同步传输数据之外,其他的方法接口都是灵活可调的,别人给你设置的有问题,你没有一丝办法。