一、实验说明
本实验使用 STM32F103 串口 USART1 实现:单片机上电后,每隔 1 秒通过串口向上位机(电脑)发送一个字符 'a' 。这是 STM32 串口通信最基础、最核心的入门程序,学会这一段,所有串口发送都能套用。
二、硬件连接
- USART1_TX → PA9
- USART1_RX → PA10
- 开发板 USB 供电
- 串口调试助手接收数据
三、完整代码
1. 整体工作流程
- 系统上电
- 配置中断分组
- 初始化串口:开启时钟 → 配置 TX/RX 引脚 → 设置波特率 → 使能串口
- 进入主循环
- 每隔 1 秒发送一个字符 'a'
- 循环执行,持续发送
2.main.c 主程序文件
// 包含 STM32 标准库底层驱动
#include "stm32f10x.h"
// 主头文件
#include "main.h"
// 串口驱动头文件
#include "usart.h"
/**
* @brief 毫秒级软件延时函数
* @param time: 延时时间,单位 1ms
* @retval 无
*/
void delay(uint16_t time)
{
uint16_t i = 0;
while(time --) // 循环 time 次
{
i = 12000; // 内层循环,控制单次延时长度
while(i --);
}
}
/**
* @brief 主函数
* @retval int
*/
int main()
{
// 设置中断分组(整个工程只配置一次)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 初始化串口 USART1
my_usart_init();
// 死循环,串口发送逻辑放在这里
while(1)
{
// 通过 USART1 发送一个字符 'a'
USART_SendData(USART1,'a');
// 延时 1 秒,避免发送过快导致电脑卡顿
delay(1000);
}
}
① 延时函数
void delay(uint16_t time)
用于控制发送速度,不加延时会导致串口疯狂发送,电脑卡顿。
② 主循环逻辑
while(1)
{
USART_SendData(USART1,'a');
delay(1000);
}
- 每隔 1 秒调用一次串口发送函数
- 发送内容:字符
'a' - 安全、不卡顿、稳定输出
3.usart.c 串口初始化文件
// 包含 STM32 标准库
#include "stm32f10x.h"
// 串口驱动头文件
#include "usart.h"
/**
* @brief 初始化 USART1 串口通信
* @param 无
* @retval 无
*/
void my_usart_init(void)
{
// 定义结构体变量
GPIO_InitTypeDef GPIOInitStruct; // GPIO 配置结构体
USART_InitTypeDef USART_InitStruct; // 串口配置结构体
// ========== 第一步:开启时钟 ==========
// 开启 GPIOA 时钟 + USART1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
// ========== 第二步:配置 TX 引脚 PA9 ==========
// TX 发送引脚必须配置为:复用推挽输出
GPIOInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIOInitStruct.GPIO_Pin = GPIO_Pin_9;
GPIOInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
// 初始化 PA9
GPIO_Init(GPIOA, &GPIOInitStruct);
// ========== 第三步:配置 RX 引脚 PA10 ==========
// RX 接收引脚配置为:上拉输入
GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIOInitStruct.GPIO_Pin = GPIO_Pin_10;
// 初始化 PA10
GPIO_Init(GPIOA, &GPIOInitStruct);
// ========== 第四步:配置串口通信参数 ==========
// 波特率 115200
USART_InitStruct.USART_BaudRate = 115200;
// 无硬件流控制
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 模式:发送 + 接收
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
// 无校验位
USART_InitStruct.USART_Parity = USART_Parity_No;
// 1 位停止位
USART_InitStruct.USART_StopBits = USART_StopBits_1;
// 8 位数据位
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
// 初始化 USART1
USART_Init(USART1, &USART_InitStruct);
// 使能 USART1 外设(必须开启)
USART_Cmd(USART1, ENABLE);
}
① 必须开启两个时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
- GPIOA 时钟:给 PA9、PA10 供电
- USART1 时钟:给串口外设供电
② TX 引脚 PA9:复用推挽输出
GPIO_Mode_AF_PP
- 串口发送不是普通输出
- 必须开启复用功能
③ RX 引脚 PA10:上拉输
GPIO_Mode_IPU
- 接收引脚默认保持高电平
- 抗干扰、稳定
④ 串口参数配置
- 波特率:115200
- 数据位:8
- 停止位:1
- 校验位:无必须与串口调试助手一致,否则乱码
⑤ 使能串口
USART_Cmd(USART1, ENABLE);
不开这一句,串口永远不工作。
四、关键点
1. TX 与 RX 必须区分清楚
- TX 发送:复用推挽输出
- RX 接收:上拉输入 / 浮空输入
2. 串口发送不能无限制狂发
while(1)
{
USART_SendData(USART1,'a'); // 无延时,疯狂发送
}
正确做法:必须加延时。
3. 波特率必须一致
- 代码:115200
- 串口助手:115200不一致 = 乱码
4. 初始化顺序不能乱
- 开时钟
- 配置 GPIO
- 配置串口
- 使能串口
五、运行效果
烧录后打开串口调试助手:
- 每秒收到一个
a - 不卡顿、不漂移、稳定输出
