【STM32】基础知识 第十四课 串口通信: 深入探究与应用
- 概述
- 串口通信的基本原理
- 串行通信 & 并行通信
- 串行通信
- 并行通信
- 串行 vs 并行
- 单工/半双工/全双工
- 单工通信
- 半双工通信
- 全双工通信
- 总结
- 同步通信/异步通信
- 同步通信
- 异步通信
- 波特率
- 常见的串行通信接口
- STM32 串口配置
- STM32 串口中断处理
- 案例
概述
在嵌入式系统中, 串口通信是一种常见的通信方式, 特别是在单片机领域. STM32 系列单片机提供了强大的串口 (UART) 功能, 可支持多种通信模式. 今天小白将带领大家深入探讨 STM32 的串口通信, 包括其基本原理, 配置方法, 中断处理及实际应用示例.
串口通信的基本原理
串口通信 (Serial Communication) 是一种基于串行数据传输的通信方式. 在串行通信中, 数据是按位序列一个接一个地传输的. 这种方式的优先是只需较少的硬件接口 (1 条数据线和 1 条地线), 但缺点是传输速度较慢. 串口通信有多种标准, 其中最常见的是 RS-232, RS-422 和 RS-485.
在 STM32 中, UART (Universal Asynchronous Receiver/Transmitter, 通用异步收发器) 是实现串口通信的关键硬件. UART 可以将并行数据转换为并行数据.
串行通信 & 并行通信
串行和并行通信是两种主要的数据传输方式. 各自有优点和缺点.
串行通信
串行通信的数据为按顺序一次只发送以. 这种方法的主要优点是它只需要少量的屋里连接. 只需要一对线 (一条发送线和一条接收线) 即可实现两个设备之间的双向通信. 此外, 由于数据在物理线路上逐位传输, 应此电缆长度可以相对较长, 而不会出现信号衰减或衰减同步的问题.
串行通信的主要缺点是其相对较慢的数据传输速率. 每个数据位都需要在特定的时钟周期内发送, 因此大量数据传输可能需要较长的时间.
常见的串行通信接口有 UART (通用异步接收/发送器), SPI (串行外设接口) 和 I2C (双向串行总线) 等.
并行通信
并行通信是一种数据传输方式, 其中多个数据位同时通过多个通道 (物理线路) 发送. 这种方法优点是其快速的数据传输速率. 由于数据位同时传输, 因此大量数据的传输可以在很短的时间完成.
并行通信的主要缺点是它需要大量的物理连接. 对于每个要传输的数据位, 都需要一个专用的物理线路. 这可能会增加硬件的复杂性, 并限制电缆的长度, 因为每个线路的信号可能会在不同的时间到达, 从而导致数据位的错位 (这被称为时钟偏斜).
在许多现代系统中, 由于高速串行接口的出现, 如 USB, PCI, Express 和 SATA 等, 以及网络接口, 如 Ethernet, 串行通信已经成为主流. 但在某些特定的内部连接, 如计算机内部的总线, 或者某些特定的并行接口, 如并口打印机, 仍然使用并行通信.
串行 vs 并行
特点 | 传输速率 | 抗干扰能力 | 通信距离 | IO 资源占用 | 成本 |
---|---|---|---|---|---|
串行通信 | 较低 | 较强 | 较长 | 较少 | 较低 |
并行通信 | 较高 | 较弱 | 较短 | 较多 | 较高 |
单工/半双工/全双工
单工, 半双工和全双工都是描述通信系统数传输的术语, 定义了数据在设备之间如何流动.
单工通信
单工通信 (Simplex Communication) 是最基本的通信形式, 数据只能在一个方向上流动. 单工通信就像一个广播系统, 信息从一个中心站 (例如广播塔), 传输出去, 接收器 (例如收音机/电视) 可以接受信息, 但不能发送信息. 单工通信的优点是其结构简单, 但缺点是它不能进行双向通信.
半双工通信
半双工通信 (Half Duplex Communication) 允许数据在两个方向上流动, 但不是同时进行的. 设备必须在发送和接受模式之间切换. 就就像对讲机的工作方式, 一个用户在一次只能说话或听话. 半双工通信的优点是允许双向通信, 但缺点是设备不能同时发送和接收.
全双工通信
全双工通信 (Full Duplex Communication) 允许数据同时在两个方向上流动. 这就像电话的工作方式, 两个用户可以同时说话和听话. 全双工通信的优点是它允许同时进行双向通信, 提高了通信效率. 全双工通信的缺点是它可能需要更复杂的硬件和软件来管理同时的发送和接收.
总结
总的来说, 选择哪种通信模式取决于特定应用的需求. 在需要最简单的硬件和只需要单项通信的应用中, 可以使用单工通信. 在需要双向通信但不需要同时发送和接收的应用中, 可以使用半双工通信. 在需要搞笑的双向通信的应用中, 可以使用全双工通信.
同步通信/异步通信
同步通信和异步通信是数据传输方式的两种分类. 同步通信和异步通信的主要区别在于数据传输的时序和协调方式.
同步通信
在同步通信中, 发送方和接收方都在同一个时钟或相同的频率下工作. 这意味着数据的发送接收都是根据一个共享时钟信号进行定时的. 数据在每个时钟周期或特定的时间段内发送和接收, 因此发送方和接收方必须在这些特定的时间点准备好进行数据的发送和接收.
异步通信
在异步通信中, 数据可以在任何时间发送, 而不是在预定的时间点. 数据通常是以独立的数据包或帧的形式进行发送, 每个数据包或帧都以一个开始信号开始, 并以一个结束信号结束. 这些信号告诉接收方向何时开始和结束数据接收.
数据传输的时序控制对于保证数据的准确性和完整性至关重要. 如果时序控制不正确, 接收方可能会误解数据, 导致通信错误. 因此, 设计和实现数据传输时序是数字通信系统设计的关键组成部分.
波特率
在串行通信中, 波特率是衡量数据传输速率的一个重要参数, 通常以每秒 (bps) 表示. 在 STM32 中, 我们可以通过配置 UART (通用异步接收器发送器) 或 USART (通用同步异步接收发送器) 的寄存器来设定波特率.
STM32 的 UART 或 USART 波特率由以下几个参数决定:
- 系统时钟频率: 这是微控制器的主要时钟源, 通常由内部或外部晶振提供
- 时钟分频系数: 这是在系统时钟和 UART 或 USART 时钟之间设置的分频系数
- 波特率生成器的值: 这是在 UART 或 USART 的寄存器中设置的值, 用于进一步细分 UART 或 USART 的时钟以生成所需的波特率
比特率 vs 波特率:
- 比特率: 每秒钟传送的比特数: 单位 bit/s
- 波特率: 每秒钟传送的码元数, 单位 Baud
- 比特率 = 波特率 * l o g 2 M log_2M log2M, M 表示每个码元承载的信息量
- 二进制系统中, 波特率数值上等于比特率
常见的串行通信接口
通信接口 | 接口 引脚 | 数据同步方式 | 数据传输方向 |
---|---|---|---|
UART (通用异步收发器) | TXD: 发送端 RXD: 接收端 GND:公共地 | 异步通信 | 全双工 |
1-wire | DQ: 发送/接收端 | 异步通信 | 半双工 |
IIC | SLC: 同步时钟 SDA: 数据输入/输出端 | 同步通信 | 半双工 |
SPI | SCK: 同步时钟 MSIO:主机输入, 从机输出 | MOSI:主机输出, 丛集输入 CS: 片选信号 | 同步通信 |
STM32 串口配置
STM32 的串口配置包括设置波特率, 数据位, 奇偶校验等参数. 这些参数必须与通信的另一方保质一致, 才能确保数据的正确传输. 此外, 还需要配置相关的 GPIO 引脚做为 UART 的发送和接收线.
STM32 串口配置步骤:
- 初始化 GPIO 引脚: UART 的 TX 和 RX 引脚通常需要配置为复位功能模式
- 初始化 UART: 设置波特率, 数据位, 停止位, 奇偶校验等参数
- 启用 UART: 最后, 启用 UART 的发送和接收功能
STM32 串口中断处理
STM32 的 UART 支持多种中断源, 包括发送完成, 空闲状态等. 通过中断处理, 我们可以在数据传输完成或出现错误时执行特定的操作, 从而提高程序的响应速度和可靠性.
案例
下面是一个 STM32 串口通信的应用示例. 打印串口发送内容:
#include "./stm32f1xx_it.h"
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
int main(void)
{
uint8_t len;
uint16_t times = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟为72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
while (1)
{
if (g_usart_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
printf("\r\n您发送的消息为:\r\n");
HAL_UART_Transmit(&g_uart1_handle,(uint8_t*)g_usart_rx_buf, len, 1000); /* 发送接收到的数据 */
while(__HAL_UART_GET_FLAG(&g_uart1_handle,UART_FLAG_TC) != SET); /* 等待发送结束 */
printf("\r\n\r\n"); /* 插入换行 */
g_usart_rx_sta = 0;
}
else
{
times++;
if (times % 200 == 0) printf("请输入数据,以回车键结束\r\n");
if (times % 30 == 0) LED0_TOGGLE(); /* 闪烁LED,提示系统正在运行. */
delay_ms(10);
}
}
}
输出结果: