STM32--固件庫-矩陣鍵盤


STM32 矩陣鍵盤

簡介

1.硬件部分
2.軟件部分

硬件部分

矩陣鍵盤的工作方式

對鍵盤的響應取決於鍵盤的工作方式,鍵盤的工作方式應根據實際應用系統中的CPU的工作狀況而定,其選取的原則是既要保證CPU能及時響應按鍵操作,又不要過多占用CPU的工作時間。通常鍵盤的工作方式有三種,編程掃描、定時掃描和中斷掃描。

(1)編程掃描方式

編程掃描方式是利用CPU完成其它工作的空余時間,調用鍵盤掃描子程序來響應鍵盤輸入的要求。在執行鍵功能程序時,CPU不再響應鍵輸入要求,直到CPU重新掃描鍵盤為止。

(2)定時掃描方式

定時掃描方式就是每隔一段時間對鍵盤掃描一次,它利用單片機內部的定時器產生一定時間(例如10ms)的定時,當定時時間到就產生定時器溢出中斷。CPU響應中斷后對鍵盤進行掃描,並在有按鍵按下時識別出該鍵,再執行該鍵的功能程序。

(3)中斷掃描方式

上述兩種鍵盤掃描方式,無論是否按鍵,CPU都要定時掃描鍵盤,而單片機應用系統工作時,並非經常需要鍵盤輸入,因此,CPU經常處於空掃描狀態。

為提高CPU工作效率,可采用中斷掃描工作方式。其工作過程如下:當無按鍵按下時,CPU處理自己的工作,當有按鍵按下時,產生中斷請求,CPU轉去執行鍵盤掃描子程序,並識別鍵號。

4x4矩陣鍵盤模塊原理圖
在這里插入圖片描述

4x4矩陣鍵盤模塊實物圖
在這里插入圖片描述

軟件部分

key.c

/********************************************************************* * 文件名 :key4x4.c * 描述 :按鍵應用函數庫 * 硬件連接:------------------------- * | PB8 - H4 | * | PB9 - H3 | * | PB10 - H2 | * | PB11 - H1 | * | PB12 - L4 | * | PB13 - L3 | * | PB14 - L2 | * | PB15 - L1 | * ------------------------- * 庫版本 :ST3.5.0 *********************************************************************/

#include "key4x4.h" 
#include "delay.h" 

 /* * 函數名:Key_GPIO_Config * 描述 :配置按鍵用到的I/O口 GPIO端口可以自行定義 * 輸入 :無 * 輸出 :無 */
void Key4x4_GPIO_Config(void)
{
  	GPIO_InitTypeDef GPIO_InitStructure;
  	
  	/*開啟按鍵端口的時鍾*/
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //GPIO端口引腳可以自行定義
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
   //配置引腳速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    //配置引腳模式 GPIO_Mode_IPU 上拉輸入
	GPIO_Init(GPIOB, &GPIO_InitStructure);

  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;	
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(GPIOB, &GPIO_InitStructure);
}
 /* * 函數名:u8 Key_Scan * 描述 :按鍵掃描函數 * 輸入 :無 * 輸出 :無 */
