基于STM32任意键薄膜键盘代码


基于STM32任意键薄膜键盘代码


对于大多数人来说都写过51的按键扫描,但是对于32来说端口配置比较麻烦,对于按键扫描 *要配置相应的IO口模式,每种模式的特性是不一样的,可以通过按键的读写操作,对于各种模式有个深入的了解。
对薄膜键盘来说通过八个IO口进行扫描确认是哪个按键按下,然而一般的方式是采用行和列高低电平的反差来扫描判断的,那么我们对32 的IO口要进行写和读操作,学过32的人都知道,IO口的每一种模式都可读可写,但是对于外电路来说,不是每种模式都可以用来按键扫描。

GPIO_Mode_AIN = 0x0,
模拟输入,应用ADC 模拟输入
GPIO_Mode_IN_FLOATING = 0x04,
浮空输入,在悬空状态电平未知,一般在高低电平判决临界处,
GPIO_Mode_IPD = 0x28,
IO口内部下拉电阻输入
GPIO_Mode_IPU = 0x48,
IO口内部下拉电阻输入
GPIO_Mode_Out_OD = 0x14,
开漏输出,IO输出0接地,输出1悬空
GPIO_Mode_Out_PP = 0x10,
推挽输出 IO输出0接地,输出1接vcc
GPIO_Mode_AF_OD = 0x1C,
复用开漏输出,对于这个实在一些内部外设使用时要使用的,作为小白的我使用还是不太了解具体使用情况,只是知道大概在使用一些外设时需要使用。
GPIO_Mode_AF_PP = 0x18
复用推挽

其实对于上面的这么多模式,对于我们的中心按键扫描,可以配置很懂种模式实现,关键看是否稳定。我选用的扫描方式是以 行/列 输出为推挽输出,而 列/行 以
下拉输入为输入。
一、行/列 四个引脚 输出为推挽输出,输出比较稳定,高低电平分明,不易受外电路的干扰,
二、列/行 以下拉输入为输入,IO口电平状态默认是下拉的 ,及低电平,当外界给IO为高电平时,IO口就会被拉高,读取IO状态为高电平,很好的起到了读取外部IO的作用

之所以使用这种类型的IO配置,是因为它比较稳定,我也是小白,不太会写文字,第一次试着写的,下面粘贴代码吧

主函数

// An highlighted block

#include "stm32f10x.h"
#include "STK_H_Usart.h"
#include "bsp_led.h"
#include "stdio.h"
#include "STK_H_BMkey.h"
#include "bsp_SysTick.h"


int main(void)
{	
	uint8_t mmp=0;
	//串口初始化
	usart_config();
	//LED 初始化
	LED_GPIO_Config();	
	//按键扫描初始化
  key_GPIO_Config(1);	
	//系统定时器初始化
	SysTick_Init();	
  printf("今天是个好天气"); 

  while(1)
	{	
    mmp=key_seek();
		SysTick_Delay_Ms(500);
		printf("my world is %d\n",mmp);

	}	
}


扫描函数 .H文件

重定义了一些IO口名,便于更改引脚
这个文件就只是完成了这个时期,有点呆滞,

#ifndef  __STK_H_BMKEY_H__
#define  __STK_H_BMKEY_H__

#include "stm32f10x.h"


//第一组  行
//PC  6
#define KEY1_1_GPIO_PORT    	GPIOA		              
#define KEY1_1_GPIO_CLK 	    RCC_APB2Periph_GPIOA	 
#define KEY1_1_GPIO_PIN		GPIO_Pin_4

#define   X1_0    GPIO_ResetBits(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN);
#define   X1_1    GPIO_SetBits(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN);


//PC  8
#define KEY1_2_GPIO_PORT    	GPIOA		            
#define KEY1_2_GPIO_CLK 	    RCC_APB2Periph_GPIOA	 
#define KEY1_2_GPIO_PIN		GPIO_Pin_5			 

#define   X2_0    GPIO_ResetBits(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN);
#define   X2_1    GPIO_SetBits(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN);


