1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
| // 矩阵键盘控制LED灯 // 4X4矩阵键盘连到P1口上 // 16个LED灯依次连到P2和P3口上 // IO口作为输入口时,要先给他置1才能接受外接的信号,遇1则1,遇0则0 ORG 00H // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 初始化工作 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* START: // 使LED全灭状态 MOV R1,#0FFH MOV R2,#0FFH MOV P2,R1 MOV P3,R2 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 主循环 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* MAIN_LOOP: MOV A,#0F0H //使低四位(行)为0,高四位(列)为1,同时让列脚处于输入状态 MOV P1,A CALL SCAN_KEYS JMP MAIN_LOOP // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 检测键盘 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* SCAN_KEYS: MOV A,P1 CJNE A,#0F0H,CHECK_KEY //无键被按下时返回,结束此次检测 RET // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 按键处理过程 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* CHECK_KEY: CALL LOCATE_COL CALL DELAY FRESH_STATE: MOV A,P1 // 由于在检测行时,更换了P1的初始值为0FH,所以这里与0FH比较,而不是#0F0H CJNE A,#0FH,FRESH_STATE //去抖,直到键被松开时(相等)执行下面的语句 // 列序号存在R1中,行序号在R2中 CALL SHOW_LED RET // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 定位按钮所在列 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* LOCATE_COL: // 先定位列,根据低四位为零时,找哪一列对应的脚本是零即可 CJNE A,#0E0H,COL_2 //检测是否为第一列 MOV R1,#1 JMP LOCATE_ROW COL_2: CJNE A,#0D0H,COL_3 //检测是否为第二列,若不是跳至检测下一列 MOV R1,#2 JMP LOCATE_ROW COL_3: CJNE A,#0B0H,COL_4 //检测是否为第三列 MOV R1,#3 JMP LOCATE_ROW COL_4: //检测是否为第四列 CJNE A,#70H,RETURN MOV R1,#4 JMP LOCATE_ROW // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 定位按钮所在行 // 使高四位(列)为零,低四位(行)为1,检测低四位中哪个变为了零,即可定位行数 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* LOCATE_ROW: MOV A,#0FH MOV P1,A MOV A,P1 CJNE A,#0EH,ROW_2 MOV R2,#1 RET ROW_2: CJNE A,#0DH,ROW_3 MOV R2,#2 RET ROW_3: CJNE A,#0BH,ROW_4 MOV R2,#3 RET ROW_4: CJNE A,#07H,RETURN MOV R2,#4 RET // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* //显示相应的LED状态 // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* SHOW_LED: // 列序号减1然后乘以4加行序号等于键的序号 MOV A,R1 //刷新灯的状态 SUBB A,#1 MOV B,#4 MUL AB //结果低8位在A里 ADD A,R2 //得到键序号 MOV R3,A // 当键序号为8时,则直接让上面(P2口)8个全亮, 下面8个(P3口)全灭 CJNE A,#8,CAL_LED MOV R1,#00H MOV R2,#0FFH MOV P2,R1 MOV P3,R2 RET CAL_LED: SUBB A,#8 //带借位减法,若有借位则进(借)位标识Cy为1 JNC SET_LED // 分支1:A小于8,减的结果小于0时,则只让P2口亮相应数目的灯,下面P3口全灭 MOV A,R3 MOV R1,A MOV R2,#0FFH MOV P3,R2 MOV A,#0FFH P2_WEI_LED: CLR C RLC A DJNZ R1,P2_WEI_LED MOV P2,A RET SET_LED: // 分支2:键序号大于8时,让P2口的灯全亮,下面P3口亮相应数目(减的结果)的灯 MOV R1,#00H MOV R2,A MOV P2,R1 MOV A,#0FFH P3_WEI_LED: CLR C RLC A DJNZ R2,P3_WEI_LED MOV P3,A RET // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* RETURN: RET // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* // 延时30ms // \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* DELAY: MOV R5,#30 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET END //注:1)模块化编程,Call和RET的配对使用,完成一个子过程,并相互嵌套,完成复杂的任务过程,编写过程也是一步步实现,每实现一步通过仿真测试成功,再做下一步,确保了程序质量。2)深入理解单片机I/O口的输入输出,先置高电位,使该引脚处理接受输入状态,(原理根据期电路结构, 为0时并不能接收到外接电平的)3)代码段SCAN\_KEYS:理解矩形键盘的扫描过程,先给P1口赋值为# 0F0H,即低四位(行)为0,高四位为1,然后不断地读取P1口的值,若值仍保持原值#0F0H,则说明没有键被按下,若值发生变化,则进一步判断高四位中哪个变为低电平,则对应的列中的键被按下,即找到列序号,依据同样的道理,此时让低四位为1,高四位为0,然后看低四位中哪一个变为0,即确定行数,有了行序号和列序号即可确定键的序号,进而通过LED灯的状态来点亮相应数目的灯(此过程中又涉及减法及移位实现对应数目的灯变亮)4)代码段SHOW\_LED:实现了键序号到灯个数的转换,涉及了SUBB,RLC等操作。5)代码段CHECK\_KEY:检测键和去抖过程的结合,先执行定位键,然后再延时,直到键被松开。
|