/*采用行扫描线反转法RAM占用空间较多,因为用到的变量比较多,
但是程序变得简洁。
pic单片机当采用线反转法时端口寄存器要设置成输出*/
#include <pic.h> __CONFIG(0x3F32); //芯片配置字 #define uchar unsigned char #define uint unsigned int void delay10ms(uchar x); void beep(); void init(); uchar j; uchar LED_CODE[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0xbf}; uchar KEY_CODE[]={0x36,0x2e,0x1e,0x35,0x2d,0x1d,0x33,0x2b,0x1b}; uchar keyscan() { uchar temp1; PORTB=0x07;//将列线置0,行线作为输入状态检测。 temp1=PORTB;//读回B端口状态值 if((temp1&0x07)!=0x07)//不等于0x07表示有按键按下 { delay10ms(5);//调用延时 PORTB=0x07; temp1=PORTB;//读取行值,并保存 PORTB=0x38;//线反转,行列反转检测 for(j=0;j<=9;j++)//循环查表9次 { if((temp1|PORTB)==KEY_CODE[j])//判断行列值相加后是否等于查表值 { return(j);//返回j } } } } void main() { init();//系统初始化 PORTD=LED_CODE[9];//上电数码管显示“—” while(1) { PORTB=0x07; if(PORTB!=0x07)//判断有无按键按下有则执行按键处理程序 { keyscan();//调用扫描子程序 PORTD=LED_CODE[j];//显示对应键号 PORTB=0x07;//重新赋值 if(PORTB!=0x07)//再次判断有无按键按下 按下蜂鸣器响一声 { beep(); //调用蜂鸣器子函数 } while(PORTB!=0x07)//按键松手检测,如果按键一直按下关闭蜂鸣器 { RE1=0; delay10ms(1); } } } } void init()//系统初始化程序 { TRISB=0;//pic单片机当采用线反转法时端口寄存器要设置成输出 TRISD=0;//D端口设置为输出 TRISA=0;//A端口设置为输出 TRISE=0;//E端口设置为输出 PORTA=0;//A端口全部设置为低电平,位选开放 PORTD=0xFF;//D端口全部设置为高电平,段选关闭数码管不亮。 RE1=0;//蜂鸣器关闭 } void delay10ms(uchar x) { uint j,h; for(j=0;j<x;j++) for(h=0;h<625;h++); } void beep() { RE1=1; delay10ms(10); RE1=0; delay10ms(10); }