arduino向串口发送数据时掉包_串口收发模块设计

本文介绍了Arduino串口收发模块的设计,包括串口发送、接收、波特率生成、FIFO模块等。通过FIFO解决数据发送时的延迟问题,允许连续写入多个字节而无需等待,提高串口通信效率。同时,文章详细讲解了波特率计数器的计算和FIFO模块的配置与工作原理。
摘要由CSDN通过智能技术生成

串口收发模块设计

作者:巩文宏 公众号:数字积木

该串口收发模块有串口发送模块,串口接收模块,波特率生成模块,发送数据fifo模块,接收数据的fifo模块组成。
默认配置下,要求输入的参考时钟为50MHz,输入输出的波特率默认配置为115200.该设置体现在波特率生成模块中。
整体的设计框架如下:

0ac752a3a71387d653ae153ec8a57ca6.png


端口定义如下:端口名方向描述ClkInput主时钟,默认频率为50MHzRst_nInput复位信号,低有效RsRxInput串口接收端口RSTxOutput串口发送端口Tx_data_in[7:0]Inputtx端要发送的1字节数据Rx_data_out[7:0]outputrx端口接收到的1字节数据Tx_wenInput发送数据的写入使能信号Rx_renInput接收数据的读取使能信号Uart_irqoutput串口中断信号,为高时标志着rx接收到了有效的数据该模块的使用:发送数据
将要发送的数据放置到Tx_data_in[7:0]总线上,同时将Tx_wen置为高,下一个时钟时,该数据会写进tx_fifo中。如要发送多字节数据,则重复上述步骤,每个时钟向TX_FIFO中发送一个字节的数据,tx_fiof的默认深度为256,可以储存256个字节的数据,则一次最多可以发送256字节数据。接收数据
接收到一个字节的有效数据时,该字节立即在Rx_data_out[7:0]端口输出,此时中断信号Uart_irq为高时,读取输出端口的数据,同时将Rx_ren置一个时钟的高电平即可 。 。1,波特率计数模块在波特率生成模块中,生成发送和接收数据的采样时钟,该采样时钟为波特率的16倍频时钟。count_reg 是分频计数器。27为波特率设置为115200时的时钟分频参数。

1fbec6906dc16172ae0212755416e21c.png


设置一个可配置参数 Baud_rate,便可以再顶层例化模块中通过该参数来改变串口的波特率。参数值和对应的波特率如下表所示。默认情况下,配置参数为6,对应的波特率设置为115200.

9f351523c3481f55b5c59ca7decfdf3b.png


分频计数器的参数计算如下:
分频参数 = 主时钟频率/(波特率*16)。
设置为其他常用波特率时,该参数的值为下表:波特率计算的分频参数实际的分频参数配置参数12002604.22604124001302.1130224800651.065139600325.532543840081.481511520027.1276 2,fifo模块 tx_fifo和rx_fifo 都是例化的自定义的fifo模块。该fifo模块预留有参数接口,可以通过改变该参数来改变fifo的深度和数据宽度。
fifo模块用于临时储存串口发送和接收的数据,进行跨时钟预的数据储存。若不使用fifo来暂存数据,由于串口发送数据相对缓慢,则要连续发送多个字节的数据时,必须等待上一个字节发送完成后才能发送下一个字节,则主模块便要不断等待。使用fifo后,便可以将连续多个字节的数据一次性发送到fifo中,发送模块便会自动读取fifo中的数据进行发送,主模块便可以空闲。
接收模块的fifo同理。将接收到的多个数据暂时储存在fifo中,在读取时便可以一次性连续读取多个字节的数据。
当往fifo中写入数据时,写入的第一个字节的数据就会在R_out[7:0]端口输出。将rd信号置高时,读指针指向下一个地址,在下一个时钟将输出下一个字节数据。fifo模块的配置参数和端口定义如下:

d463f1172ad7e9c1510ccf5031a1f6c5.png


定义了一个名为array_reg的内存阵列,该内存阵列的储存深度由参数AWIDTH决定,储存的深度等于 2^AWIDTH.fifo的数据宽度等于DWIDTH。

29addeaa0d5689a7399f2ed7a877d28c.png


