4、单片机选型与开发环境:STM32与ESP32对比,Keil/Arduino IDE搭建,GPIO与中断配置

做多级预警系统,第一步就是选“大脑”。

我见过不少新手,一上来就纠结STM32还是ESP32。其实没那么玄乎。说白了,这两款芯片都是好料子,但脾气秉性完全不同。今天我就结合自己做烟感+气体传感器项目的经验,跟你聊聊怎么选、怎么搭环境、怎么把GPIO和中断玩明白。

4.1 STM32 vs ESP32:选型对比

先看一张对比表,心里有个底:

对比项 STM32(以F103为例) ESP32
内核 Cortex-M3,纯MCU Xtensa LX6双核,MCU+WiFi/BLE
主频 72MHz 240MHz
RAM/Flash 20KB/64KB(入门级) 520KB/4MB(典型)
无线能力 无(需外挂模块) 内置WiFi+蓝牙
功耗 低(uA级待机) 较高(WiFi开启时mA级)
开发环境 Keil MDK / STM32CubeIDE Arduino IDE / ESP-IDF
价格 约8-15元(F103C8T6) 约15-25元(ESP32-WROOM-32)
适合场景 工业控制、低功耗、实时性要求高 物联网、需要联网、快速原型

我个人习惯这样选:

  • 如果预警系统是独立运行的,比如工厂里的本地声光报警,不依赖云平台——我选STM32。它稳定、抗干扰强,我在一个化工厂项目里用过STM32F103,连续跑了两年没重启过。
  • 如果预警系统需要联网,比如把数据传到手机App或云平台——我选ESP32。它自带WiFi,省一个通信模块的钱和空间。我做过一个家用燃气报警器,ESP32直接连MQTT,调试起来特别快。
我的小建议: 如果你刚开始学,或者做课程原型,先用ESP32+Arduino IDE。上手快,踩坑少。等把逻辑调通了,再移植到STM32上做产品化。

4.2 开发环境搭建:Keil vs Arduino IDE

环境搭建这件事,说难不难,说简单也容易卡住。我分别说说两种方式。

4.2.1 Keil MDK(针对STM32)

Keil是老牌工具了。我当年入行时用的就是它,界面虽然复古,但功能扎实。

搭建步骤:

  1. 去Keil官网下载MDK-Arm,安装时注意选对版本(我用的是5.38)。
  2. 安装芯片包:打开Pack Installer,搜索STM32F1系列,下载安装。
  3. 新建工程:Project → New μVision Project,选芯片型号(比如STM32F103C8)。
  4. 添加启动文件、系统文件、你的main.c。
  5. 配置烧录器:我用ST-Link,在Debug选项卡里选ST-Link Debugger。
注意: Keil的编译器默认用ARMCC v5,如果你用新版的MDK,记得在Target选项卡里把编译器版本选对。我曾经因为编译器版本不对,编译出来的代码跑飞了,查了整整一下午。

4.2.2 Arduino IDE(针对ESP32)

Arduino IDE就友好多了。说白了,它把底层封装好了,你只管写逻辑。

搭建步骤:

  1. 下载Arduino IDE(我用的是2.x版本,界面清爽很多)。
  2. 添加ESP32开发板:文件 → 首选项 → 附加开发板管理器网址,填入:https://espressif.github.io/arduino-esp32/package_esp32_index.json
  3. 工具 → 开发板管理器,搜索ESP32,安装。
  4. 选择开发板:工具 → 开发板 → ESP32 Arduino → ESP32 Dev Module。
  5. 写代码,点上传。搞定。
避坑指南: 我第一次用Arduino IDE烧录ESP32时,一直报“A fatal error occurred: Failed to connect to ESP32”。后来发现是按住BOOT键再按EN键进入下载模式。嗯,这个坑我替你们踩过了。

4.3 GPIO配置:点亮一个LED开始

不管用哪款芯片,GPIO都是最基础的操作。我习惯先点亮一个LED,确认硬件和软件都通了,再往下做。

4.3.1 STM32的GPIO配置(HAL库)

// 初始化GPIO
void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟

    GPIO_InitStruct.Pin = GPIO_PIN_13;  // PC13接LED
    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);
}

// 主循环中翻转LED
while (1)
{
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    HAL_Delay(500);
}

你看,HAL库的代码虽然啰嗦,但结构清晰。我在项目中习惯用HAL库,因为可读性好,后期维护方便。

4.3.2 ESP32的GPIO配置(Arduino框架)

#define LED_PIN 2  // 开发板上的LED通常接GPIO2

void setup() {
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    digitalWrite(LED_PIN, HIGH);
    delay(500);
    digitalWrite(LED_PIN, LOW);
    delay(500);
}

Arduino的代码就简洁多了。你想想看,三行代码搞定一个闪烁LED。这就是为什么我推荐原型阶段用Arduino——快,真快。

4.4 中断配置:让系统学会“抢答”

预警系统里,中断是灵魂。为什么?因为传感器触发报警时,你不能让CPU轮询等待,必须立刻响应。中断就是让CPU学会“抢答”。

4.4.1 STM32的外部中断配置

我以按键触发中断为例,这个在预警系统中很常见——比如手动消音按钮。

// 配置PA0为外部中断(下降沿触发)
void MX_EXTI_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  // 下降沿触发
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

// 中断服务函数
void EXTI0_IRQHandler(void)
{
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
    {
        // 处理中断:比如关闭蜂鸣器
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
    }
}
关键点: 中断服务函数里不要做复杂操作,比如延时、打印。我见过有人直接在中断里写HAL_Delay(1000),结果系统直接卡死。中断里只做标志位设置或简单IO操作,复杂逻辑放到主循环里处理。

4.4.2 ESP32的中断配置

ESP32的Arduino框架下,中断配置更简单:

#define BUTTON_PIN 0  // 开发板上的BOOT按钮

void IRAM_ATTR buttonISR() {
    // 注意:中断里不要用Serial.print()
    // 只做标志位操作
    alarmFlag = true;
}

void setup() {
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);
}

void loop() {
    if(alarmFlag) {
        alarmFlag = false;
        // 处理报警逻辑
        Serial.println("Alarm triggered!");
    }
}

这里有个细节:IRAM_ATTR 这个修饰符。ESP32的中断函数必须放在IRAM中运行,否则可能触发看门狗复位。我第一次用ESP32做中断时没加这个,结果系统动不动就重启,查了好久才发现。

4.5 本章知识体系

下面这张图,帮你理清本章的核心逻辑:

第4章:单片机选型与开发环境 选型对比 STM32:稳定、低功耗 ESP32:联网、快速原型 开发环境搭建 Keil MDK(STM32) Arduino IDE(ESP32) GPIO与中断配置 核心思路:先选型 → 搭环境 → 跑通GPIO和中断

嗯,这张图把本章的三个核心模块串起来了。你跟着这个顺序走,基本不会乱。

总结一下:
  • 选型看需求:要联网选ESP32,要稳定选STM32。
  • 环境搭建:Keil适合深度开发,Arduino适合快速验证。
  • GPIO是基础,中断是灵魂。预警系统里,中断响应速度直接决定系统可靠性。

我个人的经验是:不管选哪款芯片,先把GPIO和中断玩熟。这两个搞定了,剩下的就是传感器驱动和逻辑组合了。下一章我们开始实战——把烟感传感器接上去,看看数据怎么读。


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