STM32按键控制学习指南
一.按键控制
1.封装
直接复制之前做过的文件更方便,不用再重头配置,改名为按键控制,点开
在改文件夹下新建文件夹Hardware,存放硬件驱动
如之前新建同样的操作(上一篇),在魔术棒和三角堆加入Hardware
新建.c 文件,用来封装LED驱动文件
.h 存放驱动程序可以对外提供的函数或变量声明
.c右键添加头文件
.h中添加防止头文件重复包含的代码,这里是固定格式
注意:这里前面是两个下划线,而且下划线前要加空格,最后空行结尾
打开LED.c文件,写入初始化函数void LED_Init(void),在函数里打开时钟,配置端口模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开时钟
配置端口模式
不提示代码的话试一下,按ctrl+alt+空格
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
这里的(GPIOA, &GPIO_InitStructure),第一个参数初始化GPIOA外设,第二个是结构体变量名,&是取地址符号,地址传递
在.h文件添加void LED_Init(void)声明函数可被外部调用
在main.c上面添加 #include "LED.h" 包含LED的模块的头文件
在主函数中调用LED_init,完成初始化,编译下载两个LED都是亮的状态
在LED.c文件中再加入这句,这样不操作LED就是熄灭状态
GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
定义LED的开和关
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);
然后在.h文件中声明
在主函数中调用,下载编译可以看到两个LED灯交替闪烁
main.c代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
int main(void)
{
LED_Init();
while(1)
{
LED1_ON();
LED2_OFF();
Delay_ms(500);
LED1_OFF();
LED2_ON();
Delay_ms(500);
}
}
2.按键
同上步一样,右键Hardware,新建.c .h文件
在.c添加头文件,.h搭建基本框架
#ifndef __LED_H
#define __LED_H#endif
在Key.c文件写初始化函数 void Key_Init(void)
将按键的两个端口初始化为上拉输入的模式(按下低电平,松手高电平)
添加读取按键值的函数
uint8_t就是unsigned char(用于表示0到255之间的整数值,不包含负数)
uint8_t Key_GetNum(void) //调用函数,返回按下按键的键码
定义变量 uint8_t KeyNum = 0;
接下来写读取按键端口的功能
打开Library,找到gpio.h滑到最后
GPIO的读取函数
GPIO_ReadInputDataBit 读取输入数据寄存器某一端口的输入值
GPIO_ReadInputData 读取整个输入数据寄存器
GPIO_ReadOutputDataBit 读取输出数据寄存器的某一位
GPIO_ReadOutputData 读取整个输出数据寄存器
0代表低电平,1代表高电平
如果读取PB1端口=0,就代表按键按下
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
按键按下时会有抖动,在上面添加 #include "Delay.h"
然后添加 Delay_ms消除抖动
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
Delay_ms(20);
KeyNum = 1; //传递键码
然后在.h文件声明函数(这里uint8出错可以不管,想解决看最后)
在main.c文件上加入 #include "Key.h"
主循环之前初始化按键 Key_Init();
然后定义全局变量
uint8_t KeyNum; //存放键码的返回值
main.c完整代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"uint8_t KeyNum;
int main(void)
{
LED_Init();
Key_Init();
while(1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
LED1_ON();
}
if (KeyNum == 2)
{
LED2_OFF();
}
}
}
想要实现按下点亮,再按熄灭
驱动文件中调用 void LED1_Turn(void) 函数,LED状态取反
调用 GPIO_ReadOutputDataBit 函数,读取当前端口输出状态,输出0,置1,否则置0,实现端口电平翻转
LED.c代码
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开时钟GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
}
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
void LED1_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
else
{
GPIO_ResetBits(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 LED2_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}
}
在头文件中声明
主文件中改为 LED1_Turn,编译下载
二.光敏传感器控制蜂鸣器
1.封装蜂鸣器
复制上面的文件改名为光敏传感器控制蜂鸣器,同样右键Hardware,新建.c和.h文件
同之前一样.c文件添加头文件,.h文件添加框架
复制LED.c的内容到Buzzer.c中,修改为Buzzer_Init、Buzzer_ON、Buzzer_OFF、Buzzer_Turn,引脚改为开启GPIOB的时钟,GPIOB, GPIO_Pin_12
#include "stm32f10x.h" // Device header
void Buzzer_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_ON(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_OFF(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
else
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
}
声明函数
修改main.c,编译下载测试,蜂鸣器鸣响
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
uint8_t KeyNum;
int main(void)
{
Buzzer_Init(); //初始化蜂鸣器
while(1)
{
Buzzer_ON();
Delay_ms(500);
Buzzer_OFF();
Delay_ms(500);
Buzzer_Turn();
Delay_ms(500);
Buzzer_Turn();
Delay_ms(500);
}
}
2.封装光敏传感器
同样右键Hardware,新建.c和.h文件
添加头文件,添加框架
LightSensor.c文件中添加函数 void LigtSensor_Init(void)
复制按键中的初始化程序,光敏传感器连接13号口,这里改为GPIO_Pin_13
#include "stm32f10x.h" // Device header
void LigtSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}uint8_t LightSensor_Get(void) //返回端口值
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);}
声明函数
最后在主函数中测试,上面添加 #include "LightSensor.h"
编译下载,遮住,响,去掉,不响
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"uint8_t KeyNum;
int main(void)
{
Buzzer_Init();
LigtSensor_Init(); //初始化光敏传感器
while(1)
{
if (LightSensor_Get() == 1) //光线暗的情况
{
Buzzer_ON();
}
else
{
Buzzer_OFF();
}
}
}
终于写完了,虽然写的不是特别完善,后面学明白了会慢慢更改,加入更详细的原理解释和效果图,太累了,先这样吧,感谢美女帅哥的阅读,如果有哪里不合适还请多多指教
uint8报错问题,加一句 #include "stdint.h"
作者:鲨鱼爱吃菜