文章目录
- 一、GPIO输入
- 按键简介
- 传感器模块简介
- 硬件电路
- 二、C语言
- C语言数据类型
- C语言宏定义
- C语言typedef
- C语言结构体
- C语言枚举
- 三、练习
- 3.1按键控制LED
- 3.1.1接线图
- 3.1.2代码
- 效果:
- 3.2光敏电阻控制蜂鸣器
- 3.2.1接线图
- 3.2.2代码
- 效果:
一、GPIO输入
STM32 的 GPIO 支持 4 种输入模式:
- 浮空输入(GPIO_Mode_IN_FLOATING)
- 无内部上拉 / 下拉电阻
- 引脚电平由外部信号决定
- 适用于信号源自带驱动能力(如按键接 VCC/GND)
- 上拉输入(GPIO_Mode_IPU)
- 内部连接上拉电阻(默认高电平)
- 适用于检测低电平信号(如按键接地)
- 下拉输入(GPIO_Mode_IPD)
- 内部连接下拉电阻(默认低电平)
- 适用于检测高电平信号(如按键接 VCC)
- 模拟输入(GPIO_Mode_AIN)
- 用于 ADC 采样,禁用数字输入缓冲器
- 不读取数字值,仅用于模拟信号采集
按键简介
-
按键:常见的输入设备,按下导通,松手断开
-
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动
传感器模块简介
传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出。
硬件电路
二、C语言
C语言数据类型
关键字 | 位数 | 表示范围 | stdint****关键字 | ST****关键字 |
---|---|---|---|---|
char | 8 | -128 ~ 127 | int8_t | s8 |
unsigned char | 8 | 0 ~ 255 | uint8_t | u8 |
short | 16 | -32768 ~ 32767 | int16_t | s16 |
unsigned short | 16 | 0 ~ 65535 | uint16_t | u16 |
int | 32 | -2147483648 ~ 2147483647 | int32_t | s32 |
unsigned int | 32 | 0 ~ 4294967295 | uint32_t | u32 |
long | 32 | -2147483648 ~ 2147483647 | ||
unsigned long | 32 | 0 ~ 4294967295 | ||
long long | 64 | -(2^64)/2 ~ (2^64)/2-1 | int64_t | |
unsigned long long | 64 | 0 ~ (2^64)-1 | uint64_t | |
float | 32 | -3.4e38 ~ 3.4e38 | ||
double | 64 | -1.7e308 ~ 1.7e308 |
C语言宏定义
- 关键字:#define
- 用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改
- 定义宏定义: #define ABC 12345
- 引用宏定义: int a = ABC; //等效于int a = 12345;
C语言typedef
-
关键字:typedef
-
用途:将一个比较长的变量类型名换个名字,便于使用
-
定义typedef:
typedef unsigned charuint8_t; unsigned char=uint8_t
-
引用typedef: uint8_t a; //等效于unsigned char a;
C语言结构体
-
关键字:struct
-
用途:数据打包,不同类型变量的集合
-
定义结构体变量:
struct{char x; int y; float z;} StructName;
因为结构体变量类型较长,所以通常用typedef更改变量类型名
- 引用结构体成员:
StructName.x = ‘A’;
StructName.y = 66;
StructName.z = 1.23;
或 pStructName->x = ‘A’; //pStructName为结构体的地址 pStructName->y = 66;
pStructName->z = 1.23;
C语言枚举
关键字:enum
用途:定义一个取值受限制的整型变量,用于限制变量取值范围;宏定义的集合定义
枚举变量:
enum{FALSE = 0, TRUE = 1} EnumName;
因为枚举变量类型较长,所以通常用typedef更改变量类型名
- 引用枚举成员:
EnumName = FALSE;
EnumName = TRUE;
三、练习
3.1按键控制LED
3.1.1接线图
3.1.2代码
Key.c
#include "stm32f10x.h" // 包含STM32F10x系列微控制器的标准外设库头文件
#include "key.h" // 按键模块自定义头文件
#include "Delay.h" // 延时函数头文件/*** @brief 初始化按键GPIO引脚* @param 无* @retval 无* @note 配置PB1和PB11为上拉输入模式*/
void Key_Init(void)
{// 使能GPIOB外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 定义GPIO初始化结构体GPIO_InitTypeDef GPIO_InitStruct;// 配置按键引脚:PB1和PB11GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;// 设置为上拉输入模式(默认高电平,按下接地为低电平)GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;// 输入模式下速度设置无效,但需赋值GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;// 应用GPIO配置到GPIOB端口GPIO_Init(GPIOB, &GPIO_InitStruct);
}/*** @brief 检测按键并返回按键编号* @param 无* @retval uint8_t: 按键编号(1-按键1,2-按键2,0-无按键)* @note 使用轮询方式检测按键,包含消抖处理*/
uint8_t Key_GetNum(void)
{uint8_t KeyNum = 0; // 初始化按键编号为0(无按键)// 检测按键1(PB1)是否按下if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0){Delay_ms(20); // 消抖延时(硬件抖动通常小于20ms)// 确认按键确实按下(排除抖动)while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)Delay_ms(20); // 等待按键释放KeyNum = 1; // 设置按键编号为1}// 检测按键2(PB11)是否按下if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0){Delay_ms(20); // 消抖延时// 确认按键确实按下while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)Delay_ms(20); // 等待按键释放KeyNum = 2; // 设置按键编号为2}return KeyNum; // 返回按键编号
}
LED.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);}void LED1_ON(void)
{GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}void LED1_OFF(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_1);
}void LED2_ON(void)
{GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}void LED2_OFF(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
void LED1_Turn(void)
{if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1) == 0){GPIO_SetBits(GPIOA, GPIO_Pin_1);}else{GPIO_ResetBits(GPIOA, GPIO_Pin_1);}
}
void LED2_Turn(void)
{if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) == 0){GPIO_SetBits(GPIOA, GPIO_Pin_2);}else{GPIO_ResetBits(GPIOA, GPIO_Pin_2);}
}
main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "led.h"
#include "Key.h"uint8_t KeyNum;int main(void)
{// 外设初始化LED_Init();Key_Init();// 主循环while(1){// 读取按键值KeyNum = Key_GetNum();// 消抖处理(假设Key_GetNum已包含消抖)// 按键处理if(KeyNum == 1){LED1_Turn(); // 切换LED1状态Delay_ms(20); // 消抖延时}else if(KeyNum == 2){LED2_Turn(); // 切换LED2状态Delay_ms(20); // 消抖延时}}
}
效果:
- 在主循环中持续检测按键状态
- 当检测到按键 1(PB1)按下时,切换 LED1 的状态(亮→灭 或 灭→亮)
- 当检测到按键 2(PB11)按下时,切换 LED2 的状态
3.2光敏电阻控制蜂鸣器
3.2.1接线图
3.2.2代码
main.c
#include "stm32f10x.h" // 包含STM32F10x系列设备的头文件
#include "Delay.h"
#include "led.h"
#include "Buzzer.h"
#include "LightSensor.h"uint8_t KeyNum;int main(void)
{ Buzzer_Init();LightSensor_Init();while(1) // 进入无限循环,保持程序运行{if(LightSensor_Get() == 1){Buzzer_ON();}else{Buzzer_OFF();}
}}
LightSensor.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"/*** @brief 初始化光敏传感器(数字输出型)* @param 无* @retval 无* @note 配置PB13为上拉输入模式*/
void LightSensor_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入:默认高电平GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);
}/*** @brief 检测PB13引脚电平状态* @param 无* @retval uint8_t: 1-引脚为高电平,0-引脚为低电平*/
uint8_t LightSensor_Get(void)
{return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}
功能说明
-
初始化函数:配置 PB13 为上拉输入模式,无信号时引脚默认保持高电平
-
读取函数
:直接返回 PB13 引脚的电平状态
- 当引脚为高电平时返回 1
- 当引脚为低电平时返回 0
Buzzer.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"void Buzzer_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);}void Buzzer_ON(void)
{GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}void Buzzer_OFF(void)
{GPIO_SetBits(GPIOB, GPIO_Pin_12);
}/*** @brief 切换蜂鸣器状态(开→关 或 关→开)* @param 无* @retval 无*/
void Buzzer_Turn(void)
{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12) == 0){GPIO_SetBits(GPIOB, GPIO_Pin_12);// 当前为低电平(开启状态),切换为高电平}else{GPIO_ResetBits(GPIOB, GPIO_Pin_12);// 当前为高电平(关闭状态),切换为低电平}
}
效果:
无光照(PB13=1)→ LightSensor_Get()
返回 1
→ 蜂鸣器响
有光照(PB13=0)→ LightSensor_Get()
返回 0
→ 蜂鸣器停