📌 一个核心规则

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 */
说明
作用 存放全局变量
注意 上半部分的外设句柄(htim2huart1等)是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 错误处理 ⚠️ 按需

💡 三句话记住全部

  1. 所有代码写在 BEGIN 和 END 中间——写外面会被删

  2. BEGIN 0 写函数,BEGIN 2 写初始化,BEGIN 3 写主循环——三个核心区

  3. 自动生成的代码(外设句柄、MX_xxx_Init)不要动——其他区域保持默认

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