第二次作业——UART

UART

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,通常称作UART) 是一种串行异步收发协议,应用十分广泛。UART工作原理是将数据的二进制位一位一位的进行传输。在UART通讯协议中信号线上的状态位高电平代表’1’低电平代表’0’。当然两个设备使用UART串口通讯时,必须先约定好传输速率和一些数据位。

空闲位:
UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平
起始位:
开始进行数据传输时发送方要先发出一个低电平’0’来表示传输字符的开始。因为空闲位一直是高电平所以开始第一次通讯时先发送一个明显区别于空闲状态的信号即为低电平。
数据位:
起始位之后就是要传输的数据,数据可以是5,6,7,8,9位,构成一个字符,一般都是8位。先发送最低位最后发送最高位。
奇偶校验位:
数据位传送完成后,要进行奇偶校验,校验位其实是调整个数,串口校验分几种方式:
1.无校验(no parity)
2.奇校验(odd parity):如果数据位中’1’的数目是偶数,则校验位为’1’,如果’1’的数目是奇数,校验位为’0’。
3.偶校验(even parity):如果数据为中’1’的数目是偶数,则校验位为’0’,如果为奇数,校验位为’1’。
4.mark parity:校验位始终为1
5.space parity:校验位始终为0
停止位:
数据结束标志,可以是1位,1.5位,2位的高电平。
波特率:
数据传输速率使用波特率来表示,单位bps(bits per second),常见的波特率9600bps,115200bps等等,其他标准的波特率是1200,2400,4800,19200,38400,57600。举个例子,如果串口波特率设置为9600bps,那么传输一个比特需要的时间是1/9600≈104.2us。
在这里插入图片描述
以9600 8N1(9600波特率,8个数据位,没有校验位,1位停止位)为例,这是目前最常用的串口配置,现在我们传输’O’'K’两个ASCII值,'O’的ASCII为79,对应的二进制数据为01001111 ,'K’对应的二进制数据为01001011 ,传输的格式数据如下图所示:
以9600 8N1(9600波特率,8个数据位,没有校验位,1位停止位)为例,这是目前最常用的串口配置,现在我们传输’O’'K’两个ASCII值,'O’的ASCII为79,对应的二进制数据为01001111 ,'K’对应的二进制数据为01001011 ,传输的格式数据如下图所示:
在这里插入图片描述

题目分析

在这里插入图片描述
既然波特率是1000 bps,所以我们可以知道传输每一个bit所需要的时间是1/1000 s = 1ms,在这里我们只需要知道它的原始意义,就是每秒传输1000bit。而题目中给的时钟信号clk是40kHz的,所以每秒有40k个时钟周期。因此,其实就是,每个bit有40个时钟周期采样,我们取中间的采样值,以保证不会滑码和误码。

一共传输10个bit,所以每次传输使用400个时钟周期。

当然,分析到这里并不代表着我就能自己写出来了。依在下的功力,当然还需要借鉴一些大佬的思路。于是我找了Zach_z的一篇博客,他在里面详细地描述了它的思路,用代码。我觉得十分有道理,于是总结来说就是:

8位要传输的数据,首尾加上起始位和终止位(在这里没有用到校验位),每四十个时钟周期改变一次 bit_out 的值,然后在接受的时候,也是每四十个周期接受一次 bit_in 的值,但是与发送的每个40交错20,就是通信原理里学的在中间位置采样。

因为这个Z大佬写的程序没有给testbench,所以上午我写了两个模块之后不知道怎么把它们联合起来。于是像往常一样,又向肥子同学伸出了求救的双手,给了一份去年老师写的tb文件。而且,我还有一个巨大的疑问,因为老师给的模块里只有send_start,用来起始发送过程,并没有出现接受过程的起始信号,我陷入沉思……然后看了老师的tb,又找了另外几个大佬的博客,结论是:我就是个菜鸡嘛,人家都说了有起始位了,之前一直是1,当传输开始的时候会突然出现一个0,然后开始接收过程。

我看了一下,tb是这样联合起来的
在这里插入图片描述
简直不能更有道理了!bit_in 不就是时时刻刻应该等于 bit_out 嘛,这也纠正了我从刚开始就有的一个误区——一位一位的传输意思是发送一位就接收一位,这个过程是时刻吻合的,而抽样是在40’ 中间。

学到了学到了。

不过我还是给了一个recv_flag 信号,用来告知receive过程的进行,以及计数器cnt的不断increment。

心得

这玩意在下写了一整天,从吃完早饭大概十点(hhh我知道起床太晚),到晚上遛弯回来终于改完最后一个bug(关于这个bug我要说一下,每个模块的命名要和里面module的命名相一致,不然会冒出根本找不到源头的错误,就这个错误我就找了一个多小时……关键这种错误会让你以为是程序写错了,虽然也确实有点错hhh),现在是九点二十,终于终于,出了正确的结果。

这之中还包括着对着自己的代码陶醉了很久^-^,UE可真香啊。

上图!!!
在这里插入图片描述
值得一提的是,前面说过的那个遛弯回来解决的bug,遛弯之前死活就是没找出来,结果回来之后一改就改对了(虽然是个愚蠢的错误)。刚刚又恰好看了一篇文章《如何像高级开发人员一样思考》,里面讲怎么开发我倒是一点都没看懂,但是他说,“每当你在同一个问题或者错误上连续工作一小时,那么就应该尝试休息一下,因为有时问题就出在我们自己身上。”

嗯!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值