📌 一个核心规则
CubeMX重新生成代码时,只保留 /* USER CODE BEGIN xxx */ 和 /* USER CODE END xxx */ 之间的内容。
你的代码必须写在这对注释中间,写在外部会被删除。
📂 各区域说明(按文件顺序)
1. BEGIN Header / END Header
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
* Copyright (c) 2026 STMicroelectronics.
* ...
*/
/* USER CODE END Header */
|
说明 |
| 作用 |
文件头注释,包含版权信息和文件说明 |
| 需要写什么 |
一般不需要修改 |
| 能删吗 |
可以删,但没必要 |
2. BEGIN Includes / END Includes
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
|
说明 |
| 作用 |
包含本文件需要的其他头文件 |
| 需要写什么 |
#include <stdio.h>(用printf时)、#include "servo.h"(自己的驱动)、#include <string.h>等 |
| 注意 |
#include "main.h"是自动生成的,不要动 |
3. BEGIN PTD / END PTD
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
|
说明 |
| 作用 |
定义私有的数据类型(结构体、枚举、联合体) |
| 需要写什么 |
typedef struct { float distance; uint8_t angle; } SensorData_t; |
| 新手建议 |
需要时再用,不需要可以空着 |
4. BEGIN PD / END PD
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
|
说明 |
| 作用 |
定义常量宏,给数字和引脚起有意义的名字 |
| 需要写什么 |
#define TRIG_PIN GPIO_PIN_0、#define BUFFER_SIZE 128、#define TIMEOUT 1000 |
| 好处 |
代码更易读,修改更方便 |
5. BEGIN PM / END PM
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
|
说明 |
| 作用 |
定义带参数的宏函数 |
| 需要写什么 |
#define ABS(x) ((x) > 0 ? (x) : -(x))、#define MIN(a,b) ((a) < (b) ? (a) : (b)) |
| 新手建议 |
一般用不到,空着就行 |
6. BEGIN PV / END PV
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
|
说明 |
| 作用 |
存放全局变量 |
| 注意 |
上半部分的外设句柄(htim2、huart1等)是CubeMX自动生成的,不要动 |
| 需要写什么 |
你自己的全局变量:float distance = 0;、uint8_t buffer[64]; |
7. BEGIN PFP / END PFP
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
|
说明 |
| 作用 |
声明私有函数,告诉编译器"这些函数在后面有定义" |
| 注意 |
上半部分是CubeMX自动生成的,不要动 |
| 需要写什么 |
如果你在BEGIN 4(文件末尾)写了函数,且需要在main中调用,就在这里声明 |
| 新手建议 |
如果你在BEGIN 0中写函数(在main之前),一般不需要在这里声明 |
8. BEGIN 0 / END 0 ⭐
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
|
说明 |
| 作用 |
实现你所有的自定义功能函数 |
| 需要写什么 |
业务逻辑函数(测距、控制)、硬件封装函数、工具函数(延时、printf重定向) |
| 位置 |
在main函数之前,所以这里的函数不需要在PFP中声明 |
9. main函数内部的区域
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
}
⑨-① BEGIN 1 / END 1
|
说明 |
| 作用 |
在main函数开头声明局部变量 |
| 需要写什么 |
uint8_t angle = 0;、uint16_t count = 0; |
⑨-② BEGIN Init / END Init
|
说明 |
| 作用 |
在HAL_Init()之后、时钟配置之前插入代码 |
| 需要写什么 |
一般不需要写,保持为空 |
⑨-③ BEGIN SysInit / END SysInit
|
说明 |
| 作用 |
在SystemClock_Config()之后、外设初始化之前插入代码 |
| 需要写什么 |
一般不需要写,保持为空 |
⑨-④ BEGIN 2 / END 2 ⭐
|
说明 |
| 作用 |
所有"只执行一次"的初始化代码写在这里 |
| 需要写什么 |
启动外设(HAL_TIM_Base_Start)、设置初始状态(舵机归零)、打印启动信息 |
⑨-⑤ BEGIN WHILE / END WHILE
|
说明 |
| 作用 |
包裹while(1){结构 |
| 需要写什么 |
不要在这里写业务代码,只保留while(1){ |
⑨-⑥ BEGIN 3 / END 3 ⭐
|
说明 |
| 作用 |
所有需要反复执行的逻辑写在这里 |
| 需要写什么 |
传感器读取、电机控制、通信处理、按键检测 |
10. 外设初始化函数内部的插入点
以 MX_TIM2_Init 为例:
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
// ... CubeMX生成的配置代码 ...
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
// ... HAL初始化代码 ...
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
| 插入点 |
位置 |
用途 |
xxx_Init 0 |
函数开头,配置代码之前 |
极少使用 |
xxx_Init 1 |
配置赋值之后,HAL初始化之前 |
修改默认配置值 |
xxx_Init 2 |
HAL初始化完成之后 |
添加额外操作 |
11. BEGIN Error_Handler_Debug / END Error_Handler_Debug
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
|
说明 |
| 作用 |
HAL库出错时调用的函数 |
| 需要写什么 |
添加错误提示(点亮LED、串口打印错误信息) |
| 新手建议 |
保持默认即可 |
📊 总结速查表
| 区域 |
作用 |
要不要写 |
BEGIN Header |
文件头版权信息 |
❌ 不用管 |
BEGIN Includes |
包含头文件 |
✅ 加 #include |
BEGIN PTD |
定义结构体/枚举 |
⚠️ 按需 |
BEGIN PD |
定义宏常量 |
✅ 推荐 |
BEGIN PM |
定义宏函数 |
❌ 不用管 |
BEGIN PV |
定义全局变量 |
⚠️ 按需 |
BEGIN PFP |
声明私有函数 |
❌ 基本不用 |
BEGIN 0 |
自定义功能函数 |
✅ 核心 |
BEGIN 1 |
main局部变量 |
⚠️ 按需 |
BEGIN Init |
早期初始化 |
❌ 不用管 |
BEGIN SysInit |
中期初始化 |
❌ 不用管 |
BEGIN 2 |
用户初始化 |
✅ 核心 |
BEGIN WHILE |
while结构 |
❌ 不要写代码 |
BEGIN 3 |
主循环 |
✅ 核心 |
xxx_Init 0/1/2 |
外设初始化插入 |
❌ 不用管 |
Error_Handler_Debug |
错误处理 |
⚠️ 按需 |
💡 三句话记住全部
-
所有代码写在 BEGIN 和 END 中间——写外面会被删
-
BEGIN 0 写函数,BEGIN 2 写初始化,BEGIN 3 写主循环——三个核心区
-
自动生成的代码(外设句柄、MX_xxx_Init)不要动——其他区域保持默认
所有评论(0)