STM32 开发笔记:从环境搭建到任务调度

今天体验了一把augment确实好用,记录一下

STM32 开发笔记:从环境搭建到任务调度

🛠️ 环境准备

必需工具

  • STM32CubeMX:图形化配置工具,用于初始化 MCU 外设和生成基础代码
  • STM32CubeCLT:包含编译工具链(arm-none-eabi-gcc)和烧录工具(STM32_Programmer_CLI)
  • CMake:跨平台构建系统,用于管理项目编译流程
  • OpenOCD:开源调试器(可选,用于 DAPLink 等调试器连接)

验证环境

在 PowerShell 中执行以下命令检查工具链是否安装正确:

powershell

arm-none-eabi-gcc --version    # 检查GCC编译器版本
cmake --version                # 检查CMake版本
STM32_Programmer_CLI --version # 检查STM32烧录工具版本
openocd --version              # 检查OpenOCD版本(可选)

🎯 CubeMX 项目创建

  1. 创建新项目

    • 打开 STM32CubeMX,通过 "File > New Project" 选择目标 MCU 型号(如 STM32G474RE)
    • 配置引脚功能、外设(如 GPIO、USART、ADC 等)及系统时钟(如配置为 72MHz)
    • 在 "Project Manager > Toolchain/IDE" 中选择 "CMake" 作为工具链,点击 "GENERATE CODE" 生成项目
  2. 关键配置要点

    • 确保时钟树配置正确,避免频率设置错误导致芯片异常
    • 外设初始化参数(如 USART 波特率、GPIO 模式)需根据需求调整

⚙️ CMake 编译

1. 项目结构说明

plaintext

your_project/
├── CMakeLists.txt          # 项目构建配置文件
├── Core/
│   ├── Inc/               # 核心头文件(如main.h、stm32g4xx_hal_conf.h)
│   └── Src/               # 核心源文件(如main.c、system_stm32g4xx.c)
├── Drivers/               # ST官方驱动文件(HAL库、LL库)
└── user/                  
    ├── inc/               # 用户自定义头文件
    └── src/               # 用户自定义源文件

2. 配置项目

  • 使用预设配置(推荐):

    powershell

    cmake --preset Debug  # 生成Debug配置的编译文件
    
  • 手动配置:

    powershell

    cmake -B build/Debug -DCMAKE_BUILD_TYPE=Debug  # 在build/Debug目录生成编译文件
    

3. 编译项目

powershell

cmake --build --preset Debug  # 编译项目,生成.elf可执行文件

4. 生成烧录文件

powershell

# 将.elf转换为HEX格式(适用于ST-Link烧录)
arm-none-eabi-objcopy -O ihex build/Debug/项目名.elf build/Debug/项目名.hex

🔥 烧录固件

方法 1:使用 ST-Link(推荐)

powershell

# 第一步:检查ST-Link连接
STM32_Programmer_CLI -l

# 第二步:烧录固件并验证(-w:写入,-v:验证,-rst:复位芯片)
STM32_Programmer_CLI -c port=SWD -w build/Debug/项目名.hex -v -rst

方法 2:使用 DAPLink(配合 OpenOCD)

powershell

openocd -f interface/cmsis-dap.cfg -f target/stm32g4x.cfg \
  -c "adapter speed 1000" \        # 设置适配器速度为1000kHz
  -c "init" \                      # 初始化调试器
  -c "reset halt" \                # 复位芯片并暂停
  -c "flash write_image erase build/Debug/项目名.hex" \  # 擦除并写入固件
  -c "reset run" \                 # 复位并运行程序
  -c "shutdown"                    # 关闭OpenOCD

📁 添加用户代码

1. 创建用户目录结构

powershell

mkdir user                # 创建用户代码根目录
mkdir user/inc            # 用户头文件目录
mkdir user/src            # 用户源文件目录

2. 更新 CMakeLists.txt

在 CMakeLists.txt 中添加用户代码路径:

cmake

# 添加头文件路径
set(MX_Include_Dirs
    ${CMAKE_SOURCE_DIR}/Core/Inc
    ${CMAKE_SOURCE_DIR}/user/inc  # 新增用户头文件路径
)

