【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)编译成功,已经识别

四、实验效果

相关推荐
10001hours4 小时前
(基于江协科技)51单片机入门:10.AT24C0
科技·嵌入式硬件·51单片机
transuperb6 小时前
51单片机AD/DA
网络·嵌入式硬件·51单片机
光子物联单片机8 小时前
STM32G474单片机开发入门(一)STM32G474RET6单片机详解
stm32·单片机·嵌入式硬件·mcu
zhuxinmingde8 小时前
电机控制-PMSM无感FOC控制(五)相电流检测及重构 — 单电阻采样
单片机·嵌入式硬件·重构
眰恦ゞLYF8 小时前
嵌入式硬件——基于IMX6ULL的UART(通用异步收发传输器)
单片机·嵌入式硬件·uart·imx6ull
A9better8 小时前
嵌入式开发学习日志32——stm32之PWM
stm32·单片机·嵌入式硬件·学习
眰恦ゞLYF12 小时前
嵌入式硬件——基于IMX6ULL的GPT(通用定时器)实现
单片机·嵌入式硬件·gpt·imx6ull
充哥单片机设计15 小时前
【STM32项目开源】基于STM32的智能老人拐杖
stm32·单片机·嵌入式硬件