分享一个STM32F103系列的按键控制LED灯的库函数程序
这个程序我是在正点的mini板上做的实验。如果没有开发板也可以在电脑仿真软件Proteus 8 Professional上实现。
这份代码能够实现按键控制LED的功能。在mini板上一共有三个用户按键,分别是:KEY0、KEY1、KEY_UP。其中KEY0和KEY1是由低电平触发,也就是其中一个引脚接地,而KEY_UP则是由高电平触发,接的是+3.3V。关于按键的原理就不过多介绍,因为也比较简单。
1、程序源码的主要用户模块
1.main.c
2.LED.h、LED.c
3.KEY.h、KEY.c
主要用到的文件
2、 具体实现源码
1.main.c
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
u16 i;
int main(void)
{
//两个功能的初始化
LED_Init();
Key_Init();
while(1)
{
i=Scanf_Key(); //Scanf_Key()具有返回值,能够返回按键的值,0、1、2,分别对应三个按键
switch(i)
{
case 0:GPIO_ResetBits(GPIOA,GPIO_Pin_8);break;
case 1:GPIO_ResetBits(GPIOD,GPIO_Pin_2);break;
case 2:GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);break;
default:GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);break;
}
}
}
2.key.h
#include "stm32f10x.h"
#include "led.h"
//将相关的GPIO宏定义,是为了能够在不同板子间移植方便,不用大规模修改程序引脚
#define GPIO_KEY0 GPIOC
#define GPIO_KEY1 GPIOA
#define GPIO_KEY_UP GPIOA
#define GPIO_Pin_KEY0 GPIO_Pin_5
#define GPIO_Pin_KEY1 GPIO_Pin_15
#define GPIO_Pin_KEY_UP GPIO_Pin_0
#define RCC_APB2Periph_KEY0 RCC_APB2Periph_GPIOC
#define RCC_APB2Periph_KEY1_UP RCC_APB2Periph_GPIOA
//GPIO_ReadInputDataBit的功能:读取指定端口管脚的输入电平
#define KEY0 GPIO_ReadInputDataBit(GPIO_KEY0, GPIO_Pin_KEY0)
#define KEY1 GPIO_ReadInputDataBit(GPIO_KEY1, GPIO_Pin_KEY1)
#define KEY_UP GPIO_ReadInputDataBit(GPIO_KEY_UP, GPIO_Pin_KEY_UP)
void Key_Init(void);
u8 Scanf_Key(void);
#endif
3.key.c
#include "key.h"
#include "stm32f10x.h"
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_KEY0 | RCC_APB2Periph_KEY1_UP, ENABLE); //开启引脚时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_KEY0 | GPIO_Pin_KEY1; //指定引脚按键0和按键1
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIO_KEY0,&GPIO_InitStruct); //初始化
GPIO_Init(GPIO_KEY1,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_KEY_UP; //此按键一端接正极
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_Init(GPIO_KEY_UP,&GPIO_InitStruct); //初始化
}
u8 Scanf_Key(void) //定义一个函数
{
static unsigned char KeyNum=20; //定义一个静态变量
if(!KEY0 || !KEY1 || KEY_UP) //判断是哪一个按键按下,KEY_UP是一个比较特殊的按键,因为它的一端引脚接高电平
{
delay(50); //延时是为了消抖
if(!KEY0 || !KEY1 || KEY_UP) //再次判断
{
if(!KEY0) return KeyNum=0; //判断并赋值
if(!KEY1) return KeyNum=1;
if(KEY_UP) return KeyNum=2;
}while(!KEY0 || !KEY1 || KEY_UP); //等待查询
}
return KeyNum; //最后返回一个结果
}
4.led.h
#ifndef _LED_H
#define _LED_H
#include "stm32f10x.h"
void delay(uint32_t ms);
void LED_Init(void);
#endif
5.led.c
#include "stm32f10x.h"
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义CPIO初始化类型定义
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD,ENABLE); //使能GPIOA的时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8; //填入LED0连接的引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //设置该引脚的模式为推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的输出速度
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; //填入LED1连接的引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //设置该引脚的模式为推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的输出速度
GPIO_Init(GPIOD, &GPIO_InitStruct);
}
void delay(uint32_t ms)
{
uint32_t i;
for(;ms!=0;ms--)
{
i=14398;
while(i--);
}
}
关于代码部分情况
与点灯相比,按键是少了一个GPIO_InitStruct.GPIO_Speed,也就是不需要配置输出速度,因为按键是充当输入设备。既然是输入,那就需要配置STM32芯片的引脚来读取它送到GPIO引脚的逻辑电平,通过C语言的判断语句指定引脚的高低电平,就能实现相应简单的功能。按键的初始化也是GPIO的初始化,所以在配置流程上和点灯的区别不大。
名词介绍
GPIO_Mode_IPU
上拉输入。也就是初始化时,将该引脚置高电平,当按键按下时,该引脚就会变成低电平,从而实现按键的控制功能
GPIO_Mode_IPD
下拉输入。也就是初始化时,将该引脚置低电平,当按键按下时,该引脚就会变成高电平,从而实现按键的控制功能,此配置和上面恰恰相反,原因是KEY0、KEY1一脚接地,而KEY_UP接+3.3V电源。
GPIO_ReadInputDataBit(GPIOx, GPIO_Pin)
读取指定端口管脚的输入,通过该函数能够读取指定GPIO引脚的逻辑电平。