个人学习笔记:按键实验

   日期:2021-01-18     浏览:84    评论:0    
核心提示:个人学习笔记:按键实验一.所使用的函数1.时钟使能函数RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)2.引脚初始化函数GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)3.对IO口置1GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)4.对IO口置0GPIO_

个人学习笔记:按键实验

一.所使用的函数

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; ——有问题

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

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服