USART串口通信详解:从电路原理到代码实现 | 零基础入门STM32第三十三步

主题内容教学目的/扩展视频
串口通信重点课程什么是USART串口,电路原理,单片机内部寄存器,固件库说明。加载相关文件,驱动程序分析,printf的使用。什么是中断,中断的程序设计,还有哪些中断。熟悉串口的使用,熟练使用printf函数。介绍printf函数的高级使用方法,介绍各中断。

师从洋桃电子,杜洋老师



一、USART串口基础认知

1. 什么是USART?

USART(Universal Synchronous/Asynchronous Receiver/Transmitter)是一种通用串行通信接口,具备以下特点:

  • 双工通信:支持同时收发数据
  • 可配置参数:波特率(600-115200bps)、数据位(8/9位)、停止位(1/1.5/2位)
  • 电平标准:TTL(3.3V/5V)与RS232(±12V)两种版本

2. 典型应用场景

  • 单片机与PC通信
  • 工业设备数据采集
  • 无线模块(WiFi/蓝牙)数据传输
  • 嵌入式系统调试信息输出

二、硬件电路设计要点

1. USB转TTL电路(CH340C模块)

(图1:USART通信连接原理图)
STM32          CH340C
PA9(TX)  ---> RX
PA10(RX) ---> TX
GND      ---> GND

注意事项

  • 需共地连接确保电平基准一致
  • 避免超过芯片最大输入电压(CH340C支持3.3V/5V自适应)

2. 单片机端电路保护

  • 串联220Ω电阻防止信号过冲
  • 添加TVS二极管防静电
  • 对VCC和GND加0.1μF去耦电容

三、STM32内部寄存器解析

1. 关键寄存器组成

寄存器名称功能描述常用配置值
USART_CR1控制寄存器1UE=1(使能USART)
USART_CR2控制寄存器2(停止位设置)STOP[1:0]=00(1位停止位)
USART_BRR波特率寄存器根据公式计算得出

2. 波特率计算公式

波特率 = fCK / (16 * USARTDIV)
/* 
  示例:115200bps @72MHz主频
  USARTDIV = 72000000/(16*115200) = 39.0625
  BRR = 0x273   // 整数部分39=0x27,小数0.0625*16=1
*/

四、固件库函数说明(标准外设库)

1. 初始化结构链

void USART1_Init(u32 bound){ //串口1初始化并启动
├── GPIO端口设置
├── USART1_TX   PA.9
├── USART1_RX	  PA.10
├── Usart1 NVIC 配置
├── USART 初始化设置

参数结构体解析

typedef struct {
  uint32_t USART_BaudRate;     // 波特率
  uint16_t USART_WordLength;   // 数据位(USART_WordLength_8b/9b)
  uint16_t USART_StopBits;     // 停止位(USART_StopBits_1/1.5/2)
  uint16_t USART_Parity;       // 校验位(USART_Parity_No/Even/Odd)
  uint16_t USART_Mode;         // 工作模式(USART_Mode_Rx | USART_Mode_Tx)
} USART_InitTypeDef;

2. 常用库函数列表

函数名称功能描述
USART_Cmd()使能/禁用USART
USART_SendData()发送单字节数据
USART_ReceiveData()接收单字节数据
USART_GetFlagStatus()查询状态标志位
USART_ITConfig()中断使能控制

五、驱动程序逐行解析

1. 初始化配置流程

#include "stm32f10x.h"
#include "usart.h"

int main(void) {
    RCC_Configuration();        // 时钟设置
    USART1_Init(115200);        // 初始化参数配置
    
    while(1) {
        // 发送方法:轮询方式
        USART_SendData(USART1, 0x55);  // 写入发送数据寄存器
        while(!USART_GetFlagStatus(USART1, USART_FLAG_TC)); // 等待发送完成
        delay_ms(1000);                // 延时控制发送间隔
    }
}

2. 关键代码解析

RCC配置函数

void RCC_Configuration(void) {
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
}

USART初始化函数

void USART1_Init(u32 bound){ //串口1初始化并启动
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
     //USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
    //USART1_RX	  PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
   //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器 
   //USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART1, &USART_InitStructure); //初始化串口
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断
    USART_Cmd(USART1, ENABLE);                    //使能串口 
}

完整工程代码示例⏬USART串口发送程序

六、上位机测试方法

1. 串口助手设置参数

参数项设置值
波特率115200
数据位8
停止位1
校验位None
流控制

2. 数据接收验证

当单片机发送0x55(二进制01010101)时:

  • 十六进制显示:55
  • ASCII显示:字符"U"
  • 波形测量:使用示波器可观测到方波信号(115200bps对应8.68μs/bit)

⏬DYS串口助手 V1

七、进阶应用技巧

1. 字符串发送优化

USART1专用的printf函数
当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数
调用方法:USART1_printf("123"); //向USART2发送字符123
*/
void USART1_printf (char *fmt, ...){ 
	char buffer[USART1_REC_LEN+1];  // 数据长度
	u8 i = 0;	
	va_list arg_ptr;
	va_start(arg_ptr, fmt);  
	vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);
	while ((i < USART1_REC_LEN) && (i < strlen(buffer))){
        USART_SendData(USART1, (u8) buffer[i++]);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 
	}
	va_end(arg_ptr);
}

2. 中断接收配置

void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改)	
	u8 Res;
	//以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是数据的长度(不包括回车)
	//当(USART1_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。
	//在主函数里写判断if(USART1_RX_STA&0xC000),然后读USART1_RX_BUF[]数组,读到0x0d 0x0a即是结束。
	//注意在主函数处理完串口数据后,要将USART1_RX_STA清0
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){  //接收中断(接收到的数据必须是0x0d 0x0a结尾)		
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑		
		if((USART1_RX_STA&0x8000)==0){//接收未完成			
			if(USART1_RX_STA&0x4000){//接收到了0x0d				
				if(Res!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
				else USART1_RX_STA|=0x8000;	//接收完成了 
			}else{ //还没收到0X0D					
				if(Res==0x0d)USART1_RX_STA|=0x4000;
				else{
					USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组
					USART1_RX_STA++;	//数据长度计数加1
					if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	} 
} 

八、常见问题排查表

现象可能原因解决方法
无任何数据接收1. 线序接反(TX-RX交叉)
2. 波特率不匹配
检查硬件连接
核对双方波特率
接收数据乱码1. 地线未连接
2. 时钟源偏差
确保共地
使用精准晶振
只能发送不能接收RX引脚配置错误检查GPIO模式设置

实验建议:使用逻辑分析仪捕获实际通信波形,观察起始位、数据位、停止位的时序关系


九、相关资源

[1] 洋桃电子B站课程-STM32入门100步
[2] STM32F103xx官方数据手册
[3] STM32F103X8-B数据手册(中文)
[4] STM32F103固件函数库用户手册(中文)
[5] USART串口发送程序
[6] DYS串口助手 V1
[7] CH340C 数据手册


💬 技术讨论(请在评论区留言~)

📌 下期预告:下一期将探讨USART发送程序重点课程,欢迎持续关注!

点击查阅🔍往期【STM32专栏】文章

版权声明:本文采用[CC BY-NC-SA 4.0]协议,转载请注明来源
实测开发版:洋桃1号开发版(基于STM32F103C8T6)
更新日志

  • v1.0 初始版本(2025-02-27)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值