USART串口通信从电路原理到代码实现:STM32零基础入门第XXX步(详细解析)

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

师从洋桃电子,杜洋老师


📑文章目录

  • 一、USART串口基础认知
  • 1. 什么是USART?
  • 2. 典型应用场景
  • 二、硬件电路设计要点
  • 1. USB转TTL电路(CH340C模块)
  • 2. 单片机端电路保护
  • 三、STM32内部寄存器解析
  • 1. 关键寄存器组成
  • 2. 波特率计算公式
  • 四、固件库函数说明(标准外设库)
  • 1. 初始化结构链
  • 2. 常用库函数列表
  • 五、驱动程序逐行解析
  • 1. 初始化配置流程
  • 2. 关键代码解析
  • 六、上位机测试方法
  • 1. 串口助手设置参数
  • 2. 数据接收验证
  • 七、进阶应用技巧
  • 1. 字符串发送优化
  • 2. 中断接收配置
  • 八、常见问题排查表
  • 九、相关资源

  • 一、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 控制寄存器1 UE=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)
  • 作者:触角01010001

    物联沃分享整理
    物联沃-IOTWORD物联网 » USART串口通信从电路原理到代码实现:STM32零基础入门第XXX步(详细解析)

    发表回复