/* 矩阵按键控制程序*/#include typedef unsigned char u8;typedef unsigned int u16;***it LSA=P2^2; //定义 P2 口的第 2 位为特殊位变量 LSA***it LSB=P2^3; //定义 P2 口的第 3 位为特殊位变量 LSB***it LSC=P2^4; //定义 P2 口的第 4 位为特殊位变量 LSC#define GPIO_KEY P1 //定义 矩阵键盘的接口/按键的接口接到 P1 端口#define GPIO_DIG P0 //定义 数码管发送段码数据 的接口接到 P0 端口u8 KeyValue; //用来存放读取到的按键值//共阴数码管段编码数据u8 code smgduan[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //显示0~F的值//延时函数void delay(u16 i){ while(i--);}//按键扫描程序,识别具体哪一个按键按下void KeyDown(){ u8 a=0; //记录按键检测次数 //按照矩阵按键行列扫描原理判断哪一个按键按下 GPIO_KEY=0x0f; //设置按键触点初始值默认为零(高四位为 0000,低四位为 1111) if(GPIO_KEY!=0x0f) //判断按键是否按下 { delay(50000); //延时函数:软件消除抖动,按键按下时,触点会发生抖动现象,造成电压不稳 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; //设置按键触点初始值默认为1(高四位为 1111,低四位为 0000) //行检测:判断具体哪一行按下 switch(GPIO_KEY) { case 0x70: KeyValue=+0;break; case 0xb0: KeyValue=+4;break; case 0xd0: KeyValue=+8;break; case 0xe0: KeyValue=+12;break; } //按键超时判断并且退出程序 while((a<50) && (GPIO_KEY!=0xf0)) //判断按键是否松下(按键触点电平不为0,即按键持续按下,未松开) { delay(1000); a++; } } }}void main(){ LSA=0; LSB=0; LSC=0; while(1) { KeyDown(); //执行按键扫描函数,识别具体哪一个按键按下 GPIO_DIG=smgduan[KeyValue]; //向端口 P0 发送数码管段选数据 }}
问题 1:(u8 KeyValue;)
为什么用来存放读取到的按键值需要用 u8 类型的来定义,而不是 char 或者 int 类型;
答案:
u8 = unsigned char, u16 = unsigned int; char 本身范围(-128~127), 按键的值是没有负数的。所以用 u8 比较合适,且 char 类型占用的内存比 int 小。
问题 2:(u8 code smgduan[ ]={ })
为什么共阴数码管段编码数据需要用 u8 类型的来定义,而不是 int 类型或者其他类型的;
答案:
同1。
问题 3:(void delay(u16 i){ })
为什么延时函数要用 u16 类型的来定义,而不是 u8 类型或者 int 类型;
答案:
delay()延时函数通常取较大的数字,char 的范围(-128~127),u8 是(0~255),int 的范围(-2^31~2^(31-1)),u16 的范围(0~2^(31-1))。显然,(0~255)不能满足延时的需求。
问题 4:(u8 a=0; )
这个语句定义 a 是用来干什么用的,为什么是 u8 字符类型来定义,而不是用 char 类型或者 int 类型。
答案:
a 是用来检测按键是否松开的,每隔多少秒检测一次,未松开则 a++, 若到达一定次数则判定未松开,这里显然 a 也不可能为负数,故用u8。