当前位置: 首页 > news >正文

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 新建工程并选择芯片

  1. 打开 STM32CubeMX,点击主界面的ACCESS TO MCU SELECTOR。

  2. 在搜索框输入STM32F103R6,在搜索结果中选择对应芯片(注意封装匹配,如 LQFP64),点击Start Project。

2.2 配置系统时钟

  1. 左侧导航栏选择RCC,在右侧配置界面中:

  • 高速外部时钟(HSE)选择Crystal/Ceramic Resonator(晶体振荡器)。

  1. 点击左侧Clock Configuration,配置系统时钟树:

  • PLL 源选择HSE,PLL 倍频系数设置为9(8MHz HSE → 72MHz 系统时钟)。

  • APB1 时钟分频设置为2(36MHz),APB2 时钟分频设置为1(72MHz)。

2.3 配置串口参数

  1. 左侧导航栏选择USART1,模式设置为Asynchronous(异步模式)。

  2. 配置串口基本参数:

  • 波特率:115200

  • 数据位:8 Bits

  • 停止位:1 Bit

  • 校验位:None(无奇偶校验)

  • 硬件流控:Disable(无硬件流控)

  1. 此时 PA9(USART1_TX)和 PA10(USART1_RX)会自动配置为串口功能,无需手动修改 GPIO 模式。

2.4 生成工程代码

  1. 点击菜单栏Project → Settings,设置:

  • Project Name:自定义工程名(如STM32_UART_Demo)

  • Project Location:选择保存路径

  • Toolchain/IDE:选择MDK-ARM

  1. 点击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 文件

  1. 在 Keil 中点击工具栏的Build按钮(或按F7)编译工程。

  2. 编译成功后,在工程目录的Debug文件夹下会生成.hex文件(如STM32_UART_Demo.hex),用于后续 Proteus 仿真。

五、Proteus 仿真电路设计

5.1 新建 Proteus 工程

  1. 打开 Proteus8,点击New Project,输入工程名和路径,选择Create a schematic from scratch。

  2. 跳过 PCB 设计步骤(仅需仿真原理图),完成工程创建。

5.2 添加元件

点击界面左侧的Component Mode(P 图标),搜索并添加以下元件:

  • STM32F103R6(核心芯片)

  • COMPIM(虚拟串口模块)

  • RES(电阻,1kΩ)

  • LED(发光二极管)

  • CRYSTAL(晶振,8MHz)

  • CAP(电容,2 个 30pF,用于晶振;1 个 10uF,用于电源滤波)

  • POWER(电源接口)

  • GROUND(接地接口)

5.3 电路连接

  1. 核心电路连接:

  • STM32F103R6 的PA9(USART1_TX) → COMPIM的RXD

  • STM32F103R6 的PA10(USART1_RX) → COMPIM的TXD

  • 晶振两端分别连接OSC_IN(PA8)和OSC_OUT(PA9),并通过 30pF 电容接地

  • VDD和VSS分别连接电源和地,VDD 与地之间接 10uF 滤波电容

  1. 状态指示电路(可选):

  • LED 正极通过 1kΩ 电阻连接PA0,负极接地(用于指示系统运行状态)

5.4 配置虚拟串口

  1. 双击COMPIM模块,在弹出的配置窗口中:

  • Physical Port选择一个虚拟串口(如COM1,需与后续调试助手对应)

  • Baud Rate设置为115200,Data Bits为8,Stop Bits为1,Parity为None

  • 其他参数保持默认,点击OK保存。

六、仿真运行与调试

6.1 加载程序到 STM32

  1. 双击 Proteus 中的STM32F103R6芯片,在Program File选项中选择之前生成的.hex文件。

  2. 勾选Reset after Program,点击OK。

6.2 配置虚拟串口与调试助手

  1. 使用 VSPD 创建一对虚拟串口(如COM1和COM2,需确保未被占用)。

  2. 打开串口调试助手,选择与COMPIM配对的串口(如COM2),配置参数:

  • 波特率:115200

  • 数据位:8

  • 停止位:1

  • 校验位:无

  • 勾选发送新行(自动添加 \r\n)

6.3 运行仿真

  1. 点击 Proteus 界面左下角的Run Simulation按钮(三角形图标)启动仿真。

  2. 此时调试助手会收到 STM32 发送的欢迎消息:STM32F103R6 UART Example: Send any data。

  3. 在调试助手的发送框输入任意字符(如Hello UART),点击发送,会收到 STM32 的应答:Received: Hello UART。

  4. 若添加了 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 开发板)进行测试,硬件电路需与仿真电路保持一致。

创作不易,如有帮助请点赞 + 收藏,欢迎留言交流技术问题!

http://www.dtcms.com/a/365802.html

相关文章:

  • JMeter下载安装及使用入门
  • 常用符号 Emoji 对照表——Unicode UTF-8
  • SQLSERVER临时表
  • 关于专业化与多元化该怎么选?
  • 解决MQ访问不了或者登录不成功问题
  • 卷积神经网络CNN-part2-简单的CNN
  • TypeScript与JavaScript:从动态少年到稳重青年的成长之路
  • RabbitMQ相关知识
  • HTML第七课:发展史
  • Unity:XML笔记(二)——Xml序列化、反序列化、IXmlSerializable接口
  • 裸机程序(1)
  • 【ARM嵌入式汇编基础】-数据处理指令(三)
  • 低成本低功耗认证芯片推荐——LCS4110R
  • 【Luogu】P2398 GCD SUM (容斥原理求gcd为k的数对个数)
  • 鸿蒙NEXT开发实战:图片显示、几何图形与自定义绘制详解
  • GPT4o 提示词 结合 NanoBanbana 会摩擦出什么火花呢?
  • FPGA笔试面试常考问题及答案汇总
  • 入行FPGA选择国企、私企还是外企?
  • 案例演示 切片器悬浮永驻 Power BI VS QuickBI ,不得不说,两个极端了
  • 华勤内推码
  • 智慧交通管理信号灯通信4G工业路由器应用
  • 【机器学习深度学习】LLM:在检索与重排序中的适用场景
  • PS更改图像尺寸
  • 心路历程-初识Linux用户
  • 于海斌、王耀南、张钹三位院士解读具身智能
  • 数据结构与算法-线性表
  • C++零基础第一天:从Hello World到变量常量
  • 【JAVA】windows本地跑zookeeper,然后使用代码连接服务获取znode数据
  • 什么是STDIO 模式,fastmcp 采用 STDIO
  • 基于Java的瑜伽馆管理系统的设计与实现(代码+数据库+LW)