原理在http://www.51hei.com/mcu/3815.html上讲得很清楚,也附了代码,本文主要是改进了代码中的一些问题,并且作了详细的注释,欢迎读者评论交流。(还没测试,测试结果要等键盘发过来)
#include"anjian4_4.h"
/*
PF7:A B C D
PF6:3 6 9 #
PF5:2 5 8 0
PF4:1 4 7 * 第一列
///
PF3:* 0 # D
PF2:7 8 9 C
PF1:4 5 6 B
PF0:1 2 3 A 第一行
*/
/*按键使能函数
PB0-PB7
*/
void Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
/********4列输出*********/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/********4行输入*********/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF, &GPIO_InitStructure);
}
//按键扫描函数
void matrixkeyscan()
{
uchar temp,key;
/*=========================以下代码是按键扫描程序=========================*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET); // 先清空引脚状态
/*----------------------------Scan the 1st ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET); // 设置PD1 2 3为1
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET); // 设置PD0 为0 二进制编码为1111 1110
//1111 1110 高位是列,低位是行
//把引脚的值赋给temp,作运算的时候不改变P3的值
//后面计算全部用temp,方便大规模改动引脚
temp=(GPIOF->IDR&0xFF);//读取
if((temp&0xf0)!=0xf0)//如果有按键按下
{
delayms(10);//延时消抖
temp=(GPIOF->IDR&0xFF);//第二次读取
if(temp!=0xf0)//如果有按键按下
{
switch(temp)//通过P3的值,判断是哪个按键按下
{
case 0xee:
key=1;
break;
case 0xde:
key=2;
break;
case 0xbe:
key=3;
break;
case 0x7e:
key='A';
break;
}
while(temp!=0xf0)//等待按键释放
{
temp=(GPIOF->IDR&0xFF);//读取
}
}
}
/*----------------------------Scan the 2st ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET); // 设置PD0 2 3为1
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET); // 设置PD1 为0 二进制编码为1111 1101
temp=(GPIOF->IDR&0xFF);//读取
if((temp&0xf0)!=0xf0)
{
delayms(10);
temp=(GPIOF->IDR&0xFF);//二次读取
if((temp&0xf0)!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key='B';
break;
}
while(temp!=0xf0)//等待按键释放
{
temp=(GPIOF->IDR&0xFF);//读取
}
}
}
/*----------------------------Scan the 3st ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3, GPIO_PIN_SET); // 设置PD0 1 3为1
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); // 设置PD2 为0 二进制编码为1111 1011
temp=(GPIOF->IDR&0xFF);//读取
temp=temp&0xf0;
if((temp&0xf0)!=0xf0)
{
delayms(10);
temp=(GPIOF->IDR&0xFF);//二次读取
if((temp&0xf0)!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=7;
break;
case 0xdb:
key=8;
break;
case 0xbb:
key=9;
break;
case 0x7b:
key='C';
break;
}
while(temp!=0xf0)//等待按键释放
{
temp=(GPIOF->IDR&0xFF);//读取
}
}
}
/*----------------------------Scan the 4st ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET); // 设置PF0 1 2为1
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); // 设置PF3 为0 二进制编码为1111 0111
temp=(GPIOF->IDR&0xFF);//读取
temp=temp&0xf0;
if((temp&0xf0)!=0xf0)
{
delayms(10);
temp=(GPIOF->IDR&0xFF);//二次读取
if((temp&0xf0)!=0xf0)
{
switch(temp)
{
case 0xe7:
key='*';
break;
case 0xd7:
key=0;
break;
case 0xb7:
key=9;
break;
case 0x77:
key='D';
break;
}
while(temp!=0xf0)//等待按键释放
{
temp=(GPIOF->IDR&0xFF);//读取
}
}
}
}
|