[STM32] 交互初探:按键与LED的GPIO实战
1. 从零开始搭建STM32开发环境第一次接触STM32开发的朋友可能会被各种专业术语吓到但其实搭建开发环境就像组装乐高积木一样简单。我刚开始学习的时候也走了不少弯路现在就把最实用的经验分享给大家。首先需要准备的是硬件设备。除了STM32开发板推荐使用STM32F103C8T6这种性价比高的型号你还需要一个ST-Link下载器价格在20-30元左右几根杜邦线建议买公对公、公对母各一包面包板中号就够用LED灯建议3mm或5mm的颜色随意220欧姆电阻限流用四脚独立按键淘宝搜索轻触开关就能找到软件方面我强烈推荐使用Keil MDK作为开发环境。虽然网上有人说用Arduino IDE也可以但作为过来人我建议还是用专业工具这样能学到更多底层知识。安装Keil时记得勾选STM32F1系列的设备支持包这个很容易被新手忽略。提示第一次使用ST-Link时可能需要安装驱动可以在ST官网下载ST-Link Utility里面自带驱动。2. GPIO基础概念解析GPIO全称是General Purpose Input/Output翻译过来就是通用输入输出。你可以把它想象成STM32芯片上的一个个小开关每个开关都可以单独控制。我刚开始学的时候总记不住GPIO的工作模式后来发现用家里电灯的开关来类比就很好理解输出模式就像你控制电灯开关可以主动打开或关闭输入模式就像门铃按钮只能检测是否被按下推挽输出开关能同时控制开和关就像双控开关开漏输出只能控制关不能主动开就像只能拉闸不能送电在按键和LED实验中我们需要配置两个GPIO连接按键的GPIO设为上拉输入模式GPIO_Mode_IPU连接LED的GPIO设为推挽输出模式GPIO_Mode_Out_PP这里有个容易踩的坑上拉电阻的选择。STM32内部已经有上拉电阻了所以不需要外接但如果你的按键反应不灵敏可能是上拉电阻值不合适。3. 硬件连接详解硬件连接是很多新手最容易出错的地方。我当初就因为接错线烧过一个LED所以这里要特别仔细说明。LED连接方法将LED的正极长脚通过220欧姆电阻连接到STM32的PA0引脚LED的负极短脚接地GND独立按键连接方法按键的一个引脚接PA1对角引脚接地注意是对角不是相邻的这里有个实用技巧用万用表蜂鸣档测试按键引脚。按下按键会响的两个脚就是一组这样就不用担心接错了。注意STM32的GPIO电压是3.3V千万不要接5V电源否则可能损坏芯片4. 代码编写实战现在进入最关键的代码部分。我会把代码拆解成几个模块来讲这样更容易理解。4.1 LED驱动模块先来看LED.c文件#include stm32f10x.h void LED_Init(void) { // 1. 开启GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 2. 配置GPIO参数 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // PA0 GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; // 速度选择 GPIO_Init(GPIOA, GPIO_InitStructure); // 3. 初始状态设为关闭 GPIO_SetBits(GPIOA, GPIO_Pin_0); }这里有几个关键点一定要先开启时钟否则GPIO无法工作GPIO_Speed选择50MHz是为了确保LED响应速度推挽输出模式能提供较强的驱动能力4.2 按键检测模块Key.c文件要复杂一些因为需要处理按键消抖#include stm32f10x.h #include Delay.h void Key_Init(void) { // 1. 开启GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 2. 配置GPIO参数 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; // PA1 GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; // 上拉输入 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); } unsigned char Key_GetNum(void) { unsigned char KeyNum 0; // 检测按键是否按下 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) 0) { // 消抖延时 Delay_ms(20); // 等待按键释放 while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) 0); Delay_ms(20); KeyNum 1; } return KeyNum; }按键消抖是个很重要的概念。机械按键在按下时会产生抖动如果不处理会导致误判。我实测发现20ms的延时效果最好太短可能无法完全消除抖动太长又会影响响应速度。4.3 主程序逻辑main.c文件负责协调整个系统#include stm32f10x.h #include LED.h #include Key.h int main(void) { // 初始化外设 LED_Init(); Key_Init(); while(1) { // 检测按键 if(Key_GetNum() 1) { // 切换LED状态 if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0)) GPIO_ResetBits(GPIOA, GPIO_Pin_0); else GPIO_SetBits(GPIOA, GPIO_Pin_0); } } }这个主循环采用了事件驱动的设计思想。只有当按键按下时才会执行LED状态切换其他时间MCU处于低功耗状态。这种写法比不断轮询的方式更高效。5. 常见问题排查在实际操作中你可能会遇到这些问题LED不亮检查LED正负极是否接反用万用表测量PA0引脚电压按下按键时应该在0V和3.3V之间变化确认电阻值是否合适220欧姆比较保险按键无反应检查按键是否接在对角线上用万用表测量PA1引脚按下按键时应该从3.3V变为0V确认GPIO模式设置为上拉输入程序下载失败检查ST-Link连接是否正确确认开发板供电正常在Keil的Options for Target - Debug设置中选择正确的ST-Link调试器我遇到过最诡异的问题是按键偶尔会失灵后来发现是因为杜邦线接触不良。所以建议大家尽量使用质量好的连接线或者直接把元件焊在开发板上。