矩阵按键程序

在我的盘子上是按下是0,不按是1

矩阵按键扫描原理:
先是把列置0,行是输入上拉,扫描行得到行的键值;再是把行置0,列是输入上拉,扫描列得到列的键值;最后把行列的键值相加得到最后的总的键值。
行扫描返回的键值为:0xe0,0xd0,0xb0,0x70
列扫描返回的键值为:0x0e,0x0d,0x0b,0x07
总的键值为:0xee,0xed,0xeb,0xe7,0xde,0xdd,0xdb,0xd7,0xbe,0xbd,0xbb,0xb7,0x7e,0x7d,0x7b,0x77。正好十六个键值

我用数码管来验证矩阵键盘函数的正确性,依次按下按键数码管显示0-F数字也可以用led来验证

我是用的D0-3控制列,D4-7控制行
A8-11控制数码管位,A0-7控制数码管段

这个工程总共有五个文件分别如下

main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"

 int main(void)
{	
	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	//系统时钟设置PLL作为系统时钟
	delay_init();	   	 	//延时初始化 
	NUM_KEY_Matrix_Init();		  	  	//初始化矩阵键盘与数码管连接的硬件接口
	KEY_Matrix_Scan();                //4*4键盘检验扫描函数

}

key.c

#include "stm32f10x.h"
#include "key.h"
#include "sys.h" 
#include "delay.h"

#define row 0xf0   //行扫描码
#define column 0x0f //列扫描码

