开发环境STM32F103Keil μVision 5STM32 标准外设库摘要今天完成了蜂鸣器模块封装、光敏传感器控制、对射式红外计数和旋转编码器实验。本文只保留已经确认的现象、原因、解决方法和关键代码。1. 蜂鸣器编译下载正常但没有声音现象调用 BUZZER_ON() 后蜂鸣器不响。原因蜂鸣器接在 PB12但 Buzzer.c 有一处把 GPIOB 误写成 GPIOA。解决方法统一检查 RCC 时钟、GPIO_Init() 和 SetBits/ResetBits 使用的端口全部改为 GPIOB。验证结果改回 GPIOB 后蜂鸣器正常工作。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_Init(GPIOB, GPIO_InitStructure);GPIO_ResetBits(GPIOB, GPIO_Pin_12);GPIO_SetBits(GPIOB, GPIO_Pin_12);2. Delay.h 中的 uint32_t 标红但能编译现象Keil 给 uint32_t 画红色波浪线但工程能正常编译下载。原因真正编译时其他文件先包含了 stm32f10x.h编辑器单独分析 Delay.h 时找不到类型定义。解决方法在 Delay.h 中直接包含 stdint.h。验证结果红色提示消失头文件依赖更规范。#ifndef __DELAY_H#define __DELAY_H#include stdint.hvoid Delay_us(uint32_t us);void Delay_ms(uint32_t ms);void Delay_s(uint32_t s);#endif图 1 Delay.h 中 uint32_t 的编辑器红色提示3. 输入括号会覆盖后面的等号现象补函数调用括号时后面的 被覆盖。原因Keil 进入了覆盖输入模式。解决方法按一次 Insert笔记本可尝试 Fn Insert。验证结果恢复插入模式后可正常输入。if (LightSensor_Get() 1){BUZZER_ON();}else{BUZZER_OFF();}图 2 Keil 覆盖输入模式4. CountSensor.c 连续出现变量声明和括号错误现象出现 declaration may not appear...、expected a ; 等错误。原因结构体变量写在执行语句后同时把中断函数写进了 CountSensor_Init() 内部。解决方法把 GPIO/EXTI/NVIC 结构体统一放在函数开头中断函数写在初始化函数外。验证结果修改后工程可正常编译。5. 对射式红外传感器电源灯不亮现象传感器电源灯不亮程序能正常编译下载。原因面包板插孔接触不良模块没有真正获得供电。解决方法更换插孔位置并优先检查 VCC、GND、杜邦线和面包板导通。验证结果更换位置后电源灯恢复。6. unit16_t 未定义现象编译提示 identifier unit16_t is undefined。原因将 uint16_t 拼写成了 unit16_t。解决方法改回 uint16_t并在头文件中包含 stdint.h。验证结果重新编译通过。uint16_t CountSensor_Get(void);7. Keil Browse Information 不可用现象Encoder.c 能打开但右键跳转和源码浏览不可用。原因Browse Information 数据库未生成或未更新。解决方法执行 Project → Rebuild All Target Files必要时勾选 Browse Information。验证结果重新编译后恢复。图 3 Encoder.c 的 Browse Information 尚未生成8. Encoder.c 一次出现多个编译错误现象出现函数未定义、expected a declaration、GPIO_Pin0 未定义等错误。原因函数嵌套GPIO_Pin0/1 少下划线if 写成 f大括号层级被破坏。解决方法保持 Encoder_Init、Encoder_Get、EXTI0_IRQHandler、EXTI1_IRQHandler 四个函数同级修正宏名和 if。验证结果工程编译通过编码器可正常计数。9. 编码器旋转方向与视频相反现象顺时针时数字减小交换 A/B 后变为增加。原因编码器方向由 A、B 两相信号的先后顺序决定。模块丝印、安装方向或接线顺序不同方向可能与视频相反。解决方法交换 A/B 接线或保持接线并交换中断中的 与 --。验证结果交换 A/B 后顺时针增加说明编码器和代码功能正常。10. 对射红外计数模块工作链路物体遮挡传感器后PB14 产生下降沿EXTI14 发出中断请求NVIC 允许 CPU 响应程序进入 EXTI15_10_IRQHandler() 完成计数并清除标志位。void EXTI15_10_IRQHandler(void){if (EXTI_GetITStatus(EXTI_Line14) SET){CountSensor_Count;EXTI_ClearITPendingBit(EXTI_Line14);}}固定排查清单• Build Output 是否为 0 Error。• 程序是否成功下载并真正运行。• 外设 VCC、GND 和电源指示灯。• 面包板和杜邦线是否真正导通。• RCC 时钟、GPIO 端口和引脚是否一致。• 类型名、函数名、宏名称和英文标点。• 中断函数是否写在初始化函数外。• EXTI 映射、触发沿和 NVIC 通道是否匹配。• 编码器方向异常时检查 A/B 相位顺序。
STM32 小白实战 02:从蜂鸣器到旋转编码器,外部中断与工程调试踩坑总结
开发环境STM32F103Keil μVision 5STM32 标准外设库摘要今天完成了蜂鸣器模块封装、光敏传感器控制、对射式红外计数和旋转编码器实验。本文只保留已经确认的现象、原因、解决方法和关键代码。1. 蜂鸣器编译下载正常但没有声音现象调用 BUZZER_ON() 后蜂鸣器不响。原因蜂鸣器接在 PB12但 Buzzer.c 有一处把 GPIOB 误写成 GPIOA。解决方法统一检查 RCC 时钟、GPIO_Init() 和 SetBits/ResetBits 使用的端口全部改为 GPIOB。验证结果改回 GPIOB 后蜂鸣器正常工作。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_Init(GPIOB, GPIO_InitStructure);GPIO_ResetBits(GPIOB, GPIO_Pin_12);GPIO_SetBits(GPIOB, GPIO_Pin_12);2. Delay.h 中的 uint32_t 标红但能编译现象Keil 给 uint32_t 画红色波浪线但工程能正常编译下载。原因真正编译时其他文件先包含了 stm32f10x.h编辑器单独分析 Delay.h 时找不到类型定义。解决方法在 Delay.h 中直接包含 stdint.h。验证结果红色提示消失头文件依赖更规范。#ifndef __DELAY_H#define __DELAY_H#include stdint.hvoid Delay_us(uint32_t us);void Delay_ms(uint32_t ms);void Delay_s(uint32_t s);#endif图 1 Delay.h 中 uint32_t 的编辑器红色提示3. 输入括号会覆盖后面的等号现象补函数调用括号时后面的 被覆盖。原因Keil 进入了覆盖输入模式。解决方法按一次 Insert笔记本可尝试 Fn Insert。验证结果恢复插入模式后可正常输入。if (LightSensor_Get() 1){BUZZER_ON();}else{BUZZER_OFF();}图 2 Keil 覆盖输入模式4. CountSensor.c 连续出现变量声明和括号错误现象出现 declaration may not appear...、expected a ; 等错误。原因结构体变量写在执行语句后同时把中断函数写进了 CountSensor_Init() 内部。解决方法把 GPIO/EXTI/NVIC 结构体统一放在函数开头中断函数写在初始化函数外。验证结果修改后工程可正常编译。5. 对射式红外传感器电源灯不亮现象传感器电源灯不亮程序能正常编译下载。原因面包板插孔接触不良模块没有真正获得供电。解决方法更换插孔位置并优先检查 VCC、GND、杜邦线和面包板导通。验证结果更换位置后电源灯恢复。6. unit16_t 未定义现象编译提示 identifier unit16_t is undefined。原因将 uint16_t 拼写成了 unit16_t。解决方法改回 uint16_t并在头文件中包含 stdint.h。验证结果重新编译通过。uint16_t CountSensor_Get(void);7. Keil Browse Information 不可用现象Encoder.c 能打开但右键跳转和源码浏览不可用。原因Browse Information 数据库未生成或未更新。解决方法执行 Project → Rebuild All Target Files必要时勾选 Browse Information。验证结果重新编译后恢复。图 3 Encoder.c 的 Browse Information 尚未生成8. Encoder.c 一次出现多个编译错误现象出现函数未定义、expected a declaration、GPIO_Pin0 未定义等错误。原因函数嵌套GPIO_Pin0/1 少下划线if 写成 f大括号层级被破坏。解决方法保持 Encoder_Init、Encoder_Get、EXTI0_IRQHandler、EXTI1_IRQHandler 四个函数同级修正宏名和 if。验证结果工程编译通过编码器可正常计数。9. 编码器旋转方向与视频相反现象顺时针时数字减小交换 A/B 后变为增加。原因编码器方向由 A、B 两相信号的先后顺序决定。模块丝印、安装方向或接线顺序不同方向可能与视频相反。解决方法交换 A/B 接线或保持接线并交换中断中的 与 --。验证结果交换 A/B 后顺时针增加说明编码器和代码功能正常。10. 对射红外计数模块工作链路物体遮挡传感器后PB14 产生下降沿EXTI14 发出中断请求NVIC 允许 CPU 响应程序进入 EXTI15_10_IRQHandler() 完成计数并清除标志位。void EXTI15_10_IRQHandler(void){if (EXTI_GetITStatus(EXTI_Line14) SET){CountSensor_Count;EXTI_ClearITPendingBit(EXTI_Line14);}}固定排查清单• Build Output 是否为 0 Error。• 程序是否成功下载并真正运行。• 外设 VCC、GND 和电源指示灯。• 面包板和杜邦线是否真正导通。• RCC 时钟、GPIO 端口和引脚是否一致。• 类型名、函数名、宏名称和英文标点。• 中断函数是否写在初始化函数外。• EXTI 映射、触发沿和 NVIC 通道是否匹配。• 编码器方向异常时检查 A/B 相位顺序。