Day1学习知识点总结
底层基础:掌握 RCC 时钟总线作用,学会开启 GPIO 端口时钟;分清 GPIO 推挽输出、上拉输入两种常用模式,以及配套读写 API 使用规范。
外设实操:完成 LED、有源蜂鸣器、独立按键、光电传感器硬件接线与驱动编写,掌握共阳极器件电平逻辑、按键软件消抖方法。
工程规范:学习模块化开发思路,外设拆分独立.c/.h 驱动文件,main 函数仅保留业务逻辑,实现代码复用与便捷维护。
今日完整学习总览
基础层(前置点灯内容)
STM32 工程搭建、面包板硬件接线规范
RCC 时钟总线原理、GPIO 引脚核心配置逻辑
GPIO推挽输出实战:共阳极 LED 点灯、周期闪灯
拓展层(新增外设模块)
GPIO 输出拓展:有源蜂鸣器驱动(PB0 推挽输出)
GPIO 输入两类实战:独立按键(PB1 上拉输入、软件消抖)、光电遮挡传感器(PB2 上拉输入)
区分 GPIO 全部输入 / 输出模式,理清单片机输出控制外设、读取外部信号两套底层逻辑
工程标准化拆分:外设独立.c/.h驱动,main 只写业务逻辑,实现代码复用、易维护
标准化毫秒级软件延时,适配消抖、降 CPU 扫描负载场景
二、全部硬件电路汇总(统一引脚分配)
- LED 指示灯(基础点灯)
硬件:共阳极接法,LED 长脚接 3.3V,短脚串限流电阻接PA0
电平逻辑:PA0 输出低电平→灯亮;PA0 高电平→灯灭
- 有源蜂鸣器
硬件:正极串 1k 电阻接PB0,负极接 GND,自带振荡电路
电平逻辑:PB0 低电平→蜂鸣器响;PB0 高电平→静音;模式:推挽输出 Out_PP
- 独立机械按键
硬件:一端PB1、一端 GND,开启芯片内部上拉电阻 IPU
电平逻辑:松开 = 引脚高电平 1;按下 = 引脚低电平 0;必须软件消抖
- 光电遮挡传感器模块
供电:VCC 接 3.3V、GND 共地;信号 OUT 接PB2
电平逻辑:无遮挡 = 高电平 1;有遮挡 = 低电平 0;上拉输入 IPU,无需消抖
三、核心底层原理整合(RCC+GPIO 输入输出)
- RCC 外设时钟(所有实验通用前置)
RCC 是 STM32 外设总开关,所有 GPIO 挂载在 APB2 总线,使用前必须开启对应端口时钟:
AHB:高速 DMA、SD 卡(初学不用)
APB2:GPIOA/GPIOB/GPIOC、ADC、TIM1、USART1(本节课全部外设)
APB1:普通定时器、I2C、USART2/3(后续学习)
核心规则:时钟整组开启,无法单独开启某一个引脚;仅初始化过的引脚生效,其余默认浮空输入。
开启函数示例:
- GPIO 两大类型完整区分(重点整合)
(1)Output 输出模式:单片机向外输出 0/1,控制 LED、蜂鸣器
输出核心 API:
GPIO_ResetBits(GPIOx,GPIO_Pin_x):输出低电平0GPIO_SetBits(GPIOx,GPIO_Pin_x):输出高电平1(2)Input 输入模式:单片机被动读取外部按键 / 传感器电平
输入读取 API:
四、三大完整实操实验逻辑
实验 1:基础 LED 闪灯(前置入门)
开启 GPIOA 时钟
PA0 初始化为 50MHz 推挽输出,上电默认高电平(灯灭)
循环:拉低 PA0 亮灯→延时→拉高 PA0 灭灯→延时往复
实验 2:按键控制蜂鸣器
开启 GPIOB 时钟,PB0 输出、PB1 上拉输入
循环读取 PB1 电平:
读到 0(按键按下):拉低 PB0,蜂鸣器鸣叫
读到 1(按键松开):执行光电传感器判断逻辑
机械按键增加delay_ms(10)消抖,消除电平抖动误触发
实验 3:光电传感器自动报警
PB2 配置上拉输入,循环读取传感器电平
有遮挡(返回 0):蜂鸣器鸣叫;无遮挡(返回 1):蜂鸣器关闭
主循环增加 50ms 延时,降低扫描频率,减少 CPU 占用
五、模块化工程分层结构(核心工程化思想)
摒弃全部代码写在 main.c 的写法,外设驱动与业务逻辑分离,文件划分如下:
main.c:仅外设初始化调用 + while (1) 业务判断逻辑,无底层引脚配置
led.c + led.h:LED 点灯驱动,封装初始化、亮灯、灭灯接口
beep.c + beep.h:蜂鸣器驱动,封装初始化、开 / 关蜂鸣
key.c + key.h:按键驱动,封装初始化、带消抖按键读取函数
sensor.c + sensor.h:光电传感器驱动,封装初始化、遮挡状态读取
delay.c + delay.h:统一毫秒级软件延时函数,全工程复用
模块化优势
修改硬件引脚仅改动对应外设.c,不影响其他模块代码
主函数逻辑极简,可读性强,后期拓展外设无需重构
整套驱动文件可直接复制到其他 STM32 工程复用
七、今日整合知识点总结(大白话)
RCC 是电源开关,GPIO 是引脚精细控制器,必须先开时钟再配置引脚,否则所有 IO 失效。
GPIO 分输出、输入两类:输出是单片机控制外部器件(LED、蜂鸣器主推挽输出);输入是单片机读取外部信号(按键、传感器优先上拉输入)。
共阳极 LED、有源蜂鸣器电平逻辑统一:低电平工作,高电平关闭。
机械按键存在电平抖动,必须加 10ms 软件延时消抖,传感器无机械结构无需消抖。
工程必须模块化拆分:外设单独.c/.h,main 只做逻辑判断,方便维护、移植。
输出函数SetBits/ResetBits只能控制外设,输入读取只能用GPIO_ReadInputDataBit,两类 API 不可混用。
所有 PB 引脚外设共用 GPIOB 时钟,PA0 LED 单独开启 GPIOA 时钟,多端口工程需用|同时开启多路时钟。
八、整合后完整易错点清单
代码笔误:蜂鸣器操作引脚全部是 GPIOB,原文误写 GPIOA 会导致蜂鸣器无响应。
忘记开启对应端口时钟:LED 不开 GPIOA、蜂鸣 / 按键 / 传感器不开 GPIOB,引脚完全无输出 / 读取。
按键配置浮空输入:无上下拉电阻,手靠近引脚电平乱跳,按键频繁误触发。
输入输出 API 混用:用ReadInputDataBit控制蜂鸣器、用SetBits读取按键电平,编译无报错但功能完全失效。
所有业务逻辑堆在 main.c:后期添加流水灯、串口等外设时代码臃肿,修改困难。
主循环无延时,高频读取传感器 / 按键:CPU 满载占用,程序卡顿。
上电不初始化外设默认电平:LED、蜂鸣器上电瞬间误触发,初始化时统一置高电平关闭外设。
| c
// 同时开启PA、PB端口时钟(LED用PA0,蜂鸣/按键/传感器用PB)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); |
| — |
| 输出模式 | 特点 | 适用场景 | 本节课使用 |
|---|---|---|---|
| 推挽输出 Out_PP | 高低电平驱动能力都强 | LED、蜂鸣器、普通 IO 控制 | 全部输出外设 |
| 开漏输出 Out_OD | 仅能主动拉低,拉高依赖外部上拉 | I2C 通信,初学不使用 | 无 |
| 输入模式 | 特点 | 适用场景 | 本节课使用 |
|---|---|---|---|
| 浮空输入 IN_FLOATING | 无上下拉,电平极易受干扰 | 高速模拟信号,按键禁用 | 无 |
| 上拉输入 IPU | 内部自带上拉,默认高电平,抗干扰强 | 独立按键、光电传感器信号脚 | PB1 按键、PB2 传感器 |
| 下拉输入 IPD | 内部自带下拉,默认低电平 | 特殊按键电路 | 无 |
c// 返回值1=高电平,0=低电平uint8_tGPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x);c#ifndef__DELAY_H#define__DELAY_Hvoiddelay_ms(uint32_tt);#endifc#include"delay.h"voiddelay_ms(uint32_tt){uint32_ti,j;for(i=t;i>0;i--)for(j=7200;j>0;j--);}c#ifndef__LED_H#define__LED_HvoidLED_Init(void);voidLED_On(void);voidLED_Off(void);#endifc#include"led.h"#include"stm32f10x.h"voidLED_Init(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_SetBits(GPIOA,GPIO_Pin_0);//上电默认灭灯}voidLED_On(void){GPIO_ResetBits(GPIOA,GPIO_Pin_0);}voidLED_Off(void){GPIO_SetBits(GPIOA,GPIO_Pin_0);}c#ifndef__BEEP_H#define__BEEP_HvoidBEEP_Init(void);voidBEEP_On(void);voidBEEP_Off(void);#endifc#include"beep.h"#include"stm32f10x.h"voidBEEP_Init(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_0);//上电默认关闭蜂鸣器}voidBEEP_On(void){GPIO_ResetBits(GPIOB,GPIO_Pin_0);}voidBEEP_Off(void){GPIO_SetBits(GPIOB,GPIOB,GPIO_Pin_0);}c#ifndef__KEY_H#define__KEY_HvoidKEY_Init(void);uint8_tKEY_Read(void);//返回1松开,0按下#endifc#include"key.h"#include"stm32f10x.h"#include"delay.h"voidKEY_Init(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOB,&GPIO_InitStruct);}uint8_tKEY_Read(void){if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0){delay_ms(10);//消抖延时while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0);//等待松开delay_ms(10);return0;}return1;}c#ifndef__SENSOR_H#define__SENSOR_HvoidSENSOR_Init(void);uint8_tSENSOR_Read(void);//0有遮挡,1无遮挡#endifc#include"sensor.h"#include"stm32f10x.h"voidSENSOR_Init(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init(GPIOB,&GPIO_InitStruct);}uint8_tSENSOR_Read(void){returnGPIO_ReadInputDataBit(GPIOB,GPIOB,GPIO_Pin_2);}c#include"stm32f10x.h"#include"led.h"#include"beep.h"#include"key.h"#include"sensor.h"#include"delay.h"intmain(void){//全部外设初始化,仅调用封装好的驱动函数LED_Init();BEEP_Init();KEY_Init();SENSOR_Init();while(1){//功能1:基础LED周期闪烁LED_On();delay_ms(500);LED_Off();delay_ms(500);//功能2:按键优先控制蜂鸣器if(KEY_Read()==0){BEEP_On();}else{//功能3:无按键按下时,光电传感器自动报警if(SENSOR_Read()==0)BEEP_On();elseBEEP_Off();}delay_ms(50);}}