//PA  8
#define KEY1_3_GPIO_PORT    	GPIOA			              
#define KEY1_3_GPIO_CLK 	    RCC_APB2Periph_GPIOA
#define KEY1_3_GPIO_PIN		GPIO_Pin_6	

#define   X3_0    GPIO_ResetBits(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN);
#define   X3_1    GPIO_SetBits(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN);


//PA  10
#define KEY1_4_GPIO_PORT    	GPIOA			              
#define KEY1_4_GPIO_CLK 	    RCC_APB2Periph_GPIOA		 
#define KEY1_4_GPIO_PIN		GPIO_Pin_7

#define   X4_0    GPIO_ResetBits(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN);
#define   X4_1    GPIO_SetBits(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN);



#define   X_0   X1_0  \
                X2_0  \
				X3_0  \
				X4_0

#define   X_1   X1_1  \
                X2_1  \
				X3_1  \
				X4_1

//第二组  列
//
//PA  12
#define KEY2_1_GPIO_PORT    	GPIOA	              
#define KEY2_1_GPIO_CLK 	    RCC_APB2Periph_GPIOA 
#define KEY2_1_GPIO_PIN		GPIO_Pin_2			 

#define   Y1_0    GPIO_ResetBits(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN);
#define   Y1_1    GPIO_SetBits(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN);


// PA  14
#define KEY2_2_GPIO_PORT    	GPIOA	            
#define KEY2_2_GPIO_CLK 	    RCC_APB2Periph_GPIOA	 
#define KEY2_2_GPIO_PIN		    GPIO_Pin_3		

#define   Y2_0    GPIO_ResetBits(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN);
#define   Y2_1    GPIO_SetBits(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN);

//PC  10
#define KEY2_3_GPIO_PORT    	GPIOA			              
#define KEY2_3_GPIO_CLK 	    RCC_APB2Periph_GPIOA		 
#define KEY2_3_GPIO_PIN		GPIO_Pin_11

#define   Y3_0    GPIO_ResetBits(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN);
#define   Y3_1    GPIO_SetBits(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN);

//PC  12
#define KEY2_4_GPIO_PORT    	GPIOA              
#define KEY2_4_GPIO_CLK 	    RCC_APB2Periph_GPIOA		 
#define KEY2_4_GPIO_PIN		     GPIO_Pin_12			        

#define   Y4_0    GPIO_ResetBits(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN);
#define   Y4_1    GPIO_SetBits(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN);




#define   Y_0   Y1_0 \
                Y2_0;\
				Y3_0\
				Y4_0

#define   Y_1   Y1_1 \
                Y2_1;\
				Y3_1\
				Y4_1

/*初始化函数,*/
void key_GPIO_Config(int a);
uint8_t  key_seek(void);


#endif




扫描函数 .C文件

实现IO初始化,还有读取函数的书写,扫描函数的书写

#include "STK_H_BMkey.h"
#include "stdio.h"
#include "bsp_SysTick.h"

