#include <reg52.h> //一般51单片机的头文件声明
上面是我们一般写51单片机程序的头文件,但是在蓝桥杯开发板上注意到其中需要用到P4口,而此头文件并没有声明P4口。
因此在使用的时候我们需要提前声明好P4口才能使用。
声明格式如下:
sfr P4 = 0xC0; //端口声明,此版本reg52没有P4口
在需要使用P4口的函数前声明即可
矩阵键盘的扫描思想
与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。我们以4X4的矩阵键盘为例,试着探讨其工作方式和扫描思路。
在上面的矩阵键盘中,要识别出黄色按键的按下状态,应该怎么做呢?
对与矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:
<1> R1输出点电平,R2、R3、R4输出高电平,逐个读取判断列信号,如果都为高电平则R1行上没有按键按下。
<2> R2输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
<3> R3输出点电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
<4> R4输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
如此循环往复,扫描的按键的状态。
/**********************************************************
@功能模块:主函数
@作 者:朱明
@时 间:2020年2月6日/
#include <reg52.h>
#include "mode.h"
#include "delay.h"
#include "test.h"
/**********************************************************
说明:"",<>,两种引用方式的区别:
<>是指从当前安装目录处引用,如果找不到则报错。
“”,是先从当前工程文件夹寻找如果找不到则到安装目录中去找,找不到则报错。
**********************************************************/
void main()
{
while(1)
{
test();
}
}
/********************************************************
@功能模块:工程函数
@作 者:朱明
@时 间:2020年2月6日
*********************************************************/
#include "test.h"
#include "testa.h"
sfr P4 = 0xC0; //端口声明,此版本reg52没有P4口
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C4 = P3^4;
sbit C3 = P3^5;
sbit C2 = P4^2;
sbit C1 = P4^4;
unsigned char code SMG_duanma[18]=
{ /*0*/ 0xc0 ,/*1*/ 0xf9 ,/*2*/ 0xa4 ,
/*3*/ 0xb0 ,/*4*/ 0x99 ,/*5*/ 0x92 ,
/*6*/ 0x82 ,/*7*/ 0xf8 ,/*8*/ 0x80 ,
/*9*/ 0x90 ,/*a*/ 0x88 ,/*b*/ 0x80 ,
/*c*/ 0xc6 ,/*d*/ 0xc0 ,/*e*/ 0x86 ,
/*f*/ 0x8e ,/*g*/ 0xbf ,/*h*/ 0x7f };
unsigned char key_num; //按键对应的数码管值
void test() //单片机使用核心工程文件
/************************************************************
//按键S7和S6为选择键,确定控制键控制那组LED指示灯。
//简单来说就是S7按下后,S6/S5/S4无效,再按下S7后按键S6方才有效。
//只有当S6按键有效的时候(S7无效)S5/S4按键的控制才有效
***********************************************************/
{
R1 = 0; //扫描第一排按键
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 =1;
if(C1 == 0)
{
while(C1 == 0);
key_num = 0;
testa(SMG_duanma[key_num]);
}
else if(C2 == 0)
{
while(C2 == 0);
key_num = 1;
testa(SMG_duanma[key_num]);
}
else if(C3 == 0)
{
while(C3 == 0);
key_num = 2;
testa(SMG_duanma[key_num]);
}
else if(C4 == 0)
{
while(C4 == 0);
key_num = 3;
testa(SMG_duanma[key_num]);
}
R2 = 0; //扫描第二排按键
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 =1;
if(C1 == 0)
{
while(C1 == 0);
key_num = 4;
testa(SMG_duanma[key_num]);
}
else if(C2 == 0)
{
while(C2 == 0);
key_num = 5;
testa(SMG_duanma[key_num]);
}
else if(C3 == 0)
{
while(C3 == 0);
key_num = 6;
testa(SMG_duanma[key_num]);
}
else if(C4 == 0)
{
while(C4 == 0);
key_num = 7;
testa(SMG_duanma[key_num]);
}
R3 = 0; //扫描第三排按键
R2 = R1 = R4 = 1;
C1 = C2 = C3 = C4 =1;
if(C1 == 0)
{
while(C1 == 0);
key_num = 8;
testa(SMG_duanma[key_num]);
}
else if(C2 == 0)
{
while(C2 == 0);
key_num = 9;
testa(SMG_duanma[key_num]);
}
else if(C3 == 0)
{
while(C3 == 0);
key_num = 10;
testa(SMG_duanma[key_num]);
}
else if(C4 == 0)
{
while(C4 == 0);
key_num = 11;
testa(SMG_duanma[key_num]);
}
R4 = 0; //扫描第四排按键
R2 = R3 = R1 = 1;
C1 = C2 = C3 = C4 =1;
if(C1 == 0)
{
while(C1 == 0);
key_num = 12;
testa(SMG_duanma[key_num]);
}
else if(C2 == 0)
{
while(C2 == 0);
key_num = 13;
testa(SMG_duanma[key_num]);
}
else if(C3 == 0)
{
while(C3 == 0);
key_num = 14;
testa(SMG_duanma[key_num]);
}
else if(C4 == 0)
{
while(C4 == 0);
key_num = 15;
testa(SMG_duanma[key_num]);
}
}
/********************************************************
@功能模块:模式函数
@作 者:朱明
@时 间:2020年2月6日
**********************************************************/
#include "mode.h"
void mode(unsigned char channel) //单片机使用前清零以及模式选择
{
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
/*********************************************************
@功能模块:工程函数
@作 者:朱明
@时 间:2020年2月6日
***********************************************************/
#include "testa.h"
#include "mode.h"
extern unsigned char key_num;
void testa(unsigned char value) //单片机使用核心工程文件
{
mode(6);
P0 = 0x01;
mode(7);
P0 = value;
mode(4);
P0 = 0xff << (key_num+1); //数码管显示对应的按键数
if (key_num > 7)
{
P0 = 0xff00 >> (key_num+1); //先从左到右扫描再从右到左扫描
}
}