u8 Key_Scan(void)
{
	u16 temp;
	u8 ucBackValue=0;
	//====掃描第一列==========
	GPIO_Write(GPIOB,0xfe00); 
	temp=GPIO_ReadInputData(GPIOB); //讀出整個口得到的值
	temp=temp&0xf000;    //屏蔽低4位
	if (temp!=0xf000)      //假如高4位不全是1
	{ 
		delay_ms(20);      // 延時消抖再讀
		temp=GPIO_ReadInputData(GPIOB); 
		temp=temp&0xf000;
		if (temp!=0xf000)     //消抖后如果再次高4位確定不是全1
		{ 
			temp=GPIO_ReadInputData(GPIOB)&0xff00; //讀出此次按鍵的值
			switch(temp)
			{ 
				case 0xee00:
				ucBackValue = 1;break;
				case 0xde00:
				ucBackValue = 5;break;
				case 0xbe00:
				ucBackValue = 9;break;
				case 0x7e00:
				ucBackValue = 13;break;
				default:break;
			}
			while(temp!=0xf000)   //等待按鍵放開,初始必然被執行
			{ 
				temp=GPIO_ReadInputData(GPIOB); 
				temp=temp&0xf000;
			}

		}
	}

	//====第二列送0==========
	GPIO_Write(GPIOB,0xfd00); 
	temp=GPIO_ReadInputData(GPIOB); //讀出整個口得到的值
	temp=temp&0xf000;    //屏蔽低4位
	if (temp!=0xf000)      //假如高4位不全是1
	{ 
		delay_ms(20);      // 延時消抖再讀
		temp=GPIO_ReadInputData(GPIOB); 
		temp=temp&0xf000;
		if (temp!=0xf000)     //消抖后如果再次高4位確定不是全1
		{ 
			temp=GPIO_ReadInputData(GPIOB)&0xff00; //讀出此次按鍵的值
			switch(temp)
			{ 
				case 0xed00:
					ucBackValue = 2; break;
				case 0xdd00:
					ucBackValue = 6; break;
				case 0xbd00:
					ucBackValue = 10; break;
				case 0x7d00:
					ucBackValue = 14; break;
				default:break;
		}
			while(temp!=0xf000)   //等待按鍵放開
			{ 
				temp=GPIO_ReadInputData(GPIOB); 
				temp=temp&0xf000;
			}
		}
	}
	//====第3列送0==========
	GPIO_Write(GPIOB,0xfb00); 
	temp=GPIO_ReadInputData(GPIOB); //讀出整個口得到的值
	temp=temp&0xf000;    //屏蔽低4位
	if (temp!=0xf000)      //假如高4位不全是1
	{ 
		delay_ms(20);      // 延時消抖再讀
		temp=GPIO_ReadInputData(GPIOB); 
		temp=temp&0xf000;
		if (temp!=0xf000)     //消抖后如果再次高4位確定不是全1
		{ 
			temp=GPIO_ReadInputData(GPIOB)&0xff00; //讀出此次按鍵的值
			switch(temp)
			{ 
				case 0xeb00:
				ucBackValue = 3; break;
				case 0xdb00:
				ucBackValue = 7; break;
				case 0xbb00:
				ucBackValue = 11; break;
				case 0x7b00:
				ucBackValue = 15; break;
				default:break;
		}
		while(temp!=0xf000)   //等待按鍵放開
		{ 
			temp=GPIO_ReadInputData(GPIOB); 
			temp=temp&0xf000;
		}
		}
	}
	//====第4列送0==========
	GPIO_Write(GPIOB,0xf700); 
	temp=GPIO_ReadInputData(GPIOB); //讀出整個口得到的值
	temp=temp&0xf000;    //屏蔽低4位
	if (temp!=0xf000)      //假如高4位不全是1
	{ 
		delay_ms(20);       // 延時消抖再讀
		temp=GPIO_ReadInputData(GPIOB); 
		temp=temp&0xf000;
		if (temp!=0xf000)     //消抖后如果再次高4位確定不是全1
		{ 
			temp=GPIO_ReadInputData(GPIOB)&0xff00; 
			switch(temp)
			{ 
				case 0xe700:
				ucBackValue = 4; break;
				case 0xd700:
				ucBackValue = 8; break;
				case 0xb700:
				ucBackValue = 12; break;
				case 0x7700:
				ucBackValue = 16; break;
				default:break;
			}
			while(temp!=0xf000)   //等待按鍵放開
			{ 
				temp=GPIO_ReadInputData(GPIOB); 
				temp=temp&0xf000;
			}
		}
	}
	return ucBackValue;
}

key.h

#ifndef __KEY_H
#define __KEY_H

#include "stm32f10x.h"


void Key4x4_GPIO_Config(void);
u8 Key_Scan(void);

#endif /* __KEY_H */

案例(51單片機 矩陣鍵盤 數碼管顯示0~F)

#include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器

typedef unsigned int u16;	  //對數據類型進行聲明定義
typedef unsigned char u8;

#define GPIO_DIG P0
#define GPIO_KEY P1 //可以改變,引腳可以自定義
unsigned char  KeyValue;	//用來存放讀取到的鍵值
unsigned char code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//顯示0~F的值//共陰數碼管

/******************************************************************************* * 函 數 名 : delay * 函數功能 : 延時函數,i=1時,大約延時10us *******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/******************************************************************************* * 函 數 名 : KeyDown * 函數功能 : 檢測有按鍵按下並讀取鍵值 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/
void KeyDown(void)
{
	unsigned char a=0;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
	{
		delay(1000);//延時10ms進行消抖
		if(GPIO_KEY!=0x0f)//再次檢測鍵盤是否按下
		{	
			//測試列
			GPIO_KEY=0X0F;
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=0;break;
				case(0X0b):	KeyValue=1;break;
				case(0X0d):     KeyValue=2;break;
				case(0X0e):	KeyValue=3;break;
			}
			//測試行
			GPIO_KEY=0XF0;
			switch(GPIO_KEY)
			{
				case(0X70):	KeyValue=KeyValue;break;
				case(0Xb0):	KeyValue=KeyValue+4;break;
				case(0Xd0):     KeyValue=KeyValue+8;break;
				case(0Xe0):	KeyValue=KeyValue+12;break;
			}
			
		}
	}
             while((a<50)&&(GPIO_KEY!=0xf0))	 //檢測按鍵松手檢測
	{
		delay(100);
		a++;
	}
}
void main()
{
	 while(1)
	 {
		        KeyDown();//按鍵判斷函數
			GPIO_DIG=~smgduan[KeyValue];
	 }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM