FPGA串口通讯时波特率不稳定导致接受异常
一个FPGA项目中串口模块接收数据时发现经常出现接收异常的情况,上位机通过RS232串口下发相同的字符,FPGA接收却时常出现接收缓存不一致的情况。
不得不重新审核代码。波特率计算采样模块如下:
module uart_trigger(sysclk,rst,trigger,enable);
inputsysclk;
//系统时钟
inputenable;
//使能信号
output trigger;
//采样沿
inputrst;
//复位信号reg[8:0]count;
regtrigger;
always @(posedge sysclk )begin
if(!rst | !enable)begin
count <= 0;
trigger <= 0;
end
else if(count == 9'd337)begin
trigger <= 1'b1;
count <= count + 1'b1;
end
else if(count == 9'd434)begin
count <= 1'b0;
end
else begin
count <= count + 1'b1;
trigger <= 1'b0;
end
endendmodule
串口波特率为115200,系统时钟50Mhz
于是有如下计算:
时钟周期 = 20ns
UART接收单个bit时间 = 1000_000_000 ns / 115200= 8680 ns
UART接收单个bit所耗时钟周期 = UART接收单个bit时间 / 时钟周期= 8680 ns / 20ns = 434 个时钟周期
即每434个时钟周期采样一次RXD信号是最准确的
因为数据周期正中间的位置数据质量是最好的,因此在434 / 2即217个时钟周期的时候采样数据应该是最佳的选择
在上面的代码中,trigger信号在enable信号使能后217个时钟周期时输出一个时钟周期高电平,以后每隔434个时钟周期输出一个时钟周期高电平。
trigger信号提供接收模块最精准的采样时机。如此看来代码本身并没有BUG。
那到底是什么导致经常性采样值不准确?
经过SignalTab实时波形,发现计算机的输出串口时常出现不符合逻辑的情况,在串口发送数据相同的情况下(0x55),多次实时采样图如下:
文章图片
文章图片
文章图片
可以看到RXD信号并不像理论上那样所想的,“在波特率的正中间采样,效果最好”
经过观察,发现在采样沿之后约120个时钟周期数据是最为稳定的,因此将代码
else if(count == 9'd217)begin
trigger <= 1'b1;
count <= count + 1'b1;
end
改为
else if(count == 9'd337)begin
trigger <= 1'b1;
count <= count + 1'b1;
end
【FPGA串口通讯时波特率不稳定导致接受异常】经测试,串口接收缓存终于保持稳定。
目前的测试环境是Dtech的USB转RS232数据线,上述解决方法可能并不适用于其他串口。
改天多搞一些不同厂商的USB转串口线试一试吧,也许这只是个例呢。
所以说实践是检验真理的唯一标准,而理论只能作为参考依据。“理论上能工作“这样的话在电子的世界里就是废话一句。
不说了,该睡觉了。这是我第一篇博客,以后尽量把工作学习中遇到的问题写下来,让知识真正成为经验。欢迎各位看官常来看看。
推荐阅读
- 核心
- day|day 28 设置路由表
- C语言静态动态两版本通讯录实战源码
- Android轻松实现跨进程/跨app通讯框架及其原理
- GD32VF103|GD32VF103 I2C 通讯
- FPGA|DDR3原理总结
- MobIM仅为开发者提供即时通讯的消息通道服务
- 驱动调试小结
- USB转串口|USB转四串口芯片CH9344
- FabEdge V0.4 新特性(支持多集群通讯)