一、原理分析
1、上面图中左侧是STM32里电路每个端口均可以配置的电路部分,右边部分是外接设备电路图
2、配置的输入模式:上拉输入模式:VDD开关闭合,VSS开关断开
浮空输入模式:VDD开关断开,VSS开关断开
下拉输入模式:VDD开关断开,VSS开关闭合
3、 在 按键控制LED灯亮灭 中,必须要求配置为上拉输入模式。在按键开k1断开,及不操作的时候,上拉输入模式有①VDD上拉电阻将引脚电平上拉,保证了不会出现浮动的现象。配置好了上拉输入模式,②VSS开关就已经断开了,下拉 通过K1按键开关的通断来实现的。所以在这种方式下,按下K1为低电平,松开K1位高电平
4、如果外部元器件如下图加上一个电阻R1,就可以将端口配置为浮空模式,R1充当了拉上模式中的VDD的作用(在这里我们用上拉输入模式)
二、代码的实现
1、电路图的连接
2、程序的思路
初始化程序,要用到的库函数
RCC_APB2PeriphClockCmd :使能或者失能APB2外设时钟。
GPIO_SetBits :设置指定的数据端口位。置高1。
GPIO_ResetBits :清除指定的数据端口位。置低0。
GPIO_ReadOutputDataBit :读取指定端口管脚的输出。
GPIO_ReadInputDataBit :读取指定端口管脚的输入
3、代码的实现(代码模块化的展示)
LED.C
#include "stm32f10x.h" // Device header /** * 函 数:LED初始化 * 参 数:无 * 返 回 值:无 */ void LED_Init(void) { /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟 /*GPIO初始化*/ 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); //将PA1和PA2引脚初始化为推挽输出 /*设置GPIO初始化后的默认电平*/ GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //设置PA1和PA2引脚为高电平 } /** * 函 数:LED1开启 * 参 数:无 * 返 回 值:无 */ void LED1_ON(void) { GPIO_ResetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为低电平 } /** * 函 数:LED1关闭 * 参 数:无 * 返 回 值:无 */ void LED1_OFF(void) { GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为高电平 } /** * 函 数:LED1状态翻转 * 参 数:无 * 返 回 值:无 */ void LED1_Turn(void) { if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平 { GPIO_SetBits(GPIOA, GPIO_Pin_1); //则设置PA1引脚为高电平 } else //否则,即当前引脚输出高电平 { GPIO_ResetBits(GPIOA, GPIO_Pin_1); //则设置PA1引脚为低电平 } } /** * 函 数:LED2开启 * 参 数:无 * 返 回 值:无 */ void LED2_ON(void) { GPIO_ResetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为低电平 } /** * 函 数:LED2关闭 * 参 数:无 * 返 回 值:无 */ void LED2_OFF(void) { GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为高电平 } /** * 函 数:LED2状态翻转 * 参 数:无 * 返 回 值:无 */ void LED2_Turn(void) { if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平 { GPIO_SetBits(GPIOA, GPIO_Pin_2); //则设置PA2引脚为高电平 } else //否则,即当前引脚输出高电平 { GPIO_ResetBits(GPIOA, GPIO_Pin_2); //则设置PA2引脚为低电平 } }
LED.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void);
#endif
Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
/**
* 函 数:按键初始化
* 参 数:无
* 返 回 值:无
*/
void Key_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //将PB1和PB11引脚初始化为上拉输入
}
/**
* 函 数:按键获取键码
* 参 数:无
* 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
* 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
*/
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0; //定义变量,默认键码值为0
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) //读PB1输入寄存器的状态,如果为0,则代表按键1按下
{
Delay_ms(20); //延时消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); //等待按键松手
Delay_ms(20); //延时消抖
KeyNum = 1; //置键码为1
}
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) //读PB11输入寄存器的状态,如果为0,则代表按键2按下
{
Delay_ms(20); //延时消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); //等待按键松手
Delay_ms(20); //延时消抖
KeyNum = 2; //置键码为2
}
return KeyNum; //返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}
Key.h
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
在key.c文件中介绍一下几个函数
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);这个函数是用来读取输入寄存器(图)某一个端口的输入值的
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); 这个函数是用来读取整个输入寄存器的,返回值是一个16位的数据,每一位代表一个端口值
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 这个函数是用来读取输出寄存器(图)某一个端口的输出值的,用来看一下自己输出了什么
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); 这个函数是用来读取整个输出寄存器的,返回值是一个16位的数据,每一位代表一个端口值。
按下按键一端接B1端口,按键按下为低电平,if 判断 当B1端口为低电平时(按下按键),消抖之后返回值,返回1 LED1 亮起,返回2 LED2亮起。
主函数
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum; //定义用于接收按键键码的变量
int main(void)
{
/*模块初始化*/
LED_Init(); //LED初始化
Key_Init(); //按键初始化
while (1)
{
KeyNum = Key_GetNum(); //获取按键键码
if (KeyNum == 1) //按键1按下
{
LED1_Turn(); //LED1翻转
}
if (KeyNum == 2) //按键2按下
{
LED2_Turn(); //LED2翻转
}
}
}