//矩阵键盘
unsigned char key_value;
unsigned char num[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
u32 temp1=0,temp2=0;
unsigned char key_value_r;  //行扫描键值
unsigned char key_value_c;  //列扫描键值
								    
//矩阵按键初始化函数
void KEY_Matrix_Init(void) //IO初始化
{ 
 	Matrix_enable;
}
//行扫描配置
void juzhen_Init1(){
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin  = Matrix_COLUMN_GPIO;  //GPIOD低八位端口的d0-d3为推挽输出端,d4-d7为输入上拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  //最高输出速率50MHz
	GPIO_Init(Matrix_PIO, &GPIO_InitStructure);  //IO口初始化
	
	GPIO_InitStructure.GPIO_Pin  = Matrix_ROW_GPIO;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  //最高输出速率50MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //输入上拉
	GPIO_Init(Matrix_PIO, &GPIO_InitStructure);  //IO口初始化
	
	//初始化管脚电平
 GPIO_ResetBits(Matrix_PIO,Matrix_COLUMN_GPIO);   //置0
 GPIO_SetBits(Matrix_PIO, Matrix_ROW_GPIO);  //置1
}
//列扫描配置
void juzhen_Init2(){
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin  = Matrix_COLUMN_GPIO;  //GPIOD低八位端口的d4-d7为推挽输出端,d0-d3为输入上拉
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  //最高输出速率50MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //输入上拉
	GPIO_Init(Matrix_PIO, &GPIO_InitStructure);  //IO口初始化
	
	GPIO_InitStructure.GPIO_Pin  = Matrix_ROW_GPIO;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  //最高输出速率50MHz	
	GPIO_Init(Matrix_PIO, &GPIO_InitStructure);  //IO口初始化
	
	 //初始化管脚电平
 GPIO_SetBits(Matrix_PIO,Matrix_COLUMN_GPIO);   //置1
 GPIO_ResetBits(Matrix_PIO,Matrix_ROW_GPIO);  //置0
	
	
}
//按键处理函数
unsigned char row_scan(void)   //行扫描函数
{
	//行扫描配置
	juzhen_Init1();
	delay_ms(20);
	temp1 = (GPIO_ReadInputData(Matrix_PIO)&row);   
	if (temp1!=0xf0)  
	{
		delay_ms(20);
		key_value_r=temp1;    //读行扫描的键值
		//GPIOD->ODR= 0xff;           //扫描后恢复无按键按下状态
	}
	else
	{
		key_value_r=0;
	}
	return key_value_r;    //返回行扫描键值
}
unsigned char column_scan(void)  //列扫描函数
{
	//列扫描配置
	juzhen_Init2();
	delay_ms(20);
	temp2 = (GPIO_ReadInputData(Matrix_PIO)&column);   
	if (temp2!=0x0f)  
	{
		delay_ms(20);
		key_value_c=temp2;    //读列扫描的键值
		//GPIOD->ODR = 0xff;           //扫描后恢复无按键按下状态
	}
	else
	{
		key_value_c=0;
	}
	
	return key_value_c;    //返回列扫描键值
}

void KEY_Matrix_Scan(void)  //4*4键盘检验扫描函数
{	 
	u16 a,b;          //键值变量
	KEY_Matrix_Init();         	//初始化与按键连接的硬件接口
//	NUM_Init();		  		//初始化与LED连接的硬件接口
	 	 while(1)
	{ 
		delay_ms(20);
		b=column_scan();
		delay_ms(20);
		a=row_scan();
 		key_value=a+b;  //键值生成
		switch(key_value)
		{
			case 0xee:
				GPIOA->ODR=num[0];
				break;
			case 0xed:
				GPIOA->ODR=num[1];
				break;
			case 0xeb:
				GPIOA->ODR=num[2];
				break;
			case 0xe7:
				GPIOA->ODR=num[3];
				break;
			case 0xde:
				GPIOA->ODR=num[4];
				break;
			case 0xdd:
				GPIOA->ODR=num[5];
				break;
			case 0xdb:
				GPIOA->ODR=num[6];
				break;
			case 0xd7:
				GPIOA->ODR=num[7];
				break;
			case 0xbe:
				GPIOA->ODR=num[8];
				break;
			case 0xbd:
				GPIOA->ODR=num[9];
				break;
			case 0xbb:
				GPIOA->ODR=num[10];
				break;
			case 0xb7:
				GPIOA->ODR=num[11];
				break;
			case 0x7e:
				GPIOA->ODR=num[12];
				break;
			case 0x7d:
				GPIOA->ODR=num[13];
				break;
			case 0x7b:
				GPIOA->ODR=num[14];
				break;
			case 0x77:
				GPIOA->ODR=num[15];
				break;
			default: 
				GPIOA->ODR=0xff;
		}
	}
}

key.h

#include "sys.h"

//矩阵键盘引脚配置
#define Matrix_PIO GPIOD  //矩阵按键GPIO端口设置
#define Matrix_enable RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE)  //使能GPIO时钟,给矩阵键盘时钟使能
#define Matrix_COLUMN_GPIO GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3        //GPIO的0-3引脚控制 列
#define Matrix_ROW_GPIO GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7        //GPIO的4-7引脚控制 行
void KEY_Matrix_Init(void);//IO初始化
void KEY_Matrix_Scan(void);//4*4键盘检验扫描函数
//矩阵键盘行列扫描函数
unsigned char row_scan(void);  //行扫描函数返回一个键值key_value_r
unsigned char column_scan(void);   //列扫描函数返回一个键值key_value_c
//key_value为总的键值,key_value=key_value_r+key_value_c

led.c

//数码管用于矩阵键盘输出0-F与硬件接口初始化配置
void NUM_KEY_Matrix_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能GPIOA端口时钟
	GPIO_InitStructure.GPIO_Pin  = GPIOAA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  //最高输出速率50MHz	
	GPIO_Init(GPIOA, &GPIO_InitStructure);  //IO口初始化
	//初始化管脚电平
	GPIO_SetBits(GPIOA, GPIOAL);   //置1
	GPIO_ResetBits(GPIOA,GPIOAH);   //置0

}

led.h

#include "sys.h"
//数码管引脚用于检验矩阵按键
#define GPIOAA GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11   //GPIOA的0-11引脚
#define GPIOAL GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7   //GPIOA的0-7引脚
#define GPIOAH GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11  //GPIOA的8-11引脚
void NUM_KEY_Matrix_Init(void);//数码管用于矩阵键盘输出0-F与硬件接口初始化配置