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,调试起来特别快。
4.2 开发环境搭建:Keil vs Arduino IDE
环境搭建这件事,说难不难,说简单也容易卡住。我分别说说两种方式。
4.2.1 Keil MDK(针对STM32)
Keil是老牌工具了。我当年入行时用的就是它,界面虽然复古,但功能扎实。
搭建步骤:
- 去Keil官网下载MDK-Arm,安装时注意选对版本(我用的是5.38)。
- 安装芯片包:打开Pack Installer,搜索STM32F1系列,下载安装。
- 新建工程:Project → New μVision Project,选芯片型号(比如STM32F103C8)。
- 添加启动文件、系统文件、你的main.c。
- 配置烧录器:我用ST-Link,在Debug选项卡里选ST-Link Debugger。
4.2.2 Arduino IDE(针对ESP32)
Arduino IDE就友好多了。说白了,它把底层封装好了,你只管写逻辑。
搭建步骤:
- 下载Arduino IDE(我用的是2.x版本,界面清爽很多)。
- 添加ESP32开发板:文件 → 首选项 → 附加开发板管理器网址,填入:
https://espressif.github.io/arduino-esp32/package_esp32_index.json - 工具 → 开发板管理器,搜索ESP32,安装。
- 选择开发板:工具 → 开发板 → ESP32 Arduino → ESP32 Dev Module。
- 写代码,点上传。搞定。
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);
}
}
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 本章知识体系
下面这张图,帮你理清本章的核心逻辑:
嗯,这张图把本章的三个核心模块串起来了。你跟着这个顺序走,基本不会乱。
- 选型看需求:要联网选ESP32,要稳定选STM32。
- 环境搭建:Keil适合深度开发,Arduino适合快速验证。
- GPIO是基础,中断是灵魂。预警系统里,中断响应速度直接决定系统可靠性。
我个人的经验是:不管选哪款芯片,先把GPIO和中断玩熟。这两个搞定了,剩下的就是传感器驱动和逻辑组合了。下一章我们开始实战——把烟感传感器接上去,看看数据怎么读。
公众号:蓝海资料掘金营,微信deep3321