(注:如果本文有代码 则均搜索于网络或本人编写仅供学习之用)
UART是我们经常用到的通信方式之一,无论是RS232 RS485或者两机通信都离不开它
在使用单片机或者ARM时我们可以简单的通过配置寄存器或者调用API函数就能实现uart的
起始位,停止位,数据位数,奇偶校验,以及波特率控制
一般我们的操作流程是(不带FIFO的情况)
将数据放入一个寄存器假设为uart_buf 一个9位寄存器(或者更多)
假如需要奇偶校验那么状态寄存器中有一位状态位就是奇偶校验位直接给寄存器的第九位即可
单片机内部会根据波特率和起始位设置自动把数据一位一位的发出去
发送完成后会置标志并通知单片机发送完成
我们也可以随时查看发送缓冲区是否有数据 或者是否为空
当然目前的uart设计都预留了缓冲区以节省cpu的时间 提高了效率 底层自己处理
起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。
数据位:紧接着起始位之后。资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用
ASCII码。从最低位开始传送,靠时钟定位。
奇偶校验位:资料位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此
来校验资料传送的正确性。
停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。
空闲:处于逻辑“1”状态,表示当前线路上没有资料传送
波特率:是衡量资料传送速率的指针。表示每秒钟传送的二进制位数。例如资料传送速率为120
字符/秒,而每一个字符为10位,则其传送的波特率为10×120=1200字符/秒=1200波特。
这里先设计一个最原始的UART发送器
波特率9600,奇偶校验无,数据位8,停止位1
这个设计比较重要的地方就是时钟和时序的问题 如何产生准确的9800bps的速率问题
设计思路 先计算发送一位的时间 然后用计数器对系统时钟计数到发送时间后 发送一位 然后继
续计数以此类推 算出发送一个字节的整个时间和时序
以波特率9600为例子说明,波特率9600接收一个bit的时间为1s/9600=104us,即每隔104us发
送一个数据。
104us = 104000ns 50M时钟的一个周期时间为20ns要远小于104000ns,所以可以用50M时钟
产生的计数器来计数,然后根据计数器来发送数据。
新建一个计数器,50Mhz为时钟,那么计数器变化一次时间为20ns。
由于一次完整数据接收需要有1144000ns时间,所以计数器必须记到1144000ns时间。
1144000ns/20ns = 57200 ,所以需要16位计数器。
Startbit(0)占据计数器的0 -104000ns/20ns = 5200
D0 占据计数器的5200-208000ns/20ns = 10400
D1 占据计数器的10400-312000ns/20ns = 15600
D2 占据计数器的15600-416000ns/20ns = 20800
D3 占据计数器的20800-520000ns/20ns = 26000
D4 占据计数器的26000-624000ns/20ns = 31200
D5 占据计数器的31200-728000ns/20ns = 36400
D6 占据计数器的36400-832000ns/20ns = 41600
D7 占据计数器的41600-936000ns/20ns = 46800
校验位 占据计数器的46800-1040000ns/20ns = 52000
Endbit(1) 占据计数器的52000-1144000ns/20ns = 57200
也可以用类似的思路
比如每隔5200一个计数器加1则
加到10后从0开始
根据此计数器来判断要发送的位
大致代码流程
时钟上升沿计数 以产生波特率时钟
适当的时候获取要发送的数据data
然后按照上面的时间节点发送数据到uart输出口
计数到57200从0开始
网上有设计好的uart实例大家可以学习了 自己使用
文章评论(0条评论)
登录后参与讨论