怎么设计串口发送逻辑?

in WhereIN3 years ago

怎么设计串口发送逻辑?

串口发送逻辑似乎比串口接收逻辑要简单一些。因为不需要进行多次采样求平均值。

既然这样的话,那就要先进行建模。首要考虑的是用系统时钟clk和复位rst_n输入作为整个模块控制信号。还要有数据输入的接口[7:0]tx_data。还要有数据输入控制信号,比如什么时候发送数据,一般就是这个触发信号有效时,数据开始发送。而模块的输出就是串行输出接口rs232_tx。这就是整个发送的架构,一般来说这没有问题。不过,我有一个问题,每发送一字节数据就要触发一次吗?这个问题先略过,因为我也现在也不怎么明白。

我们进入详细设计。首先肯定是波特率计数器的问题。还是以9600bps的波特率,50MHz的系统时钟为例,那么波特率计数器需要计5208个数。假设检测到了tx_trig信号为高电平,表示串口要发送数据了。先发送一个起始位,rs232_tx<=start_bit。同时波特率计数器开始计数,所以触发信号的下降沿与起始位的下降沿重合,且此时的波特率计数器的值为1。但是还要看此时bit_cnt这个值的条件。

然后计到最大值5208后,发送下一位数据。if(值达到了5208)rs232_tx<=tx_data[0]。这时波特率计到最大值后变为1,也就是1~5208~1。但这时需要有一个位计数器,用来表示当前发送了第几位,以便发送完成后将波特率计数器清0。一般可以在波特率计数器值达到最大值时将位计数值加1。当计数值达到8的时候,开始发送第8位数据,如果发送停止位,可以使计数值变为9。当计数值为9,且波特率计数器的值最大时,就可以清零了(注意,清零是在下一节拍进行清零)。如果不发送停止位,计到8就可以了。就这样,代码思路完成了。

当然,还可以加入一些控制寄存器,比如发送有效标志位tx_flag,位标志bit_flag等。

假设这就是一款独立的电路,有熟入,有输出,如果在数据传输的过程中,由于干扰或其它原因,输入的数据改变了,那传输的数据由于是直接在输入端取数,肯定也会发生变化,这时传输的数据就乱了。所以,需要增加一个输入寄存器[7:0]tx_data_r来控制这种情况。

一般来说,复位时,这个寄存器的值被复位为0。什么时候被载入输入数据呢?数据被触发发送到真正的发送需要1个时钟周期。可以在触发信号产生时将数据存入输入寄存器,这时需要在数据存入寄存器后,开始发送,这时就比触发信号延迟了两个时钟周期。所以这时需要有一个“数据已经被存到输入寄存器”的标志位tx_flag。也就是“如果检测到触发信号”,寄存数据到输入寄存器,同时产生标志位信号,然后检测到标志位信号,启动波特率计数器,同时发送起始位。也就是波特率计数器为1的时候,同时发送起始位。后面和前面分析一样。

但是同样会出现另外一种意外,就是数据传输过程中触发信号不小心启动了一次,这时候输入寄存器里的值又会被更新。还是有问题。但是可以借助刚才产生的标志位来判断,因为标志位一开始是低电平,触发之后,标志位就变成了高电平,所以可以规定只有满足有触发且标志位为0时,数据才会存入寄存器。这样就不会有问题了。

但是串口没有发送数据时输出会存在一个状态,那就是高电平,也就是空闲状态输出高电平,而停止位也是高电平。那是不是发送完数据直接到空闲状态就可以呢?还真的可以这样。在波特率计数器达到最大值时,位计数器会加1,直到发送完第8位数据,波特率计数器达到最大,就可以将位计数清0了,同时将发送标志清0。然后检查发送标志,如果为零,发送模块输出为高。但是这样停止位会有一个时钟周期的延时。不如直接在位计数器清零时直接将输出拉高。

但是我发现一个问题就是,因为触发tx_trig之后会产生发送标志tx_flag,同时寄存数据,tx_flag触发波特率计数,并且判断此时的bit_cnt的值,再进行发送,这样就会延迟一个节拍,实际是在波特率计数器baud_cnt为1的时候发送起始位@_@。但是位计数器bit_cnt会在baud_cnt为1时更新,那么第二个数据会在baud_cnt=2时发送,相当于起始位计了5029(1~5027~0~2)个数,虽然没有很大影响,但确实是不严谨的地方。如果不使用bit_flag,而直接在baud_cnt等于5027的时候对bit_cnt赋值,那么bit_cnt在baud_cnt为0时更新,数据在baud_cnt为1时发送,那么1~5027~0~1就对了。

有的设计也会输出发送标志位作为发送状态标志。当然也可以用多路选择器加入波特率选择模块。还可以输出发送完成标志。

不过,我发现if(tx_trig)tx_data_r<=tx_data;按理说,tx_data_r的更新要延后一拍,但是仿真时并未延迟,包括tx_flag也没有延迟,这是叫我疑惑的地方。可能正是由于同时变的,tx_trig,tx_data,clk同时发生变化,所以才产生如此的现象,实际情况下,如果数据延迟一些,tx_data_r和tx_flag应该就会有相应的延迟。

其实我忽然想到下次弄一个结构框图可能就容易理解很多。

[WhereIn Android] (http://www.wherein.io)

Sort:  

大神,谢谢分享😂

[WhereIn Android] (http://www.wherein.io)

😂更要谢谢你哟

[WhereIn Android] (http://www.wherein.io)

哇塞!shop

[WhereIn Android] (http://www.wherein.io)

谢谢

[WhereIn Android] (http://www.wherein.io)

周末愉快☕

[WhereIn Android] (http://www.wherein.io)

周末愉快😊

[WhereIn Android] (http://www.wherein.io)

This post has been rewarded by the Steem Community Curation Project #wherein

昨天明明把手机放在桌上,今天又找不到了 ( ˘︹˘ )
咦?你是谁?我又是谁?
加入我们微信群没?还没的话赶快加我们瓜子老板。很帅的 iguozi <(^,^)>

Ha recibido un voto a favor de la comunidad WHEREIN, impulsada por STEEMIT INC. Gracias por usar WHEREIN

Terimakasih Sudah Menggunakan WhereIn, Postingan Anda Terpilih Untuk Mendapatkan Upvote Dari WhereIn Dan Di Dukung Oleh Steemit.inc !

Coin Marketplace

STEEM 0.18
TRX 0.16
JST 0.030
BTC 62405.22
ETH 2436.36
USDT 1.00
SBD 2.62