矩阵按键pic汇编
- 格式:wps
- 大小:85.00 KB
- 文档页数:7
3×4的矩阵键盘电路图及汇编语言源程序
[导读] 3×4的矩阵键盘通过并行接口芯片8255A与微机相连。
8255A的A口定义为输出口,与键盘行线相连;B口定义为输入口,与键盘列线相连。
设8255A A口地址为40H,B口地址为41H,控制寄存
3×4的矩阵键盘通过并行接口芯片8255A与微机相连。
8255A的A口定义为输出口,与键盘行线相连;B口定义为输入口,与键盘列线相连。
设8255A A口地址为40H,B口地址为41H,控制寄存器地址为43H。
MOV AL,82H
OUT 43H,AL
BEGIN:MOV AL,0
OUT 40H,AL
WAIT : IN AL,41H
AND AL,0FH
CMP AL,0FH
JZ WAIT
MOV CX,7FFH
L0: LOOP L0
ST: MOV BL,3
MOV BH,4
MOV AL,0FEH
MOV CL,0FH
MOV CH,0FFH
L1: OUT 40H,AL
ROL AL
MOV AH,AL
IN AL,41H
AND AL,CL
CMP AL,CL
JNZ L2
ADD CH,BH
MOV AL,AH
DEC BL
JNZ L1
JMP BEGIN
L2: INC CH
RCR AL
JC L2
MOV AL,CH JMP KEYTABLE。
PIC16F877A矩阵键盘的用法Post By:2010-9-27 13:39:00/*********************************************************************** ********Platform: PIC1687AProject : 实验16:矩阵式按键Clock F : 外部4MSoftware: PICCAuthor : 竹林清风comments:学习使用矩阵式按键的用法本例功能是按一下相应键,数码管显示相应的值0-9;不带连发,不带组合,希望有兴趣的人帮忙完成并共享UP键按键计数proteus仿真通过;************************************************************************ *******/#include <pic.h>#include <pic1687x.h>#include"delay.h"#include"key.h"unsigned char led_7[]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管显示值unsigned char key_temp;void main(void){unsigned char ID=0;TRISB=0X00;//所有B0端口输出PORTB=0XFF;TRISD=0X0F;//初始化键盘接口PORTD=0XFF;//置输出为高电平while(1){delay_nms(5);key_temp = read_keyboard(); // 调用键盘接口函数读键盘 if (key_temp != No_key){ // 有按键按下switch(key_temp){case 1:PORTB=led_7[1];break;case 2:PORTB=led_7[2];break;case 3:PORTB=led_7[3];break;case 4:PORTB=led_7[4];break;case 5:PORTB=led_7[5];break;case 6:PORTB=led_7[6];break;case 7:PORTB=led_7[7];break;case 8:PORTB=led_7[8];break;case 9:PORTB=led_7[9];break;case K3_2:PORTB=led_7[0];break;case 13:if(++ID>=10){ID=0;}PORTB=led_7[ID];break;}}}}下面为延时函数:文件delay.cvoid delay_1us(void) //1us {asm("nop");}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}头文件:delay.hvoid delay_1us(void);void delay_nus(unsigned int n); //N us延时函数void delay_1ms(void); //1ms延时函数void delay_nms(unsigned int n); //N ms延时函数键盘key.h#define No_key 255#define K1_1 1#define K1_2 2#define K1_3 3#define k1_4 4#define K2_1 5#define K2_2 6#define K2_3 7#define K2_4 8#define K3_1 9#define K3_2 0#define K3_3 10#define K3_4 11#define K4_1 12#define K4_2 13#define K4_3 14#define K4_4 15#define Key_mask 0b00001111unsigned char read_keyboard(){static unsigned char key_state = 0, key_value, key_line;unsigned char key_return = No_key,i,key_time;switch (key_state){case 0:key_line = 0b00010000;for (i=1; i<=4; i++) // 扫描键盘{PORTD = ~key_line; // 输出行线电平PORTD = ~key_line; // 必须送2次!!!key_value = Key_mask & PORTD; // 读列电平if (key_value == Key_mask)key_line <<= 1; // 没有按键,继续扫描else{key_state++; // 有按键,停止扫描break; // 转消抖确认状态}}break;case 1:if (key_value == (Key_mask & PORTD)) // 再次读列电平, {switch (key_line | key_value) // 与状态0的相同,确认按键 { // 键盘编码,返回编码值case 0b00011110:key_return = K1_1; //"1"key_state++;break;case 0b00011101:key_return = K1_2; //"2"key_state++;break;case 0b00011011:key_return = K1_3; //"3"key_state++;break;case 0b00010111:key_return = k1_4; //"4" key_state++;break;case 0b00101110:key_return = K2_1; //"5" key_state++;break;case 0b00101101:key_return = K2_2; //"6" key_state++;break;case 0b00101011:key_return = K2_3; //"7" key_state++;break;case 0b00100111:key_return = K2_4; //"8" key_state++;break;case 0b01001110:key_return = K3_1; //"9" key_state++;break;case 0b01001101:key_return = K3_2; //"0" key_state++;break;case 0b01001011:key_return = K3_3; //"A"key_state++;break;case 0b01000111:key_return = K3_4; //"B"key_state++;break;case 0b10001110:key_return = K4_1; //"C"key_state++;break;case 0b10001101://key_return = K4_2; //"D"// key_state++;key_time=0;key_state=3;break;case 0b10001011:key_return = K4_3; //"E"key_state++;break;case 0b10000111:key_return = K4_4; //"F"key_state++;break;}// 转入等待按键释放状态}elsekey_state--; // 两次列电平不同返回状态0,(消抖处理)break;case 2: // 等待按键释放状态PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask)key_state=0; // 列线全部为高电平返回状态0 break;case 3:PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask){key_state=0; // 列线全部为高电平返回状态0 key_return = K4_2;}//break;else if( (Key_mask & PORTD)!=Key_mask) {if(++key_time>=100){key_state=4;key_time=0;key_return=20;}}break;case 4:PORTD = 0b00000111; // 行线全部输出低电平PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask){key_state=0; // 列线全部为高电平返回状态0 //key_return = K4_2;}else if(++key_time>=20){key_time=0;key_return=20;}break;}return key_return;}此主题相关图片如下ju.jpg:。
单片机矩阵键盘汇编语言程序(总6页)本页仅作为文档封面,使用时可以删除This document is for reference only-rar21year.March51单片机4*4矩阵键盘汇编语言程序示例(原创),欢迎咨询线反转法ORG 00HLJMP MAINMAIN:MOV R0,#00HMOV R1,#00HMOV R2,#00HMOV R3,#00HMOV A,#00HAJMP KEYSCANKEYSCAN:MOV P3,#0F0HMOV A,P3ANL A,#0F0HXRL A,#0F0HJNZ DELAYDELAY:MOV R2,#05HLOOP1:MOV R3,#0FAHLOOP2:DJNZ R3,LOOP2DJNZ R2,LOOP1MOV A,P3ANL A,#0F0HMOV R0,AXRL A,#0F0HJNZ KEYSCAN1LJMP KEYSCAN KEYSCAN1:MOV A,#00H MOV P3,#0FHMOV A,P3ANL A,#0FHMOV R1,AXRL A,#0FHJNZ NUMLJMP KEYSCANNUM:MOV A,R0MOV B,R1ORL A,BMOV DPTR,#TABSJMP DISP0DISP0:CJNE A,#0EEH,DISP1 MOV A,#00HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP1:CJNE A,#0EDH,DISP2 MOV A,#01HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP2:CJNE A,#0EBH,DISP3 MOV A,#02HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP3:CJNE A,#0E7H,DISP4 MOV A,#03HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP4:CJNE A,#0DEH,DISP5 MOV A,#04HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP5:CJNE A,#0DDH,DISP6 MOV A,#05HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP6:CJNE A,#0DBH,DISP7 MOV A,#06HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP7:CJNE A,#0D7H,DISP8 MOV A,#07HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP8:CJNE A,#0BEH,DISP9 MOV A,#08HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISP9:CJNE A,#0BDH,DISPA MOV A,#09HMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISPA:CJNE A,#0BBH,DISPB MOV A,#0AHMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISPB:CJNE A,#0B7H,DISPC MOV A,#0BHMOVC A,@A+DPTRMOV P0,ALJMP KEYSCANDISPC:CJNE A,#07EH,DISPDMOV A,#0CHMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISPD:CJNE A,#07DH,DISPEMOV A,#0DHMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISPE:CJNE A,#07BH,DISPFMOV A,#0EHMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDISPF:CJNE A,#077H,KEYMOV A,#0FHMOVC A,@A+DPTRMOV P0,ALCALL DELAY1LJMP KEYSCANDELAY1:MOV R2,#0FHLOOP10:MOV R3,#0FAHLOOP20:DJNZ R3,LOOP20DJNZ R2,LOOP10RETKEY:LJMP MAINTAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H END行扫描法ORG 00HLJMP MAINMAIN:LCALL KEYJUDGELCALL DISPLJMP MAIN KEYJUDGE:MOV P3,#0F0HMOV A,P3XRL A,#0F0HJNZ DELAYLJMP MAIN DELAY:MOV R4,#08H LOOP1:MOV R5,#0FAH LOOP2:DJNZ R5,LOOP2 DJNZ R4,LOOP1MOV P3,#0F0HMOV A,P3XRL A,#0F0HJZ MAINRETKEYSCAN:MOV R0,#00HMOV R1,#00HMOV R2,#0FEHMOV R3,#04H KEY:MOV P3,R2KEY0:JB ,KEY1MOV R1,#00HLJMP NUMKEY1:JB ,KEY2MOV R1,#04HLJMP NUMKEY2:JB ,KEY3MOV R1,#08HLJMP NUMKEY3:JB ,NEXTMOV R1,#0CHLJMP NUMNEXT:INC R0MOV A,R2RL AMOV R2,ADJNZ R3,KEYLJMP NUMNUM:MOV A,R0ADD A,R1MOV DPTR,#TABMOVC A,@A+DPTRMOV R6,ARETDISP:MOV P0,R6LCALL DELAY1RETDELAY1:MOV R4,#0FHLOOP10:MOV R5,#0FAHLOOP20:DJNZ R5,LOOP20DJNZ R4,LOOP10RETTAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H END。
C51矩阵键盘汇编语言源代码/************************************************************** ******************;* 描述: *;* lcd1602显示遥控键值读取器 *;* lcd1602显示遥控器接p3.2 *;* 喇叭接p1.5 继电器接p1.4 *;* 17(40h)键按下,继电器吸合。
19(04h)键按下,继电器关闭。
*;* 连接方法:使用红外功能时 J1跳线短接 **************************************************************** *****************/;-----------------------------------------------IRCOM EQU 20H ;20H-23H IR使用X EQU 26H ;LCD 地址变量IRIN EQU P3.2BEEP EQU P1.5RELAY EQU P1.4RS EQU P2.6RW EQU P2.5EN EQU P2.7;------------------------------------------------ORG 0000HJMP MAIN;------------------------------------------------MAIN:MOV SP,#40HMOV A,#00HMOV R0,#20HLOOP0: MOV @R0,A ;20H-26H清零INC R0CJNE R0,#27H,LOOP0SETB IRINCALL SET_LCDCALL MENU1LOOP1:CALL IR_INCALL IR_SHOWMOV A,22HCJNE A,#40H,LOOP2 ;K17键按下CLR RELAY ;继电器吸合LOOP2: CJNE A,#04H,LOOP3 ;K19键按下SETB RELAY ;继电器关闭LOOP3: JMP LOOP1;----------------------------------------------------- ; LCD 初始化设置;----------------------------------------------------- SET_LCD:CLR ENCALL INIT_LCD ;初始化 LCDCALL DELAY1MOV DPTR,#INFO1 ;指针指到显示信息1MOV A,#1 ;显示在第一行CALL LCD_SHOWMOV DPTR,#INFO2 ;指针指到显示信息2MOV A,#2 ;显示在第二行CALL LCD_SHOWRET;----------------------------------------------------- INIT_LCD: ;8位I/O控制 LCD 接口初始化MOV A,#38H ;双列显示,字形5*7点阵CALL WCOMCALL DELAY1MOV A,#38H ;双列显示,字形5*7点阵CALL WCOMCALL DELAY1MOV A,#38H ;双列显示,字形5*7点阵CALL WCOMCALL DELAY1MOV A,#0CH ;开显示,关光标,CALL WCOMCALL DELAY1MOV A,#01H ;清除 LCD 显示屏CALL WCOMCALL DELAY1RET;---------------------------------------------------- LCD_SHOW: ;在LCD的第一行或第二行显示信息字符CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置 LCD 的第一行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址CALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置 LCD 的第二行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址CALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: CALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;--------------------------------------------------- CLR_LINE: ;清除该行 LCD 的字符MOV R0,#24CL1: MOV A,#' 'CALL WDATADJNZ R0,CL1RET;---------------------------------------------------- MENU1: ;LCD 显示工作菜单信息MOV DPTR,#MENU2MOV A,#1 ;在第一行显示信息CALL LCD_SHOWRETMENU2: DB " Red Control ",0;----------------------------------------------------- INFO1: DB " ",0 ;LCD 第一行显示信息INFO2: DB " IR-CODE: --H ",0 ;LCD 第二行显示信息;-----------------------------------------------------;----------------------------------------------------- ; 写指令、数据使能子程序;----------------------------------------------------- WCOM:MOV P0,A ;写指令使能CLR RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲CLR RWSETB ENCALL DELAY0CLR ENRETWDATA:MOV P0,A ;写数据使能SETB RS ;RS=H,RW=L,D0-D7=数据,E=高脉冲CLR RWSETB ENCALL DELAY0CLR ENRETDELAY0: MOV R7,#250 ;延时500微秒DJNZ R7,$RET;---------------------------------------------------;在 LCD 第二行显示字符;A=ASC DATA, B=LINE X POS;--------------------------------------------------- LCDP2: ;在LCD的第二行显示字符PUSH ACC ;MOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址CALL WCOM ;写入命令POP ACC ;由堆栈取出ACALL WDATA ;写入数据RET;--------------------------------------------------- ; IR 译码子程序;--------------------------------------------------- IR_IN:MOV R0,#IRCOMI1: JNB IRIN,I2 ;等待 IR 信号出现JMP I1I2: MOV R4,#20I20: CALL DELDJNZ R4,I20JB IRIN,I1 ;确认IR信号出现I21: JB IRIN,I3 ;等 IR 变为高电平CALL DELJMP I21I3: MOV R3,#0 ;8位数清为0LL: JNB IRIN,I4 ;等 IR 变为低电平CALL DELJMP LLI4: JB IRIN,I5 ;等 IR 变为高电平CALL DELJMP I4I5: MOV R2,#0 ;0.14ms 计数L1: CALL DELJB IRIN, N1 ;等 IR 变为高电平;IR=0,检查R2中的计数值MOV A,#8CLR CSUBB A,R2 ;判断高低位;IF C=0 BIT=0MOV A,@R0RRC AMOV @R0,A ;处理完一位INC R3CJNE R3,#8,LL ;需处理完8位MOV R3,#0INC R0CJNE R0,#24H,LL ;收集到4字节了JMP OKN1: INC R2CJNE R2,#30,L1 ;0.14ms 计数过长则时间到自动离开OK: RET;--------------------------------------------------------------------IR_SHOW:MOV A,22HCPL A ;将22H取反后和23H比较CJNE A,23H,IR_SHOW1 ;如果不等表示接收数据发生错误,放弃。
4*4矩阵键盘扫描汇编程序(基于51单片机)// 程序名称:4-4keyscan.asm;// 程序用途:4*4矩阵键盘扫描检测;// 功能描述:扫描键盘,确定按键值。
程序不支持双键同时按下,;// 如果发生双键同时按下时,程序将只识别其中先扫描的按键;// 程序入口:void;// 程序出口:KEYNAME,包含按键信息、按键有效信息、当前按键状态;//================================================================== ====PROC KEYCHKKEYNAME DATA 40H ;按键名称存储单元;(b7-b5纪录按键状态,b4位为有效位,;b3-b0纪录按键)KEYRTIME DATA 43H ;重复按键时间间隔SIGNAL DATA 50H ;提示信号时间存储单元KEY EQU P3 ;键盘接口(必须完整I/O口) KEYPL EQU P0.6 ;指示灯接口RTIME EQU 30 ;重复按键输入等待时间KEYCHK:;//=============按键检测程序========================================= ====MOV KEY,#0FH ;送扫描信号MOV A,KEY ;读按键状态CJNE A,#0FH,NEXT1 ;ACC<=0FH; CLR C ;Acc等于0FH,则CY为0,无须置0NEXT1:; SETB C ;Acc不等于0FH,则ACC必小于0 FH,;CY为1,无须置1MOV A,KEYNAMEANL KEYNAME,#1FH ;按键名称屏蔽高三位RRC A ;ACC带CY右移一位,纪录当前按键状态ANL A,#0E0H ;屏蔽低五位ORL KEYNAME,A ;保留按键状态;//=============判别按键状态,决定是否执行按键扫描=================== =====CJNE A,#0C0H,NEXT2 ;110按键稳定闭合,调用按键检测子程序SJMP KEYSCANNEXT2:CJNE A,#0E0H,NEXT3 ;111按键长闭合,重复输入允许判断SJMP WAITNEXT3:CJNE A,#0A0H,EXIT ;101干扰,当111长闭合处理ORL KEYNAME,#0E0HWAIT:MOV A,KEYRTIMEJNZ EXIT ;时间没到,退出;//=============键盘扫描程序========================================= =====KEYSCAN:MOV R1,#0 ;初始化列地址MOV R3,#11110111B ;初始化扫描码LOOP:MOV A,R3RL AMOV R3,A ;保留扫描码MOV KEY,A ;送扫描码MOV A,KEY ;读键盘ORL A,#0F0H ;屏蔽高四位CJNE A,#0FFH,NEXT31 ;A不等于FFH,说明该列有按键动作INC R1 ;列地址加1,准备扫描下一列CJNE R1,#4,LOOP ;列地址不等于4,扫描下一列SJMP EXIT ;没有按键,退出;//=============按键判断对应位等于零,说明该行有按键按下============= =====NEXT31:JB ACC.0,NEXT32MOV R2,#0 ;第0行有按键SJMP NEXT5NEXT32:JB ACC.1,NEXT33MOV R2,#1 ;第1行有按键SJMP NEXT5NEXT33:JB ACC.2,NEXT34MOV R2,#2 ;第2行有按键SJMP NEXT5NEXT34:MOV R2,#3 ;第3行有按键NEXT5: ;计算按键地址MOV A,R1RL ARL A ;列地址乘4(每列对应4行)ADD A,R2 ;加行地址MOV DPTR,#KEYTABMOVC A,@A+DPTRANL KEYNAME,#0E0HORL KEYNAME,A ;送按键(送值的时候已经置按键有效)MOV KEYRTIME,#RTIME ;送重复按键等待时间CLR KEYPL ;打开指示灯MOV SIGNAL,#10 ;送信号提示时间(每次按键闪10 0ms)EXIT:MOV KEY,#0FFH ;置键盘接口高电平RET ;退出;//=============按键名称表=========================================== =====KEYTAB:DB 1AH ;扫描码0,对应A ************************************ ******DB 1BH ;扫描码1,对应B ** **DB 1CH ;扫描码2,对应C ** I/O口 PX.4 PX.5 PX.6 PX.7 **DB 1DH ;扫描码3,对应D ** **DB 11H ;扫描码4,对应1 ** PX.0 A(0) 1(4) 2(8) 3 (C) **DB 14H ;扫描码5,对应4 ** **DB 17H ;扫描码6,对应7 ** PX.1 B(1) 4(5) 5(9) 6 (D) **DB 1EH ;扫描码7,对应E ** **DB 12H ;扫描码8,对应2 ** PX.2 C(2) 7(6) 8(A) 9 (E) **DB 15H ;扫描码9,对应5 ** **DB 18H ;扫描码A,对应8 ** PX.3 D(3) E(7) 0(B) F(F) **DB 10H ;扫描码B,对应0 ** **DB 13H ;扫描码C,对应3 ************************************ ******DB 16H ;扫描码D,对应6DB 19H ;扫描码E,对应9DB 1FH ;扫描码F,对应FEND第二种解法ORG 0000HSTART: MOV R0,#00H ;初始化程序,开始的延时是为了使硬件能够准备好DJNZ R0,$LOOP: MOV SP,#60HCALL KEYDISPLAY:MOV A,R4MOV DPTR,#TABLE ;定义字形表的起始地址MOVC A,@A+DPTR ;TABLE为表的起始地址MOV P2,ASJMP LOOP;子程序内容,P1口的低四位为行线,高四位为列线KEY: PUSH PSWPUSH ACCMOV P1,#0F0H ;令所有的行为低电平,全扫描字-P1.0-P1.3,列为输入方式;这一段只是验证有键按下,并不能判断是哪一行MOV R7,#0FFH ;设置计数常数,作为延时KEY1: DJNZ R7, KEY1MOV A,P1 ;读取P1口的列值ANL A,#0F0H ;判别有键值按下吗(当有键按下时,P1口的高四位就不全为1了,底四位还是都为0的);这个地方进行相或的原因,是因为要把底四位的0000变成1111,以便下一步进行求反ORL A,#0FH //这个地方原版上没有,这是又加了,如果不加的的话,是不对的********CPL A ;求反后,有高电平就有键按下JZ EKEY;累加器为0则转移(意为求反后本来全为0的,如果有键按下时,求反后高四位就有1了),退出LCALL DEL20ms ;有键按下,进行处理;下面进行行行扫描,1行1行扫SKEY: MOV A,#00HMOV R0,A ;R0作为行计数器,开始初值为0MOV R1,A ;R1作为列计数器,开始初值为0MOV R2,#0FEH ;R2作为扫描暂存字,开始初值为1111 1110,(第四位作为行扫描字)SKEY2: MOV A,R2MOV P1,A ;输出行扫描字,1111 1110NOPNOPNOP ;3个NOP操作使P1口输出稳定MOV A,P1 ;读列值(和开始一样)MOV R1,A ;暂存列值(第一次为**** 1110,既高四位有一位"可能"会为0)ANL A,#0F0H ;取高四位,ORL A,#0FH ;使第四位全部置1CPL ABIAOZHI:JNZ SKEY3 ;累加器为非0则转移指令(意思是判断到按键在这一行),转去处理INC R0 ;如果按键没在这一行,行计数器加1SETB C ;进位标志位加1,为了在左移的时候开始的低位0不在出现在低(循环一圈后)MOV A,R2RLC A ;带进位左移1位(形成下一行扫描字,再次扫描)MOV R2,AMOV A,R0;把加1后的行计数器R0和总共扫描次数(4次比较)CJNE A,#04H,SKEY2 ;(扫描完了么)书本上这个地方也有错误,书本上写的是:SKEY1AJMP EKEY ;如果没有的话,退出;有键按下后行扫描过后,此为确列行SKEY3: MOV A,R1 ;JNB ACC.4,SKEY5 ;直接寻址位为0咋转移指令JNB ACC.5,SKEY6JNB ACC.6,SKEY7JNB ACC.7,SKEY8AJMP EKEY //我自己感觉到这命令没有用处SKEY5: MOV A,#00H ;存0列号MOV R3,AAJMP DKEYSKEY6: MOV A,#01H ;存1列号MOV R3,AAJMP DKEYSKEY7: MOV A,#02H ;存2列号MOV R3,AAJMP DKEYSKEY8: MOV A,#03H ;存3列号MOV R3,AAJMP DKEY;取出具体的行号,再加上列号,最终确认按键的号码DKEY: //MOV R4,#00HMOV A,R0MOV B,#04HMUL AB ;让行号*4,第四位放在A中(总共就4行,相乘后一定<16,也就是只有第四位有值)ADD A,R3 ;让行号和列号相加,最终确认任按键的具体号MOV R4,AEKEY: POP ACCPOP PSWRET ;按键扫描处理函数DEL20ms:MOV R7,#2DL2: MOV R6,#18DL1: MOV R5,#255DJNZ R5,$DJNZ R6,DL1DJNZ R7,DL2RET;此为共阴极数码管的数字表TABLE: DB 3FH ;0DB 06H ;1DB 5BH ;2DB 4FH ;3DB 66H ;4DB 6DH ;5DB 7DH ;6DB 27H ;7DB 7FH ;8DB 6FH ;9DB 77HDB 7CHDB 39HDB 5EHDB 79HDB 71HEND第三种PIC单片机键盘扫描汇编程序;本程序用于PIC外接键盘的识别,通过汇编程序,使按下K1键时第一个数码管显示1,按下K2键时第一;个数码管上显示2,按下K3键时第一个数码管上显示3,按下K4键时第一个数码管上显示4,;汇编程序对键盘的扫描采用查询方式LIST P=18F458INCLUDE "P18F458.INC";所用的寄存器JIANR EQU 0X20FLAG EQU JIANR+1 ;标志寄存器DEYH EQU JIANR+2DEYL EQU JIANR+3F0 EQU 0 ;FLAG的第0位定义为F0ORG 0X00GOTO MAINORG 0X30;*************以下为键盘码值转换表****************** CONVERT ADDWF PCL,1RETLW 0XC0 ;0,显示段码与具体的硬件连接有关RETLW 0XF9 ;1RETLW 0XA4 ;2RETLW 0XB0 ;3RETLW 0X99 ;4RETLW 0X92 ;5RETLW 0X82 ;6RETLW 0XD8 ;7RETLW 0X80 ;8RETLW 0X90 ;9RETLW 0X88 ;ARETLW 0X83 ;BRETLW 0XC6 ;CRETLW 0XA1 ;DRETLW 0X86 ;ERETLW 0X8E ;FRETLW 0X7F ;"."RETLW 0XBF ;"-"RETLW 0X89 ;HRETLW 0XFF ;DARKRETURN;***************PIC键盘扫描汇编程序初始化子程序***************** INITIALBCF TRISA,5 ;置RA5为输出方式,以输出锁存信号BCF TRISB,1BCF TRISA,3BCF TRISE,0BCF TRISE,1BSF TRISB,4 ;设置与键盘有关的各口的输入输出方式BCF TRISC,5BCF TRISC,3 ;设置SCK与SDO为输出方式BCF INTCON,GIE ;关闭所有中断LW 0XC0WF SSPSTAT ;设置SSPSTAT寄存器LW 0X30WF SSPCON1 ;设置SPI的控制方式,允许SSP方式,并且时钟下降;沿发送数据,与"74HC595当其SCLK从低到高电平;跳变时,串行输入数据(DI)移入寄存器"的特点相对应LW 0X01WF JIANR ;显示值寄存器(复用为键值寄存器)赋初值CLRF FLAG ;清除标志寄存器RETURN ;返回;**************显示子程序*****************DISPLAYCLRF PORTAWF SSPBUFAGAINBTFSS PIR1,SSPIFGOTO AGAINNOPBCF PIR1,SSPIFBSF PORTA,5 ;详细的程序语句请参考 pic教程语句部分,可在首页搜索。
PIC单片机矩阵键盘+线反转法/*采用行扫描线反转法RAM 占用空间较多,因为用到的变量比较多,但是程序变得简洁。
pic 单片机当采用线反转法时端口寄存器要设置成输出*/#include pic.h__CONFIG(0x3F32); //芯片配置字#define uchar unsigned char #define uint unsigned intvoid delay10ms(uchar x);void beep();void init();uchar j;ucharLED_CODE[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};ucharKEY_CODE[]={0x36,0x2e,0x1e,0x35,0x2d,0x1d,0x33,0x2b,0x1b};ucharkeyscan(){uchar temp1;PORTB=0x07;//将列线置0,行线作为输入状态检测。
temp1=PORTB;//读回B 端口状态值if((temp10x07)!=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 端口全部设置为高电平,段选关闭数码管不亮。
目录1 引言 (2)2 4×4矩阵键盘控制LED工作原理及软硬件设计、仿真调试 (2)2.1 4×4矩阵式键盘识别显示系统概述 (2)2.2 4×4矩阵式键盘原理 (3)2.3 4×4矩阵式键盘控制LED显示方法 (3)2.4 电路设计及电路图 (3)2.5 4×4矩阵式键盘软件编程 (6)2.6 4×4矩阵式键盘软件仿真调试分析 (9)3 结论 (10)4参考文献 (10)1 引言随着现代科技日新月异的发展,作为新兴产业,单片机的应用越来越广。
单片机以其体积小、重量轻、功能强大、功耗低等特点而备受青睐。
键盘作为一种最为普遍的输入工具在单片机项目应用上显得尤为重要。
用MCS51系列的单片机并行口P1接4×4矩阵键盘,以P1.0-P1.3 作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的0-F序号。
2 4×4矩阵键盘控制LED工作原理及软硬件设计、仿真调试2.1 4×4矩阵式键盘识别显示系统概述矩阵式键盘模式以4个端口连接控制4*4个按键,实时在LED数码管上显示按键信息。
显示按键信息,省下了很多的I/O端口为他用,相反,独立式按键虽编程简单,但占用I/O口资源较多,不适合在按键较多的场合应用。
矩阵式键盘简介:矩阵式键盘又称行列键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
在行线和列线的每个交叉点上设置一个按键。
这样键盘上按键的个数就为4*4个。
这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。
最常见的键盘布局如图1所示。
一般由16个按键组成,在单片机中正好可以用一个P 口实现16个按键功能,这也是在单片机系统中最常用的形式,本设计就采用这个键盘模式。
2.2 4×4矩阵式键盘原理在占用相同的I/O端口的情况下,行列式键盘的接法会比独立式接法允许的按键数量多。
计算机原理实验室实验报告课程名称:姓名学号班级成绩设备名称及软件环境实验名称矩阵键盘实验日期一.实验内容掌握4×4矩阵式键盘程序识别原理及4×4矩阵式键盘按键的设计方法。
二.理论分析或算法分析用单片机的并行口P3连接4×4矩阵键盘,并以单片机的P3.0-P3.3各管脚作输入线,以单片机的P3.4-P3.7各管脚作输出线,在数码管上显示每个按键“0-F”的序号。
4×4矩阵式键盘识别电路原理图:键盘中对应按键的序号排列:电路硬件说明(1)在“单片机系统”区域中,把单片机的P3.0-P3.7端口通过8联拨动拨码开关JP3连接到“4×4行列式键盘”区域中的M1-M4,N1-N4端口上。
(2)在“单片机系统”区域中,把单片机的P0.0-P0.7端口连接到“静态数码显示模块”区域中的任何一个a-h端口上;要求:P0.0对应着a,P0.1对应着b,……,P0.7对应着h。
三.实现方法(含实现思路、程序流程图、实验电路图和源程序列表等)1、4×4矩阵键盘识别处理。
2、每个按键都有它的行值和列值,行值和列值的组合就是识别这个按键的编码。
矩阵的行线和列线分别通过两并行接口和CPU通信。
键盘的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么?还要消除按键在闭合或断开时的抖动。
两个并行口中,一个输出扫描码,使按键逐行动态接地;另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
3、程序流程图:4、汇编源程序:;;;;;;;;;;定义单元;;;;;;;;;;COUNT EQU 30H;;;;;;;;;;入口地址;;;;;;;;;;ORG 0000HLJMP STARTORG 0003HRETIORG 000BHRETIORG 0013HRETIORG 001BHRETIORG 0023HRETIORG 002BHRETI;;;;;;;;;;主程序入口;;;;;;;;;;ORG 0100H START: LCALL CHUSHIHUALCALL PANDUANLCALL XIANSHILJMP START ;;;;;;;;;;初始化程序;;;;;;;;;;CHUSHIHUA: MOV COUNT,#00HRET;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;;PANDUAN: MOV P3,#0FFHCLR P3.4MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW1LCALL DELAY10MSJZ SW1MOV A,P3ANL A,#0FHCJNE A,#0EH,K1MOV COUNT,#0LJMP DKK1: CJNE A,#0DH,K2MOV COUNT,#4LJMP DKK2: CJNE A,#0BH,K3MOV COUNT,#12 K4: NOPLJMP DKSW1: MOV P3,#0FFHCLR P3.5MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW2LCALL DELAY10MS JZ SW2MOV A,P3ANL A,#0FHCJNE A,#0EH,K5 MOV COUNT,#1 LJMP DKK5: CJNE A,#0DH,K6MOV COUNT,#5 LJMP DKK6: CJNE A,#0BH,K7MOV COUNT,#9 LJMP DKK7: CJNE A,#07H,K8MOV COUNT,#13 K8: NOPLJMP DKSW2: MOV P3,#0FFHCLR P3.6MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW3LCALL DELAY10MS JZ SW3MOV A,P3ANL A,#0FHCJNE A,#0EH,K9 MOV COUNT,#2 LJMP DKK9: CJNE A,#0DH,KAMOV COUNT,#6 LJMP DKKA: CJNE A,#0BH,KBMOV COUNT,#14 KC: NOPLJMP DKSW3: MOV P3,#0FFHCLR P3.7MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW4LCALL DELAY10MS JZ SW4MOV A,P3ANL A,#0FHCJNE A,#0EH,KD MOV COUNT,#3LJMP DKKD: CJNE A,#0DH,KEMOV COUNT,#7LJMP DKKE: CJNE A,#0BH,KFMOV COUNT,#11 LJMP DKKF: CJNE A,#07H,KGMOV COUNT,#15 KG: NOPLJMP DKSW4: LJMP PANDUANDK: RET;;;;;;;;;;显示程序;;;;;;;;;;XIANSHI: MOV A,COUNTMOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,ALCALL DELAYSK: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ SKRET;;;;;;;;;;10ms延时程序;;;;;;;;;;DELAY10MS: MOV R6,#20D1: MOV R7,#248DJNZ R6,D1RET;;;;;;;;;;200ms延时程序;;;;;;;;;;DELAY: MOV R5,#20LOOP: LCALL DELAY10MSDJNZ R5,LOOPRET;;;;;;;;;;共阴码表;;;;;;;;;;TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07HDB 7FH,6FH,77H,7CH,39H,5EH,79H,71H;;;;;;;;;;结束标志;;;;;;;;;;END八、C语言源程序#include<AT89X51.H>unsigned char code table[]={0x3f,0x66,0x7f,0x39,0x06,0x6d,0x6f,0x5e,0x5b,0x7d,0x77,0x79,0x4f,0x07,0x7c,0x71};void main(void){ unsigned char i,j,k,key;while(1){ P3=0xff; //给P3口置1//P3_4=0; //给P3.4这条线送入0//i=P3;i=i&0x0f; //屏蔽低四位//if(i!=0x0f) //看是否有按键按下//{ for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);if(i!=0x0f) //再次判断按键是否按下//{ switch(i) //看是和P3.4相连的四个按键中的哪个// { case 0x0e:key=0;break;case 0x0d:key=1;break;case 0x0b:key=2;break;case 0x07:key=3;break;}P0=table[key]; //送数到P0口显示//}P3=0xff;P3_5=0; //读P3.5这条线//i=P3;i=i&0x0f; //屏蔽P3口的低四位//if(i!=0x0f) //读P3.5这条线上看是否有按键按下// { for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);i=P3; //再看是否有按键真的按下//i=i&0x0f;if(i!=0x0f){ switch(i) //如果有,显示相应的按键//{ case 0x0e:key=4;break;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}P0=table[key]; //送入P0口显示//}}P3=0xff;P3_6=0; //读P3.6这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=8;break;case 0x0d:key=9;break;case 0x0b:break;case 0x07:key=11;break;}P0=table[key];}}P3=0xff;P3_7=0; //读P3.7这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=12;break;case 0x0d:key=13;break;case 0x0b:key=14;break;case 0x07:key=15;break;}P0=table[key];}}}}四.实验结果分析(含执行结果验证、输出显示信息、图形、调试过程中所遇的问题及处理方法等)五.结论报告提交日期(注意:内容写不下时允许表格添加新行。
PIC单片机自学手记——PIC 单片机矩阵键盘+行扫描法/*采用行扫描法RAM占用空间较少(呵呵起码我写的程序是这样的,因为我刚开始学,还不是很懂各方面的程序优化)*/#include <pic.h>__CONFIG(0x3F32); //芯片配置字#define uchar unsigned char#define uint unsigned intvoid delay10ms(uchar x);void beep();void init();uchar key;uchar LED_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};void keyscan(){uchar temp;PORTB=0x07;//将列线置0,行线作为输入状态检测。
temp=PORTB;//读回B端口状态值if((temp&0x07)!=0x07)//将读取的值跟0x07做与运算然后再判断是否不等于0x07,如果不等于说明有按键按下{delay10ms(1);//延时10毫秒,去抖动(去干扰)PORTB=0x07;//同上temp=PORTB;//同上if((temp&0x07)!=0x07)//延时消抖后再次判断是否真的有按键按下,如果有再判断是此行的哪个按键(这里我们用的是3x3矩阵键盘,则每行有3种情况){PORTB=0x37;//第一行状态temp=PORTB;//读回B端口状态值switch(temp)//判断第一行按键按下后可能产生的情况{case 0x33:key=7;break;//第一种情况:1号按键按下_0B0011 0011case 0x35:key=4;break;//第二种情况:2号按键按下_0B0011 0101case 0x36:key=1;break;//第三种情况:3号按键按下_0B0011 0110}PORTB=0x2F;//第二行状态temp=PORTB;//读回B端口状态值switch(temp)//判断第二行按键按下后可能产生的情况{case 0x2b:key=8;break;//第一种情况:4号按键按下_0B0010 1011case 0x2d:key=5;break;//第二种情况:5号按键按下_0B0010 1101case 0x2e:key=2;break;//第三种情况:6号按键按下_0B0011 1110 }PORTB=0x1F;//第三行状态temp=PORTB;//读回B端口状态值switch(temp)//判断第三行按键按下后可能产生的情况{case 0x1b:key=9;break;//第一种情况:7号按键按下_0B0001 1011 case 0x1d:key=6;break;//第二种情况:8号按键按下_0B0001 1101 case 0x1e:key=3;break;//第三种情况:9号按键按下_0B0001 1110 }}}}void main(){init();//系统初始化PORTD=LED_CODE[10];//上电数码管显示“—”while(1){PORTB=0x07;if(PORTB!=0x07)//判断有无按键按下有则执行按键处理程序{keyscan();//调用扫描子程序PORTD=LED_CODE[key];//显示对应键号PORTB=0x07;//重新赋值if(PORTB!=0x07)//再次判断有无按键按下按下蜂鸣器响一声{beep(); //调用蜂鸣器子函数}while(PORTB!=0x07)//按键松手检测,如果按键一直按下关闭蜂鸣器 {RE1=0;delay10ms(1);}}}}void init()//系统初始化程序{TRISB=0x07;//低三位,行作为输入TRISD=0;//D端口设置为输出TRISA=0;//A端口设置为输出TRISE=0;//E端口设置为输出PORTA=0;//A端口全部设置为低电平,位选开放PORTD=0xFF;//D端口全部设置为高电平,段选关闭数码管不亮。
方法一、ORG 0000HLJMP MAINORG 0100HMAIN:MOV P1,#0F0H //P1口设初值F0,矩阵按键高四位置1,低四位置0,JNB P1.4,Y0 //用JNB检测按键端口,P1.4口低电平跳转 Y0JNB P1.5,Y1JNB P1.6,Y2JNB P1.7,Y3SJMP MAINY0:MOV 30H,#00HMOV P1,#0EFHJNB P1.4,X0MOV P1,#0DFHJNB P1.4,X1MOV P1,#0BFHJNB P1.4,X2MOV P1,#07FHJNB P1.4,X3Y1:MOV 30H,#01HMOV P1,#0EFHJNB P1.0,X0MOV P1,#0DFHJNB P1.1,X1MOV P1,#0BFHJNB P1.2,X2MOV P1,#7FHJNB P1.3,X3Y2:MOV 30H,#02HMOV P1,#0EFHJNB P1.0,X0MOV P1,#0DFHJNB P1.1,X1MOV P1,#0BFHJNB P1.2,X2MOV P1,#7FHJNB P1.3,X3Y3:MOV 30H,#03HMOV P1,#0EFHMOV P1,#0DFHJNB P1.1,X1MOV P1,#0BFHJNB P1.2,X2MOV P1,#7FHJNB P1.3,X3X0:MOV 31H,#00HACALL DELAYMOV P1,#0F0HLJMP JISUANX1:MOV 31H,#01HACALL DELAYMOV P1,#0F0HLJMP JISUANX2:MOV 31H,#02HACALL DELAYMOV P1,#0F0HLJMP JISUANX3:MOV 31H,#03HACALL DELAYMOV P1,#0F0HLJMP JISUAN JISUAN:MOV A,31HMOV B,#04HMUL ABADD A,30HMOV DPTR,#TABMOVC A,@A+DPTRMOV P0,ACC:MOV A,P1ANL A,#0F0HXRL A,#0F0HJNZ CCLCALL MAIN DELAY: MOV R4,#0C5HD1: MOV R5,#43HD0: MOV R6,#10HDJNZ R5,D0DJNZ R4,D1RETTAB: DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07 DB 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71方法二、ORG 0000HLJMP STARTKEYSBUF EQU 30HORG 0100HSTART:MOV P1,#0F0HMOV A,P1ANL A,#0F0HXRL A,#0F0HJZ STARTLCALL DELAYMOV P1,#0F0HMOV A,P1ANL A,#0F0HXRL A,#0F0HJZ STARTMOV P1,#0FEH //第0行置0CLR P1.0MOV A,P1ANL A,#0F0H //与逻辑,高位保留CJNE A,#0E0H,K1 //高四位为1110,数字0亮MOV KEYSBUF,#0LJMP DISPLAYK1: CJNE A,#0D0H,K2 // 高四位为1101,数字1亮MOV KEYSBUF,#1LJMP DISPLAYK2: CJNE A,#0B0H,K3// 高四位为1011,数字2亮MOV KEYSBUF,#2LJMP DISPLAYK3: CJNE A,#070H,K4 //高四位为0111,数字3亮MOV KEYSBUF,#3LJMP DISPLAYK4: MOV P1,#0FDH //第1行置0MOV A,P1ANL A,#0F0HCJNE A,#0E0H,K5 //高四位为1110,数字4亮MOV KEYSBUF,#4LJMP DISPLAYK5: CJNE A,#0D0H,K6 // 高四位为1101,数字5亮MOV KEYSBUF,#5LJMP DISPLAYK6: CJNE A,#0B0H,K7// 高四位为1011,数字6亮MOV KEYSBUF,#6LJMP DISPLAYK7: CJNE A,#070H,K8 //高四位为0111,数字7亮MOV KEYSBUF,#7LJMP DISPLAYK8: MOV P1,#0FBH //第2行置0MOV A,P1ANL A,#0F0HCJNE A,#0E0H,K9 //高四位为1110,数字8亮MOV KEYSBUF,#8LJMP DISPLAYK9: CJNE A,#0D0H,K10 // 高四位为1101,数字9亮MOV KEYSBUF,#9LJMP DISPLAYK10: CJNE A,#0B0H,K11// 高四位为1011,数字A亮MOV KEYSBUF,#10LJMP DISPLAYK11: CJNE A,#070H,K12 //高四位为0111,数字B亮MOV KEYSBUF,#11LJMP DISPLAYK12: MOV P1,#0F7H //第3行置0MOV A,P1ANL A,#0F0HCJNE A,#0E0H,K13 //高四位为1110,数字C亮MOV KEYSBUF,#12LJMP DISPLAYK13: CJNE A,#0D0H,K14 // 高四位为1101,数字D亮MOV KEYSBUF,#13LJMP DISPLAYK14: CJNE A,#0B0H,K15// 高四位为1011,数字E亮MOV KEYSBUF,#14LJMP DISPLAYK15:MOV KEYSBUF,#15 //高四位为0111,数字F亮LJMP DISPLAYDISPlAY:MOV DPTR,#TABMOV A,KEYSBUFMOVC A,@A+DPTRMOV P0,ACC: MOV A,P1ANL A,#0F0HXRL A,#0F0HJNZ CCLJMP STARTDELAY:MOV R6,#10D1:MOV R7,#248D2:DJNZ R7,D2DJNZ R6,D1RETTAB:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71HEND。
今天上传一个pic16f877矩阵按键扫描程序,用汇编写的。
Proteus仿真图:汇编代码:;===================================================================== ==;功能:矩阵按键扫描显示;muc:pic16f877a;===================================================================== ==LISTP=16F877#INCLUDE P16F877.INCseg EQU H'20' ;定义片选显示寄存器segcon equ h'21' ;显示数据计数器寄存器condy0 equ h'22' ;延时计数器condy1 equ h'23' ;延时计数器keytmp equ h'24' ;key EQU H'25'daltmp EQU H'26' ;键值处理暂存器coh EQU H'27'col EQU H'28'diskey EQU H'29'keytmp1 EQU H'30'output equ PORTD ;key端口segment EQU PORTB ;数码管段选ORG 0000HNOP;===================初始化===============================================StartBSF STA TUS,RP0CLRF TRISBCLRF TRISCmovlw h'0F'movwf TRISD ;高四位为输出,低四位为输入BCF STA TUS,RP0MOVLW H'01'MOVWF PORTC ;开第一个数码管;========================主函数===========================================MainCALL Keyscan ;按键扫描CALL KeyDpl ;按键处理CALL Display ;显示GOTO Main;======================显示程序===========================================DisplayMOVF diskey,WCALL DistabMOVWF segmentRETURN;------------------------共阳数码管显示列表--------------------------------;0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};//0 ~FDistabaddwf PCL,Fretlw h'0c0'retlw h'0f9'retlw h'0a4'retlw h'0b0'retlw h'99'retlw h'92'retlw h'82'retlw h'0f8'retlw h'80'retlw h'90'retlw h'88'retlw h'83'retlw h'0c6'retlw h'0a1'retlw h'86'retlw h'8e'RETLW H'0FF';=========================按键处理========================================;功能:对扫描到的按键进行处理;输入参数:key;------------------------------------------------------------------------- KeyDplMOVLW H'04'MOVWF coh ;给行初值MOVF key,WMOVWF daltmpKDpl0_1RRF daltmp,FBTFSS STA TUS,C ;判断进位GOTO KDpl1_0KDpl0_0DECFSZ coh,FGOTO KDpl0_1GOTO KDPL0 ;无正常键值退出KDpl1_0MOVF coh,WSUBLW H'04'MOVWF cohBCF STA TUS,CRLF coh,F ;乘4RLF coh,FMOVF col,WADDWF coh,WMOVWF diskeyKDPLRETURNKDPL0MOVLW H'10'GOTO KDPL;========================按键扫描=========================================;功能:用列+行扫描法扫描键值;输入:output0~3;输出:output4~7;------------------------------------------------------------------------- KeyscanMOVLW h'7F' ;0111 1111b第四列MOVWF outputMOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPNZ ;判断有无按键(即W是否为0,为0则跳)GOTO KeyS1CALL Delay10ms ;消抖MOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmpMOVLW H'0F'XORWF keytmp,WSKPNZ ;判断w是否为0GOTO KeyN ;误操作KeyS0_0MOVF output,WANDLW H'0F'MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPZ ;松手检测(是否io口变回了高电平)GOTO KeyS0_0MOVLW H'03'MOVWF colMOVF keytmp,WMOVWF keyGOTO KeyNKeyS1MOVLW h'0BF' ;1011 1111b第3列MOVWF outputMOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPNZ ;判断有无按键GOTO KeyS2CALL Delay10ms ;消抖MOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmpXORWF keytmp,WSKPNZ ;判断w是否为0GOTO KeyN ;误操作KeyS1_0MOVF output,WANDLW H'0F'MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPZGOTO KeyS1_0MOVLW H'02'MOVWF colMOVF keytmp,WMOVWF keyGOTO KeyNKeyS2MOVLW h'0DF' ;1011 1111bMOVWF outputMOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPNZ ;判断有无按键GOTO KeyS3CALL Delay10ms ;消抖MOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmpMOVLW H'0F'XORWF keytmp,WSKPNZ ;判断w是否为0GOTO KeyN ;误操作KeyS2_0MOVF output,WANDLW H'0F'MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPZGOTO KeyS2_0MOVLW H'01'MOVF keytmp,WMOVWF keyGOTO KeyNKeyS3MOVLW h'0EF' ;1011 1111b第1列MOVWF outputMOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPNZ ;判断有无按键GOTO KeyNCALL Delay10ms ;消抖MOVF output,wANDLW H'0F' ;将高位制0MOVWF keytmpMOVLW H'0F'XORWF keytmp,WSKPNZ ;判断w是否为0GOTO KeyN ;误操作KeyS3_0MOVF output,WANDLW H'0F'MOVWF keytmp1MOVLW H'0F'XORWF keytmp1,WSKPZGOTO KeyS3_0MOVLW H'00'MOVWF colMOVF keytmp,WMOVWF keyKeyNRETURN;-----------------去抖延时----------------------------------------------- ;功能:10ms延时;------------------------------------------------------------------------ Delay10msmovlw h'01'movwf condy0Del1movlw h'0f0'movwf condy1Del0decfSZ condy1,fgoto Del0decfsz condy0,fgoto Del1RETLW 0;===================================================================== ======END结束语MPLAB编程一定要注意书写格式,很多错误它都不能检测如MOVWF和MOVFW,MPLAB都能编译成功。