2. 开发环境搭建:安装Keil MDK或STM32CubeIDE,配置STM32标准外库或HAL库,建立第一个空白工程并点亮LED

好,咱们正式开始动手了。这一章,我带你搭建开发环境。说白了,就是给你的电脑装上能跟STM32“对话”的工具。很多新手在这一步就卡住了,其实没那么复杂。我当年第一次装Keil的时候,也折腾了一下午,后来发现就是路径选错了。嗯,咱们今天把这些坑都填平。

2.1 开发工具的选择:Keil MDK vs STM32CubeIDE

先说说选哪个。我个人习惯用Keil MDK,因为从ARM7时代就开始用了,界面熟悉,调试也顺手。但STM32CubeIDE是ST官方出的,免费,而且集成了CubeMX配置工具,对新手更友好。

怎么选?我建议:

  • 如果你刚入门,或者预算有限,直接用STM32CubeIDE。它免费,功能也够用。
  • 如果你以后要做商业项目,或者需要跟老代码兼容,可以考虑Keil MDK。它的编译器优化更好,调试器也更稳定。
  • 如果你像我一样,两个都装。平时用Keil,偶尔用CubeIDE生成初始化代码,然后导入Keil里用。灵活嘛。
我的小建议: 别纠结。先选一个装上,把LED点亮再说。工具只是手段,核心是理解芯片怎么工作的。

2.2 安装Keil MDK(以MDK-ARM V5为例)

好,咱们先走Keil的安装流程。你可以在Keil官网下载,但需要注册账号。如果你有正版License,直接激活。没有的话,也能用,就是代码大小有限制(32KB),点亮LED绰绰有余。

  1. 下载安装包:去Keil官网下载MDK-ARM。注意版本,我建议用V5.38或更新版本,对Cortex-M4支持更好。
  2. 安装:双击安装包,一路Next。但要注意:安装路径不要有中文!我见过有人装在“D:\软件\Keil”里,结果编译报错,折腾半天才发现是路径问题。
  3. 安装器件包:安装完后,打开Keil,点击“Pack Installer”。找到你的芯片型号,比如STM32F103C8,点击Install。这一步是下载芯片的SVD文件和启动文件。
  4. 激活License:如果你有License,点击File -> License Management,输入CID和License。没有的话,也能用,就是编译时会有个弹窗提醒。
注意: 安装过程中,如果杀毒软件弹出警告,请允许。Keil的驱动需要写入系统目录,杀毒软件有时会误报。

2.3 安装STM32CubeIDE

如果你选择CubeIDE,那就更简单了。去ST官网下载,免费,不需要License。安装过程基本是傻瓜式的。

  1. 下载:去ST官网搜索“STM32CubeIDE”,下载对应操作系统的版本。
  2. 安装:解压后运行安装程序。它会自动安装Eclipse插件和GCC编译器。
  3. 首次启动:会让你选择工作空间(Workspace)。我建议单独建一个文件夹,比如“D:\STM32_Workspace”。

安装完成后,你会看到一个Eclipse风格的界面。别被吓到,其实用起来很顺手。

2.4 配置标准外设库 vs HAL库

嗯,这里要讲一个关键选择:用标准外设库还是HAL库?

我简单解释一下:

  • 标准外设库:ST早期推出的库,直接操作寄存器,代码精简,执行效率高。但每个外设都要自己配置,工作量大。
  • HAL库:ST后来推出的,封装了更多抽象层,用起来方便,但代码体积大,执行效率稍低。

我个人建议:新项目用HAL库。为什么?因为ST已经停止更新标准外设库了,而且HAL库配合CubeMX,配置外设就像点菜一样简单。我在一个项目中用过标准外设库,后来要移植到新芯片,改代码改到崩溃。换成HAL库后,CubeMX重新生成一下就行。

重要: 如果你用的是STM32CubeIDE,它默认就集成了HAL库。如果你用Keil,需要手动下载HAL库包。去ST官网搜索“STM32Cube_FW_F1”之类的,下载后解压到Keil的安装目录下。

