矩阵按键程序
在我的盘子上是按下是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与硬件接口初始化配置