//1  k2为浮空输入 (读取Y)   0  k1 为浮空输入(读取X)
/**********************************************************
*  函数名:key_GPIO_Config(int a)
*   参数 :a   
* 参数取值:0(第一组配置为推挽,第二组下拉)  1(和前面相反)
*
**********************************************************/
void key_GPIO_Config(int a)
{		
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure;

		/*开启LED相关的GPIO外设时钟*/
	RCC_APB2PeriphClockCmd( KEY1_1_GPIO_CLK| KEY1_2_GPIO_CLK | KEY1_3_GPIO_CLK| KEY1_4_GPIO_CLK |KEY2_1_GPIO_CLK| KEY2_2_GPIO_CLK | KEY2_3_GPIO_CLK| KEY2_4_GPIO_CLK, ENABLE);

	
//KEY1  按键配置
		GPIO_InitStructure.GPIO_Pin = KEY1_1_GPIO_PIN;
if(a)	
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
else
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		GPIO_Init(KEY1_1_GPIO_PORT, &GPIO_InitStructure);	

		GPIO_InitStructure.GPIO_Pin = KEY1_2_GPIO_PIN;
		GPIO_Init(KEY1_2_GPIO_PORT, &GPIO_InitStructure);
	
			GPIO_InitStructure.GPIO_Pin = KEY1_3_GPIO_PIN;
		GPIO_Init(KEY1_3_GPIO_PORT, &GPIO_InitStructure);
	
			GPIO_InitStructure.GPIO_Pin = KEY1_4_GPIO_PIN;
		GPIO_Init(KEY1_4_GPIO_PORT, &GPIO_InitStructure);
	

//KEY2  按键配置
if(a)	
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
else
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

		GPIO_InitStructure.GPIO_Pin = KEY2_1_GPIO_PIN;	
		GPIO_Init(KEY2_1_GPIO_PORT, &GPIO_InitStructure);	

		GPIO_InitStructure.GPIO_Pin = KEY2_2_GPIO_PIN;
		GPIO_Init(KEY2_2_GPIO_PORT, &GPIO_InitStructure);
	
		GPIO_InitStructure.GPIO_Pin = KEY2_3_GPIO_PIN;
		GPIO_Init(KEY2_3_GPIO_PORT, &GPIO_InitStructure);
	
	  GPIO_InitStructure.GPIO_Pin = KEY2_4_GPIO_PIN;
		GPIO_Init(KEY2_4_GPIO_PORT, &GPIO_InitStructure);

//    Y_0;//给Y组的IO口置位0
//		X_0;//给X组的IO口置位0


		
}

/***************************************************************************
**函数名 :READ_Date
**参数  :a
**参数取值:0(读取X(行)的IO口的数据)   1(读取Y(列)的IO口的数据)  
**返回值 :八位   第四位表示读取IO电平状态,通过移位相或实现
****************************************************************************/

uint8_t READ_Date(int a)
{
    if(a) {
			return   0x0f&((GPIO_ReadInputDataBit(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN))<<3 | GPIO_ReadInputDataBit(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN)<<2   \
				      | GPIO_ReadInputDataBit(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN)<<1| GPIO_ReadInputDataBit(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN));     }
	
     else  {
			 return  0x0f&((GPIO_ReadInputDataBit(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN))<<3 | GPIO_ReadInputDataBit(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN)<<2             \
               | GPIO_ReadInputDataBit(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN)<<1| GPIO_ReadInputDataBit(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN)); }
										  
}
//扫描函数
uint8_t  key_seek(void)
{	
   int mm,key_date=0;
	  key_GPIO_Config(0);
  	  X_0; Y_1;
	 SysTick_Delay_Ms(2);
	 mm=READ_Date(0);  //变量为0 ,表示返回的是key1的数据及X的数据
	 if(mm!=0x00){
		 //printf("进入了第一个判断\n");
	     SysTick_Delay_Ms(10);
		   mm=READ_Date(0);
		   if(mm!=0x00){
				  switch(mm)
					{
						case(0x08): key_date=0;
							          break;
						case(0x04): key_date=4;
							          break;
						case(0x02): key_date=8;
							          break;
						case(0x01): key_date=12;
							          break;
					}
					key_GPIO_Config(1);
				   	X_1;Y_0;
			       SysTick_Delay_Ms(2);
	               mm=READ_Date(1);
				 	switch(mm)
					{
						case(0x08): key_date=key_date+1;
							          break;
						case(0x04): key_date=key_date+2;
							          break;
						case(0x02): key_date=key_date+3;
							          break;
						case(0x01): key_date=key_date+4;
							          break;
					}
				    printf("等待按键谈起");
					printf("(uint8_t)key_date  is %d\n",(uint8_t)key_date);
					printf("READ_Date(1) is %d\n",READ_Date(1));
				   while(0x00!=READ_Date(1));    //等待按键弹起				
				  return  (uint8_t)key_date;	  
			 }
 }
return 0;

}

自己用过,是可以使用的,有什么错误或不足的地方还请指出,第一次写,也是刚入大学的小菜鸟,刚开始学习,希望各位大佬指导,也希望能给予需要人的帮助


版权声明:本文为lovegrail原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。