# 添加源文件路径
set(MX_Application_Src
    ${CMAKE_SOURCE_DIR}/user/src/user.c  # 新增用户源文件
)

⏰ 调度器使用

1. 调度器头文件(user_scheduler.h)

c

运行

#ifndef __USER_SCHEDULER_H__
#define __USER_SCHEDULER_H__

#include "main.h"

#define MAX_TASKS 8  // 最大任务数,可根据需求调整

// 任务结构体定义
typedef struct {
    void (*task_func)(void);    // 任务函数指针
    uint32_t period_ms;         // 任务执行周期(毫秒)
    uint32_t last_run;          // 上次执行时间
    uint8_t enabled;            // 任务使能标志
} Task_t;

// 函数声明
void Scheduler_Init(void);
void Scheduler_AddTask(void (*task_func)(void), uint32_t period_ms);
void Scheduler_Run(void);

#endif

2. 调度器实现(user_scheduler.c)

c

运行

#include "user_scheduler.h"

static Task_t tasks[MAX_TASKS];  // 任务数组
static uint8_t task_count = 0;   // 任务计数器

/**
 * @brief 初始化调度器
 */
void Scheduler_Init(void) {
    task_count = 0;
}

/**
 * @brief 添加任务到调度器
 * @param task_func 任务函数指针
 * @param period_ms 任务执行周期(毫秒)
 */
void Scheduler_AddTask(void (*task_func)(void), uint32_t period_ms) {
    if (task_count < MAX_TASKS && task_func) {
        tasks[task_count].task_func = task_func;
        tasks[task_count].period_ms = period_ms;
        tasks[task_count].last_run = HAL_GetTick();
        tasks[task_count].enabled = 1;
        task_count++;
    }
}

/**
 * @brief 运行调度器,检查并执行到期任务
 */
void Scheduler_Run(void) {
    uint32_t current_time = HAL_GetTick();
    for (uint8_t i = 0; i < task_count; i++) {
        if (tasks[i].enabled && (current_time - tasks[i].last_run) >= tasks[i].period_ms) {
            tasks[i].task_func();        // 执行任务函数
            tasks[i].last_run = current_time;  // 更新上次执行时间
        }
    }
}

3. 在 main 函数中使用调度器

c

运行

int main(void) {
    // 系统初始化...
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    
    // 初始化调度器
    Scheduler_Init();
    
    // 添加任务(示例:每100ms执行一次LED闪烁任务)
    Scheduler_AddTask(LED_Toggle, 100);
    Scheduler_AddTask(USART_SendData, 500);  // 每500ms发送一次数据
    
    // 主循环
    while (1) {
        Scheduler_Run();  // 调用调度器执行任务
        // 其他非周期性任务...
    }
}

🔧 常见问题及解决方法

问题描述解决方法
编译错误:“No such file or directory”检查 CMakeLists.txt 中头文件和源文件路径是否正确,确保用户目录(user/inc、user/src)已正确添加
烧录失败:“No ST-Link detected”1. 检查 ST-Link 与芯片的连接(SWD 线、电源线)
2. 尝试重启 ST-Link 或更换 USB 接口
3. 改用 DAPLink+OpenOCD 烧录
任务不执行或执行异常1. 确保在 main 函数的 while 循环中调用了Scheduler_Run()
2. 检查任务周期设置是否合理,避免周期过短导致 CPU 负载过高
3. 确认任务函数中没有死循环或长时间阻塞操作

📝 完整开发流程总结

  1. 环境搭建:安装 STM32CubeMX、STM32CubeCLT、CMake,验证工具链版本
  2. 项目创建:使用 CubeMX 配置 MCU 和外设,生成 CMake 项目
  3. 代码组织:创建 user 目录,在 CMakeLists.txt 中添加用户代码路径
  4. 调度器实现:编写任务调度器,管理周期性任务
  5. 编译测试:使用cmake --build --preset Debug编译项目
  6. 固件烧录:通过 ST-Link 或 DAPLink 将 HEX 文件烧录到芯片
  7. 调试优化:根据运行结果修复问题,优化任务调度逻辑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值