在串口模块例化该fifo模块时,将AWIDTH配置为8,DWIDTH也配置为8。即例化了一个数据宽度为8,储存深度为256的fifo模块。

e4d820b48cfd9f9d594b4c905649b608.png

发送数据fifo:
要通过tx端口向其他串口设备发送数据,首先将要发送的数据放置到Tx_data_in[7:0]总线上,同时将Tx_wen置为高,下一个时钟时,该数据会写进tx_fifo中。如要发送多字节数据,则重复上述步骤,每个时钟向TX_FIFO中发送一个字节的数据,tx_fiof的默认深度为64,可以储存64个字节的数据,则一次最多可以发送64字节数据。当数据储存到TX_FIFO中后,fifo的空标志位(empty)不等于零,令发送模块的开发发送标志位(tx_start)等于 ~empty,则当fifo内储存有要发送的数据时,tx_start信号为1,此时,发送模块从TX_FIFO中读取一字节的数据。待这一字节的数据发送完成后,继续读取fifo内储存的下一个发送数据。直至将fifo内储存的数据全部读取完后,empty等于1,tx_start等于0,发送模块不再发送数据。 接收数据fifo:
当接收到rx端口的有效数据时,接收到的数据会临时储存在rx_fifo中,第一个字节的数据就会在Rx_data_out[7:0]端口输出。中断信号 uart_irq 时rx_fifo的空标志位的取反,此时中断信号 uart_irq 为高,标志这接收到了有效的数据。此时将Rx_ren置为高,读指针指向下一个数据的地址,在下一个时钟将输出下一个字节数据。连续将Rx_ren置为高,则可读出储存在rx_fifo中的接收到的数据,并从Rx_data_out[7:0]端口输出,直到fifo中的数据被读完。
故当tx_fifo里每接收到一个数据时,中断信号为高即标志着接收到了数据,同时在接收到的数据就在Rx_data_out[7:0]端口输出。如果每接收到一个有效数据就立即读取,则必须同时发送一个周期的Rx_ren高信号,使得读地址指针指向下一个读地址,以便当接收到新的数据时,也能立即输出。
如果等待接收多个字节的数据才读取的话,此时输出端口直接输出第一个字节的地址,当将Rx_ren信号置高时,每一个时钟输出一个接收到的数据,直到fifo中的数据被读完。3,发送模块
发送模块的端口如下:

0afc55610087fdeb4b6970dcf65842b4.png


当 信号 tx_start 为高时,该模块将此时端口 d_in[7:0]输入的数据按照预定的波特率将该字节的数据从端口tx发送出去, 波特率时钟 b_tick 指定了该模块的波特率。等到该字节数据发送完成后,tx_done信号被置为一个时钟的高电平。tx_done信号连接到tx_fifo的读端口,当tx_done为高时,fifo的读指针指向下一个地址,如果下一个地址还储存有数据,输出端口输出储存在下一个地址中的数据,同时empty信号为0,串口发送模块将继续发送数据。当下一个地址还没有数据时,empty输出为高,数据发送停止。4,接收模块接收模块的端口如下:

431b723f186e027fc86048d6a7901dbf.png


当该模块从rx端口接收到一个有效的字节数据后,rx_done会置高一个时钟,同时接收到的数据从端口dout[7:0]输出。rx_done连接到rx_fifo的写使能端口,接收到的数据将写入到rx_fifo中。5,模块测试通过电脑端串口向FPGA发送数据,FPGA端RX模块接收到数据后再将该数据通过串口在发送到电脑端。
我们连续发送了字符串“123”,在接收端也同样接收到了字符串“123”。

8724a712a329b5c5fa3f0ad4800f5c63.png


这是接收到的三个字符采样得到的时序图。

454acf7f6fec828fa9c959615d5cfebd.png


如下图,当接收到一个字节数据后,uart_irq信号会置高,同时接收到的数据就立刻在rx_data_out[7:0]端口输出。然后将rx_ren信号置高一个时钟,让读地址指针指向下一个地址,则当再次接收到一个新的数据时,该数据也能马上输出。

816af6c05edc1546139d7a9323d0c31e.png

关注公众号:“数字积木”,获取更多精彩内容,技术干货。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值