目录
一、简介
1.概念
USART(Universal Synchronous Asynchronous Receiver Transmitter,通用同步异步收发器)是一串行通信设备,可以灵活地与外部设备进行进行全双工信息交换。
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器 )是一种双向、串行、异步的通信总线,仅用一根数据接收线和一根数据发送线就能实现全双工通信。
两者相似,UART是在 USART 的基础上裁剪了同步通信功能,只保留异步通信功能,我们平时使用的串口通信都是 UART。
2.结构
任何 UART 双向通信至少需要 3 个引脚,数据发送引脚 TXD,数据接收引脚 RXD,数据参考地 GND。这里特别需要注意的是连接方法,设备 A 和设备 B 信号需要交叉连接。如果电平不同,需要电平转换芯片。
ARM芯片和PC机的电平不同需接入电平转换芯片如RS232
这里解释下电平标准,根据使用使用的电平标准不同,可以分为 TTL 和 RS232 标准, 如图所示:
因为控制器一般都是 TTL 标准,因此如果需要进行 RS232 通信时,一定要使用 R232 转换器进行 TTL 和 RS232 的电平转换。
3.特点
① 空闲时,RXD 和 TXD 默认高电平
②数据起始位为低电平,低位在前,高位在后,串口数据一般为8位
③串口可选择是否开启数据校验,校验位:单个字节数据校验,对数据中高低电平数据个数进行计数,常见的有奇偶校验。
4.优缺点
优点:
- 简单性:实现简单,硬件需求少。
- 无时钟信号:无需设备之间的时钟同步。
- 广泛支持:被微控制器和外围设备广泛支持。
缺点:
- 距离限制:适用于短距离通信,长距离会受到噪声和信号衰减的影响。
- 速度限制:与SPI或I2C等同步通信协议相比,数据传输速率较低。
- 单设备通信:主要设计为点对点通信,若要多设备通信需要额外的电路。
二、协议帧组成
在 UART中,传输模式为数据包形式。数据包由起始位、数据帧、奇偶校验位和停止位组成。
1.起始位
用于指示数据传输的开始。接收器通过检测到逻辑低电平来识别传输的开始。不传输数据时保持高电平(1),开始传输数据后变为低电平(0)。
2.数据位
实际传输的数据。数据位的长度可以在通信双方协商时设置,通常为5到9位(常见的是8位)。不使用奇偶校验位为9位。
3.奇偶校验位
用于错误检测。常见的校验方式包括偶校验(Even Parity)和奇校验(Odd Parity)。偶校验时,数据帧中的1的个数为偶数;奇校验时,1的个数为奇数。如果奇校验时 ,而数据帧1的总和为偶数,或者偶校验时 ,而总和为奇数,则UART 认为数据帧中的位已改变。如果不用校验位,可以省略这一部分。
4.停止位
指示数据传输的结束,并用于接收器同步和复位。停止位提供了一段时间让接收器准备好接收下一帧数据。发送 UART 将数据传输线从低电压驱动到高电压并保持1 到 2 位时间。
示例:
假设发送8位数据,没有校验位,1位停止位,数据为
0x55
(即二进制01010101
),其UART帧结构如下:| 起始位 | 数据位 | 停止位 |
| 0 | 01010101 | 1 |
三、UART通信过程
发送器:
- 发送器开始发送起始位。
- 紧接着发送数据位(从LSB到MSB)。
- 如果启用了校验,发送校验位。
- 最后发送停止位。
接收器:
- 接收器通过检测起始位(逻辑低)开始数据接收。
- 按照预设的波特率,依次接收数据位。
- 检查校验位(如果有)进行错误检测。
- 检测到停止位(逻辑高)后,完成一帧数据的接收。
四、USART与UART区别
|-----------|---------------------------------|-------------------------------------------------|
| | UART | USART |
| 配置和使用 | 只需配置波特率、数据位、校验位和停止位,适用于简单的点对点通信 | 除了和UART一样的配置外,还需要配置同步模式的时钟设置,适用于需要高精度、高速度的通信场合。 |
| 数据传输 | 例如,9600波特率下,每秒可以传输9600个比特 | 在同步模式下,可以通过更高的时钟频率实现更高的数据传输率 |
例子:
UART数据传输:
- 发送端:数据
0x55
(二进制01010101
),波特率9600,无校验位,1个停止位。- 接收端:检测到起始位后,按配置的波特率读取数据位,校验(如果有),然后等待停止位。
USART数据传输(同步模式):
- 发送端和接收端共享时钟信号。
- 发送端:数据
0x55
(二进制01010101
),时钟频率为1MHz。- 接收端:同步时钟信号,按时钟频率读取数据位,实现更高的传输速率。
五、代码实现
本次实验的效果是重定义printf函数输出Hello world!
1.硬件框图
2.软件实现
①初始化结构体
cpp
UART_Config_t tUartCfgStruct =
{
9600, /* 波特率选择*/
UART_DATABITS_8, /* 数据位大小 */
UART_PARITY_NONE, /* 奇偶校验位选择*/
UART_STOPBITS_1, /* 停止位 */
DISABLE, /* 数据流控制 */
40000000 /* 函数时钟频率选择 */
};
/* 初始化结构体配置 */
UART_Init(UART1_ID, &tUartCfgStruct);
②串口接收函数
cpp
unsigned char ch;
/* 等待清除DR寄存器 */
while (RESET == UART_GetLineStatus(UART1_ID,UART_LINESTA_DR));
/* 接收数据 */
ch = UART_ReceiveByte(UART1_ID);
③串口发送函数
cpp
/* 等待状态寄存器TEMT复位 */
while(RESET == UART_GetLineStatus(UART1_ID,
UART_LINESTA_TEMT));
/* 发送数据ch */
UART_SendByte(UART1_ID, ch);
}
}
④重定义printf
cpp
unsigned char ch[100];
int fputc(int ch, FILE *f)
{
(void) f;
/* Wait untill FIFO is empty */
while(RESET == UART_GetLineStatus(UART1_ID, UART_LINESTA_TEMT))
{
}
/* Send data */
UART_SendByte(UART1_ID, (uint8_t)ch);
return ch;
}
代码简单的介绍了串口发送和接收的函数以及重定向printf进行打印,代码很简单所以没有放入完整代码,有学习使用智芯开发板的小伙伴们可以留言一起进行交流。