这里以stm32f4系列的标准库为应用案例解释
1 串口介绍
1.1 初步介绍
STM32F407系列包含最多6个USART/UART接口。 4个通用同步/异步收发器(USART),2个通用异步收发器(UART)。
具体型号的可用串口数量可能不同,需参考具体型号的数据手册。
1.2 主要特性
1.2.1 USART特性
全双工异步通信
单线半双工通信
同步通信(需要时钟线)
支持LIN协议
支持智能卡协议(ISO7816)
支持IrDA SIR ENDEC规范
支持调制解调器操作(CTS/RTS)
1.2.2 UART特性
全双工异步通信
单线半双工通信
支持LIN协议
支持IrDA SIR ENDEC规范
支持调制解调器操作(CTS/RTS)
1.3 主要寄存器
每个USART/UART包含以下主要寄存器:
USART_SR - 状态寄存器
USART_DR - 数据寄存器
USART_BRR - 波特率寄存器
USART_CR1/CR2/CR3 - 控制寄存器
1.4 波特率计算
波特率计算公式:
波特率 = fCK / (16 * USARTDIV)
其中:
fCK是USART时钟频率(APB1或APB2总线)
USARTDIV是写入USART_BRR寄存器的值
1.5 常用工作模式
1.5.1 轮询模式:
简单直接
占用CPU资源
适合低速率或简单应用
1.5.2 中断模式:
数据收发通过中断处理
提高CPU利用率
需要配置NVIC
1.5.3 DMA模式:
高效数据传输
适合大数据量传输
需要配置DMA控制器
1.6 常见应用
- 与PC通信(通过USB转串口)
- 与GPS模块通信
- 与无线模块(如蓝牙、WiFi)通信
- 工业设备间的RS232/RS485通信
- 调试信息输出
1.7 注意事项
确保时钟配置正确(USART时钟使能)
注意GPIO复用功能配置
不同USART挂载在不同APB总线上,时钟频率可能不同
使用DMA时注意缓冲区管理
在低功耗应用中注意唤醒源配置
2 软件层面协议
2.1 基本概念
串口通信是一种常见的设备间通信方式,以下是关于串口通信协议的全面介绍。串口通信(Serial Communication)是指通过单根数据线按位顺序传输数据的通信方式,与之相对的是并行通信。
2.2 物理层标准
2.2.1 RS-232硬件标准
最传统的串口标准
电压范围:±3V至±15V
典型DB9连接器
传输距离短(约15米)
2.2.2 RS-422:
差分信号传输
传输距离可达1200米
全双工通信
2.2.3 RS-485:
改进的RS-422
支持多点通信(最多32个节点)
半双工通信
工业环境常用
2.3 协议核心参数
2.3.1 波特率(Baud Rate):
波特率即每秒钟传输二进制信息的位数,单位是为位/秒(bps或bit/s)。如每秒钟传输240个字符,每个字符帧格式包含10位(1个起始位、1个停止位、8个数据位),则此时的波特率为:
传输距离与波特率及传输线的电气特性有关。当传输线使用每0.3m(约1英尺)有50pF电容的非平衡屏蔽双绞线时,传输距离随波特率的增加而减小。当波特率超过1000 bps 时,最大传输距离迅速下降,如115200 bps 时最大距离下降到只有30m。
常见值:9600, 19200, 38400, 57600, 115200等
通信双方必须一致
2.3.2 数据位(Data Bits):
通常5-9位,常用8位
2.3.3 停止位(Stop Bits):
1位、1.5位或2位
用于标识数据包结束
2.3.4 校验位(Parity Bit):
可选:无校验(None)、奇校验(Odd)、偶校验(Even)
用于简单错误检测。
若设置为奇校验,则当接收方接收到数据时,校验“1”的个数是否为奇数,从而确定数据传输是否正确;若设置为偶校验,则当接收方接收到数据时,校验“1”的个数是否为偶数,从而确定数据传输是否正确;若设置为无校验,则不对数据传输的正确性做判断。
2.4 数据帧结构
3 代码
#include "stm32f4xx_usart.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
void USART_Config(void) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
// 1. 时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 2. 配置 PA9(TX) 和 PA10(RX)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置复用功能
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
// 3. 配置 USART1
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
// 4. 启动 USART
USART_Cmd(USART1, ENABLE);
}
void USART1_SendChar(uint8_t ch) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}