STM32学习笔记:按键实验

本文档详细介绍了STM32的按键实验,包括使用的函数、代码编写过程和主函数实现。通过初始化GPIO,设置上拉和下拉输入模式来检测按键状态。代码实现了支持连续按键和不支持连续按键两种模式,根据按键状态控制LED和蜂鸣器。在移植代码时注意了uint8_t类型定义问题。
摘要由CSDN通过智能技术生成

STM32学习笔记:按键实验

一.所使用的函数

1.时钟使能函数
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
2.引脚初始化函数
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
3.对IO口置1
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
4.对IO口置0
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
5.读取引脚输入数据的函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

二.代码编写过程整理

1.编写button.h文件

# ifndef __Button_H
# define __Button_H
void button_Init(void);
uint8_t Botton_scan(uint8_t); //在原始的文档中写的是u8,但是在新的stm32f10x.h头文件中未定义,所以无法直接使用
#endif

2.编写button.c文件

void button_Init(void)
{
	GPIO_InitTypeDef GPIO_Initstructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //使能GPIOE的时钟
	
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPU; //设置模式为上拉输入
	GPIO_Initstructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_Initstructure); //初始化PE3
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPU; //设置模式为上拉输入
	GPIO_Initstructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_Initstructure); //初始化PE4
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA的时钟
	
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPD; //设置模式为下拉输入
	GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure); //初始化PA0
}

正点原子的精英板一共有三个按键:WK_UP、KEY1、KEY2 ,其中KEY1和KEY2分别对应PE3和PE4,WK_UP对应的是PA0.在无按键按下时PE3和PE4对应引脚的数据是1,按下按键时PE3和PE4对应引脚输入的数据是0,为上拉输入,所以在模式选择的时候我们选择了上拉输入GPIO_Mode_IPU;在无按键按下时WK_UP对应引脚的数据是0,按下按键时WK_UP对应引脚输入的数据是1,为上拉输入,所以在模式选择的时候我们选择了下拉输入GPIO_Mode_IPD.

总结 上拉输入和下拉输入:当一个按键按下的时候,对应的引脚输入数据是0或1是不确定的,还要看外部电路的组成是上拉还是下拉,当外部电路时上拉的时候,即外部接正的时候,读入的数据是1;当外部电路是下拉的时候,读入的数据是0.所以上拉输入就是无按键按下时是1,有按键按下时是0;而下拉输入就是无按键按下时是0,有按键按下时是1.

uint8_t Botton_scan(uint8_t mode)
{
	static uint8_t button_up = 1;
	if(mode == 1)
		button_up = 1; //模式1支持连续按键,无论之前button_up的值为多少,这里都将其置1,不管button_up之前的数据
	if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
	{
	  button_up =0; //不支持连续按键模式时,按下按钮时置0,为了保存按键状态
		delay_ms(10); //软件消抖
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
		  return 1;
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
		  return 2;
	  if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
		  return 3;
  }
	else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 1|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 1|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0)
	{
		button_up = 1; //无按键按下
	}
	return 0;
}

这个是正点原子所提供的按键代码,为了让这段代码更方便分析,我把它所有的宏定义都替换掉了。这个按键代码是集“支持连续按键”和“不支持连续按键”功能于一身,连续按键:当mode等于1时它支持连续按键,原因是那一句if让button_up = 1,这样子它就可以不管static保存上一次调用代码所得的值,也就是不管按键之前的状态,只要按下就返回其对应的值,从而实现连续按键。不支持连续按键:不支持连续按键的关键是将button_up设置为一个static值,它可以保存上一次调用该函数,最后button_up的值。不支持连续按键,就是上一次如果是非按下状态,那么在这次检测到的按下状态就可以返回对应按钮所对应的值;但是如果上次是按下状态,在这次检测到的状态还是按下状态,它就不会返回对应的值而是返回0。下面我把该代码拆成两部分,这样可以更清楚地了解二者不同之处:

uint8_t Botton_scan(uint8_t mode) //连续按键
{
	button_up = 1; 
	if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
	{
		delay_ms(10); //软件消抖
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
		  return 1;
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
		  return 2;
	  if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
		  return 3;
  }
}
uint8_t Botton_scan(uint8_t mode) //不支持连续按键
{
	static uint8_t button_up = 1;
	if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
	{
	  button_up =0; 
		delay_ms(10); //软件消抖
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
		  return 1;
	  if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
		  return 2;
	  if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
		  return 3;
  }
	else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 1|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 1|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0)
	{
		button_up = 1; //无按键按下
	}
	return 0;
}

3.编写main.c函数

# include "Button.h"
# include "Led.h"
# include "Beep.h"
# include "stm32f10x.h"
# include "delay.h"

int main(void)
{
	button_Init();
	delay_init();
	led_Init();
	beep_Init();
	while(1)
	{
		uint8_t button = 0;
		button = Botton_scan(0); //选择不支持连续按键模式
		if (button != 0)
		{
			switch(button)
			{
				case 1 :
					GPIO_ResetBits(GPIOE,GPIO_Pin_5);
				  break;
				case 2 :
					GPIO_ResetBits(GPIOB,GPIO_Pin_5);
					break;
				case 3 :
					GPIO_ResetBits(GPIOB,GPIO_Pin_5);
				    GPIO_ResetBits(GPIOE,GPIO_Pin_5);
				    GPIO_SetBits(GPIOB,GPIO_Pin_8);
				    break;
			}
		}
		else delay_ms(10);
	}
}

在主函数中我为了让按键效果可以体现出来,让KEY1按下LED0亮,让KEY2按下LED1亮,按下KEY_UP时,LED0和LED1同时亮,并且有蜂鸣器响,点亮led和让蜂鸣器响的代码前两天分享过了,大家可以自己结合一下。

三.发现的问题

在自己写代码的时候发现了那些视频可能是几年前的视频了,在我的stm32f10x.h头文件中它没有了对uint8_t的宏定义,所以我在移植代码的时候使用u8会报错。

总的来说,st定义无符号8位整形数据有很多种表示方法:
1 unsigned int 8——标准写法;
2 uint8_t ;
3 u8; ——有问题

这个错误我找到的原因是这个,如果有其他的原因希望大家可以帮我指出。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ninehuang333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值