【MCU】【STM32】基于STM32CubeMX+CLion的STM32开发环境

一、简介

基于 STM32CubeMX + CLion 的 STM32 开发环境,是一种融合了 "图形化配置效率" 与 "现代 IDE 开发体验" 的嵌入式开发方案。它以 STM32CubeMX 的硬件配置自动化为基础,搭配 CLion 的智能代码编辑、调试能力,解决了传统 STM32 开发(如 Keil MDK)中 "配置繁琐、代码提示弱、跨平台性差" 的痛点,尤其适合习惯现代 C/C++ 开发流程、追求高效调试的开发者。

1.1 核心工具定位与分工

该环境的核心是 "STM32CubeMX 负责 "硬件配置与代码生成",CLion 负责 "代码编写、编译与调试" ",两者通过标准化的工程文件联动,形成完整开发闭环:

工具 核心功能 解决的痛点
STM32CubeMX 1. 图形化选择芯片型号、配置引脚(GPIO、SPI、UART 等)、时钟树、外设参数;2. 自动生成初始化代码(基于 HAL/LL 库);3. 生成支持 CLion 的工程模板(如 Makefile/CMake)。 避免手动编写繁琐的外设初始化代码、时钟树计算,降低硬件配置出错率。
CLion 1. 智能代码编辑(语法高亮、自动补全、重构、跳转);2. 集成编译工具链(ARM-GCC);3. 支持硬件调试(配合 OpenOCD/J-Link);4. 跨平台(Windows/macOS/Linux)。 解决传统 IDE(如 Keil)代码提示弱、不支持跨平台、调试界面不直观的问题。

1.2 环境搭建核心依赖

要让两者联动,需额外配置 "编译工具链" 和 "调试工具",形成完整链路:

  1. 编译工具链:ARM GNU Toolchain 用于将 C/C++ 代码编译为 STM32 可执行的二进制文件(.elf/.hex),需下载对应平台的工具链(如arm-none-eabi-gcc)并配置环境变量。

  2. 调试工具:OpenOCD + 调试器

    • OpenOCD:开源调试工具,负责与硬件调试器(如 J-Link、ST-Link)通信,实现 "下载程序、断点调试、查看寄存器" 等功能;
    • 硬件调试器:常用 ST 官方的 ST-Link(低成本,支持大部分 STM32)或 Segger 的 J-Link(兼容性更强,支持复杂调试)。
  3. 驱动支持安装调试器的 USB 驱动(如 ST-Link 驱动、J-Link 驱动),确保电脑能识别硬件。

1.3 典型开发流程(以 "GPIO 点亮 LED" 为例)

  1. Step 1:STM32CubeMX 配置与代码生成

    • 打开 STM32CubeMX,选择目标芯片(如 STM32F103C8T6);
    • 配置硬件:
      • 引脚:将 PA5(LED 引脚)设为 "GPIO_Output";
      • 时钟树:将 HSE(外部高速时钟)设为 8MHz,系统时钟(SYSCLK)设为 72MHz;
    • 工程配置:
      • 选择 "Toolchain/IDE" 为 "Makefile"(CLion 支持 Makefile/CMake,Makefile 更简单);
      • 勾选 "Generate peripheral initialization as a pair of .c/.h files per peripheral"(模块化代码);
    • 点击 "Generate Code" 生成工程文件(包含 HAL 库、初始化代码、Makefile)。
  2. Step 2:CLion 导入工程并编写业务代码

    • 打开 CLion,选择 "Open" 导入 STM32CubeMX 生成的工程文件夹;

    • CLion 会自动识别 Makefile,无需额外配置编译规则;

    • main.cwhile(1)循环中添加 LED 翻转代码:

      复制代码
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 翻转PA5电平
      HAL_Delay(500); // 延时500ms
  3. Step 3:编译与下载

    • 点击 CLion 右上角的 "Build"(或快捷键Ctrl+F9),调用 ARM-GCC 编译工程,生成*.elf文件;
    • 连接调试器(如 ST-Link)到 STM32 开发板,在 CLion 中配置调试:
      • 进入 "Run> Edit Configurations",选择 "OpenOCD Download & Run";
      • 选择对应芯片的 OpenOCD 配置文件(如stm32f1x.cfg,通常 OpenOCD 已自带);
    • 点击 "Debug"(或快捷键Shift+F9),CLion 会通过 OpenOCD 将程序下载到 STM32,并进入调试模式。
  4. Step 4:调试与验证

    • HAL_GPIO_TogglePin行设置断点,调试时程序会暂停在断点处;
    • 通过 CLion 的调试面板查看 "GPIO 寄存器状态""变量值",或单步执行(F8)观察 LED 翻转逻辑;
    • 调试完成后,点击 "Run"(或快捷键Shift+F10)直接运行程序,LED 会以 500ms 周期闪烁。

1.4 该方案的优势与局限性

