Proteus8 + STM32CubeMX 实现 STM32F103R6 串口通信教程
通过简单的几个步骤,你就能让 STM32F103R6 实现串口通信,轻松发送和接收数据,甚至控制 LED 状态。
一、准备工作
1.1 所需软件
Proteus8(推荐 8.9 及以上版本)
STM32CubeMX(6.0 及以上版本)
Keil MDK-ARM(V5 或 V6 版本)
串口调试助手(如 XCOM、SSCOM 等)
虚拟串口工具(如 VSPD,用于仿真环境调试)
1.2 硬件模型
核心芯片:STM32F103R6(中等容量 STM32F1 系列微控制器)
辅助元件:虚拟串口模块、LED(用于状态指示)、晶振、电阻等
二、使用 STM32CubeMX 创建工程
2.1 新建工程并选择芯片
打开 STM32CubeMX,点击主界面的ACCESS TO MCU SELECTOR。
在搜索框输入STM32F103R6,在搜索结果中选择对应芯片(注意封装匹配,如 LQFP64),点击Start Project。
2.2 配置系统时钟
左侧导航栏选择RCC,在右侧配置界面中:
高速外部时钟(HSE)选择Crystal/Ceramic Resonator(晶体振荡器)。
点击左侧Clock Configuration,配置系统时钟树:
PLL 源选择HSE,PLL 倍频系数设置为9(8MHz HSE → 72MHz 系统时钟)。
APB1 时钟分频设置为2(36MHz),APB2 时钟分频设置为1(72MHz)。
2.3 配置串口参数
左侧导航栏选择USART1,模式设置为Asynchronous(异步模式)。
配置串口基本参数:
波特率:115200
数据位:8 Bits
停止位:1 Bit
校验位:None(无奇偶校验)
硬件流控:Disable(无硬件流控)
此时 PA9(USART1_TX)和 PA10(USART1_RX)会自动配置为串口功能,无需手动修改 GPIO 模式。
2.4 生成工程代码
点击菜单栏Project → Settings,设置:
Project Name:自定义工程名(如STM32_UART_Demo)
Project Location:选择保存路径
Toolchain/IDE:选择MDK-ARM
点击GENERATE CODE生成 Keil 工程,等待代码生成完成。
三、编写串口通信代码
在 Keil 中打开生成的工程,找到main.c文件,添加串口发送函数和主循环逻辑:
#include "main.h"
#include <string.h> // 需包含字符串处理库UART_HandleTypeDef huart1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);/*** @brief 串口发送字符串函数* @param huart: 串口句柄(如&huart1)* @param str: 待发送的字符串*/
void UART_SendString(UART_HandleTypeDef *huart, uint8_t *str)
{// 发送字符串,超时时间设为最大(HAL_MAX_DELAY)HAL_UART_Transmit(huart, str, strlen((char*)str), HAL_MAX_DELAY);
}int main(void)
{// 初始化HAL库HAL_Init();// 配置系统时钟SystemClock_Config();// 初始化GPIO和USART1MX_GPIO_Init();MX_USART1_UART_Init();// 定义发送和接收缓冲区uint8_t welcome_msg[] = "STM32F103R6 UART Example: Send any data\r\n";uint8_t rx_buf[100] = {0}; // 接收缓冲区uint8_t tx_buf[100] = {0}; // 发送缓冲区// 上电后发送欢迎消息UART_SendString(&huart1, welcome_msg);while (1){// 接收数据(超时时间100ms)if (HAL_UART_Receive(&huart1, rx_buf, sizeof(rx_buf)-1, 100) == HAL_OK){// 构建应答消息(将接收的数据回传)sprintf((char*)tx_buf, "Received: %s\r\n", rx_buf);// 发送应答消息UART_SendString(&huart1, tx_buf);// 清空接收缓冲区,准备下次接收memset(rx_buf, 0, sizeof(rx_buf));}// 短暂延时,降低CPU占用HAL_Delay(100);}
}// 以下为自动生成的系统时钟、USART1和GPIO初始化代码(保持默认即可)
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}static void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}
}static void MX_GPIO_Init(void)
{// 可在此添加LED等GPIO的初始化代码(如PA0接LED)GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}void Error_Handler(void)
{__disable_irq();while (1){// 错误处理:可添加LED闪烁提示HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);HAL_Delay(500);}
}#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
四、编译生成 Hex 文件
在 Keil 中点击工具栏的Build按钮(或按F7)编译工程。
编译成功后,在工程目录的Debug文件夹下会生成.hex文件(如STM32_UART_Demo.hex),用于后续 Proteus 仿真。
五、Proteus 仿真电路设计
5.1 新建 Proteus 工程
打开 Proteus8,点击New Project,输入工程名和路径,选择Create a schematic from scratch。
跳过 PCB 设计步骤(仅需仿真原理图),完成工程创建。
5.2 添加元件
点击界面左侧的Component Mode(P 图标),搜索并添加以下元件:
STM32F103R6(核心芯片)
COMPIM(虚拟串口模块)
RES(电阻,1kΩ)
LED(发光二极管)
CRYSTAL(晶振,8MHz)
CAP(电容,2 个 30pF,用于晶振;1 个 10uF,用于电源滤波)
POWER(电源接口)
GROUND(接地接口)
5.3 电路连接
核心电路连接:
STM32F103R6 的PA9(USART1_TX) → COMPIM的RXD
STM32F103R6 的PA10(USART1_RX) → COMPIM的TXD
晶振两端分别连接OSC_IN(PA8)和OSC_OUT(PA9),并通过 30pF 电容接地
VDD和VSS分别连接电源和地,VDD 与地之间接 10uF 滤波电容
状态指示电路(可选):
LED 正极通过 1kΩ 电阻连接PA0,负极接地(用于指示系统运行状态)
5.4 配置虚拟串口
双击COMPIM模块,在弹出的配置窗口中:
Physical Port选择一个虚拟串口(如COM1,需与后续调试助手对应)
Baud Rate设置为115200,Data Bits为8,Stop Bits为1,Parity为None
其他参数保持默认,点击OK保存。
六、仿真运行与调试
6.1 加载程序到 STM32
双击 Proteus 中的STM32F103R6芯片,在Program File选项中选择之前生成的.hex文件。
勾选Reset after Program,点击OK。
6.2 配置虚拟串口与调试助手
使用 VSPD 创建一对虚拟串口(如COM1和COM2,需确保未被占用)。
打开串口调试助手,选择与COMPIM配对的串口(如COM2),配置参数:
波特率:115200
数据位:8
停止位:1
校验位:无
勾选发送新行(自动添加 \r\n)
6.3 运行仿真
点击 Proteus 界面左下角的Run Simulation按钮(三角形图标)启动仿真。
此时调试助手会收到 STM32 发送的欢迎消息:STM32F103R6 UART Example: Send any data。
在调试助手的发送框输入任意字符(如Hello UART),点击发送,会收到 STM32 的应答:Received: Hello UART。
若添加了 LED 电路,LED 会间隔 100ms 闪烁,指示系统正常运行。
七、常见问题解决
7.1 仿真无反应,无串口数据
检查 Hex 文件是否正确加载(STM32 属性中确认 Program File 路径)。
确认系统时钟配置(HSE 是否使能,PLL 倍频是否正确)。
检查 Proteus 中 STM32 的电源和地是否连接正确。
7.2 串口通信失败,无应答
确认COMPIM与调试助手的串口参数完全一致(波特率、校验位等)。
检查 TX/RX 引脚是否交叉连接(STM32_TX → COMPIM_RX,STM32_RX → COMPIM_TX)。
虚拟串口未正确创建:使用 VSPD 确认串口对已激活,且无占用冲突。
7.3 Keil 编译报错
检查是否遗漏#include <string.h>(strlen和sprintf函数依赖)。
确认 STM32CubeMX 生成的代码完整(未手动删除关键初始化函数)。
八、扩展应用
本教程实现了基础的串口回传功能,可扩展为:
串口指令控制(如通过特定字符控制 LED 开关)
传感器数据采集(如通过串口发送温湿度数据)
与上位机通信(如 Python/Qt 编写的控制软件)
通过 Proteus 仿真验证后,可直接将代码烧录到实际硬件(STM32F103R6 开发板)进行测试,硬件电路需与仿真电路保持一致。
创作不易,如有帮助请点赞 + 收藏,欢迎留言交流技术问题!