前言:上一篇文章中说到了UART的数据帧格式以及它的几种工作模式,在实际应用场合中,UART协议大多通过集成在MCU模块中的硬件逻辑来实现。为了更好的理解UART,在这里写篇文章用软件模拟串口通信,加深印象。
一、模拟前的准备
1.工作模式的选择
- 这里选择最常见异步全双工模式,无校验位,即TX和RX分别用于收发数据,可同时进行。因为这种模式相比其他的最具有代表性,也比较容易模拟,毕竟学东西都是由易到难的模式 :)
2.数据的格式
- 这里设定的数据帧格式为1位起始位+8位数据位+1位停止位 = 10位数据位。
3.波特率的选择
- 这里的波特率选择4800Bd/s,之前说过UART下,码元的状态只有0或1两种,所以此时波特率=比特率,即此时比特率为4800bps。
4.传输时间的计算
- 按上述所说,1s可以传输4800个bit,所以传输一个Bit的时间是1/4800s = 208us。
5.程序模式的设计
- 为了便于理解和模拟,这里采用定时器计数轮询的方法,只要含有定时器的可编程芯片都能轻易实现。
6.数据结构的设计
- 1)状态控制
uint8_t UART_SCON; //模拟控制寄存器,可控制UART是否有效
#define RIEN (1<<0)
#define TIEN (1<<1)
uint8_t UART_ISR; //模拟状态寄存器
#define RI_Bit (1<<0) //标志传送或接收一个字节的过程中
#define TI_Bit (1<<1)
#define RI_Byte (1<<2) //标志传送或接收一个字节完成
#define TI_Byte (1<<3)
#define UART_TXD_Port M0P_GPIO->P3OUT //定义传送或接收引脚
#define UART_RXD_Port M0P_GPIO->P3IN
#define UART_TXD_Pin 1<<5
#define UART_RXD_Pin 1<<6
#define UART_BitNum 10 //1bit起始位+8bit数据位+1bit停止位 = 10
#define UART_BitCnt 13 //7 9600 //52 1200 //13 4800
注:上述代码中的UART_BitCnt是传送一个Bit需要多少个计数周期。笔者使用的定时器为16us定时器,4800的波特率,计算方法为1/4800*1000000/16 = 13,表示传送一个Bit需要的13个16us的时间。
- 2)发送数据
typedef struct{
uint8_t BitNum; //用于计数传送了第几个Bit
uint8_t BitCnt; //用于计数每个Bit传送需要时间
uint16_t BitSndBuf; //存储要传送的Bit,包括起始位、数据位和停止位
uint8_t SBUF; //要发送的一个字节数据的缓存
}UART_Tran;
- 3)接收数据
typedef struct{
uint8_t BitNum; //计数接受的Bit数
uint8_t BitCnt