2.5 建立第一个空白工程

好,工具装好了,库也配好了。咱们来建第一个工程。我以Keil MDK为例,CubeIDE的操作类似。

  1. 新建工程:打开Keil,点击Project -> New uVision Project。选择你的芯片型号,比如STM32F103C8。
  2. 选择运行环境:在弹出的“Manage Run-Time Environment”窗口中,勾选“CMSIS”和“Device”下的“Startup”。这是必须的,包含了启动文件和系统初始化代码。
  3. 添加源文件:在工程中新建一个main.c文件。右键点击“Source Group”,选择“Add New Item to Group”,选择C文件,命名为main.c。
  4. 编写代码:在main.c里写一个空函数。嗯,先别急着写LED代码,咱们先让工程能编译通过。
#include "stm32f1xx_hal.h"

int main(void)
{
    HAL_Init();
    while(1)
    {
        // 空循环
    }
}

编译一下。如果没报错,恭喜你,第一个空白工程建好了。

避坑指南: 我曾经遇到过编译报错“Error: L6218E: Undefined symbol SystemInit”。这是因为启动文件里调用了SystemInit函数,但你没实现。在main.c里加一个空函数就行:
void SystemInit(void)
{
    // 空实现
}

2.6 点亮LED:从原理到代码

好,重头戏来了。咱们让LED亮起来。这不仅是“Hello World”,更是验证你的开发环境是否搭建成功的关键一步。

先看原理。LED怎么亮?很简单:给它的正极接高电平,负极接低电平,电流流过,它就亮了。在STM32上,我们通过GPIO引脚输出高电平或低电平来控制。

假设你的LED接在PC13引脚上(很多STM32最小系统板都是这样),负极接地,正极通过一个电阻接到PC13。那么,要让LED亮,PC13需要输出低电平(因为电流从正极流向负极)。

好,上代码:

#include "stm32f1xx_hal.h"

void LED_Init(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();   // 使能GPIOC时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  // 推挽输出
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

int main(void)
{
    HAL_Init();
    LED_Init();

    while(1)
    {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);  // 输出低电平,LED亮
        HAL_Delay(500);  // 延时500ms
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // 输出高电平,LED灭
        HAL_Delay(500);
    }
}

编译,下载,看效果。如果LED以1秒的频率闪烁,恭喜你,成功了!

注意: 如果你用的是STM32CubeIDE,记得在.ioc文件中配置PC13为GPIO_Output,然后生成代码。CubeIDE会自动生成LED_Init函数,你只需要在main.c里调用就行。

2.7 常见问题与解决

嗯,这里总结几个我遇到过的问题,你可能会碰到:

问题 原因 解决方法
编译报错“找不到头文件” 库路径没配置 在Keil的Options for Target -> C/C++ -> Include Paths中添加HAL库的Inc文件夹路径
下载时提示“No Cortex-M SW Device Found” 调试器驱动没装好,或接线错误 检查ST-Link驱动,检查SWDIO、SWCLK、GND接线
LED不亮 引脚配置错误,或LED接反 检查原理图,确认LED正极接的哪个引脚,确认GPIO模式是否正确
HAL_Delay不准确 系统时钟没配置 在HAL_Init()之前调用SystemClock_Config(),配置系统时钟为72MHz
我的经验: 如果LED不亮,别急着怀疑代码。先拿万用表量一下引脚电压。如果引脚电压正常,那就是LED或电阻的问题。我曾经花了一个小时查代码,最后发现是LED焊反了。嗯,从那以后,我每次都会先量电压。

2.8 小结

好,这一章的内容就到这里。你学会了:

  • 如何选择并安装Keil MDK或STM32CubeIDE
  • 标准外设库和HAL库的区别与选择
  • 建立第一个空白工程
  • 编写代码点亮LED

下一章,咱们要开始真正接触传感器了。我会带你分析PMS5003的通信协议,并编写驱动代码。嗯,那才是这个课程的核心。做好准备。

公众号:蓝海资料掘金营,微信deep3321