优势:
  1. 开发体验现代 :CLion 的智能补全(如输入HAL_GPIO_会自动提示所有 GPIO 相关函数)、代码跳转(点击函数名跳转到定义)大幅提升编码效率;
  2. 跨平台自由:Windows/macOS/Linux 均可使用,解决了 Keil MDK 仅支持 Windows 的问题(尤其适合 Mac 用户);
  3. 开源生态友好:依赖的 ARM-GCC、OpenOCD 均为开源工具,无需付费(对比 Keil 需要 license);
  4. 代码可移植性强:STM32CubeMX 生成的 HAL 库代码标准化,切换芯片时只需重新配置生成,业务代码基本无需修改。
局限性:
  1. 调试功能不如 Keil 全面:对某些复杂调试需求(如 Trace 跟踪、功耗分析)支持较弱,Keil MDK 在 STM32 专属调试功能上更成熟;
  2. 入门门槛略高:需手动配置工具链、OpenOCD,对新手而言比 "一键安装 Keil" 更复杂;
  3. 部分老芯片支持有限:STM32CubeMX 对非常早期的 STM32 型号(如 STM32F100)支持不足,更适合近 5 年推出的芯片(如 F1/F4/F7/H7/L4 系列)。

1.5 适用人群

  • 习惯现代 C/C++ 开发(如使用过 VS Code、Qt Creator)的开发者;
  • 需要跨平台开发(如在 Mac 上开发 STM32)的用户;
  • 追求开源工具链、避免商业软件依赖的团队或个人;
  • 以 HAL 库为主要开发框架的 STM32 项目(若用标准库,STM32CubeMX 支持有限,需手动适配)。

综上,STM32CubeMX+CLion 是一套 "高效、现代、跨平台" 的 STM32 开发方案,尤其适合对开发体验有要求的中高级开发者,或需要摆脱 Keil 依赖的场景。

二、工程创建

2.1 使用STM32CubeMX创建工程cmake工程,其他的STM32工程的配置与keil的配置一样,主要是针对工程配置。

2.2 工程配置

选择cmake

2.3 导入工程,打开文件夹

取消勾选默认的Debug

勾选Debug预设

2.4 交换位置

复制代码
# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})

# Enable CMake support for ASM and C languages
enable_language(C ASM)

2.5 下载工具链

Download OpenOCD for Windows

Arm GNU 工具链下载 -- Arm Developer

2.6 进入设置,配置工具链

2.7 配置OpenOCD

选择适合stm32f103c8t6的下载配置

2.8 先编译测试

三、编写、编译代码

3.1 测试烧写,注意下载STlink驱动,烧写成功

bash 复制代码
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
    HAL_Delay(100);
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
    HAL_Delay(100);
bash 复制代码
D:\DevEnv\CLion_Toolchain\openocd-v0.12.0-i686-w64-mingw32\bin\openocd.exe -s D:\DevEnv\CLion_Toolchain\openocd-v0.12.0-i686-w64-mingw32\share\openocd\scripts -f D:\DevEnv\CLion_Toolchain\stm32f1_stlink.cfg -c "tcl_port disabled" -c "gdb_port disabled" -c "tcl_port disabled" -c "program \"E:/MDK_Projects/STM32CubeMX_Projects/STM32MX_Examples_Workspaces/clion_test/build/Debug/clion_test.elf\"" -c reset -c shutdown
[0m[0mOpen On-Chip Debugger 0.12.0 (2023-01-14-23:37)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override u
se 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results mi
ght differ compared to plain JTAG/SWD
none separate

Info : clock speed 1000 kHz
Info : STLINK V2J45S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.225841
Info : [stm32f1x.cpu] Cortex-M3 r1p1 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
[stm32f1x.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000188 msp: 0x20000dc0
** Programming Started **
Info : device id = 0x20036410
Info : flash size = 64 KiB
Warn : Adding extra erase range, 0x0800123c .. 0x080013ff
** Programming Finished **
shutdown command invoked

3.2 添加mycode文件夹和bsp_led组件

bash 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "../../mycode/bsp_led/bsp_led.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    led_change();
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  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();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  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();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
bash 复制代码
//
// Created by zky on 2025/10/2.
//

#include "bsp_led.h"

void led_change(void)
{
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
    HAL_Delay(50);
}

3.3 添加cmake路径

(1)添加自定义的头文件路径和源文件路径

bash 复制代码
cmake_minimum_required(VERSION 3.22)

#
# This file is generated only once,
# and is not re-generated if converter is called multiple times.
#
# User is free to modify the file as much as necessary
#

# Setup compiler settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)


# Define the build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()

# Set the project name
set(CMAKE_PROJECT_NAME clion_test)

# Include toolchain file
include("cmake/gcc-arm-none-eabi.cmake")

# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)



# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})

# Enable CMake support for ASM and C languages
enable_language(C ASM)

# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME}
        mycode/bsp_led/bsp_led.h
        mycode/bsp_led/bsp_led.c)

# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)

# Link directories setup
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user defined library search paths
)

# Add sources to executable
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user sources here
        mycode/bsp_led/bsp_led.c
)

# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user defined include paths
        mycode/bsp_led
)

# Add project symbols (macros)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user defined symbols
)

# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
    stm32cubemx

    # Add user defined libraries
)

(2)编译成功,已经识别

四、实验效果

相关推荐
国科安芯11 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
茯苓gao13 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉16 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者17 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间18 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious18 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计1 天前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32