📄 getkey.lst
字号:
__start:
__text_start:
002A E5CF LDI R28,0x5F
002B E0D4 LDI R29,4
002C BFCD OUT 0x3D,R28
002D BFDE OUT 0x3E,R29
002E 51C0 SUBI R28,0x10
002F 40D0 SBCI R29,0
0030 EA0A LDI R16,0xAA
0031 8308 STD Y+0,R16
0032 2400 CLR R0
0033 E6E0 LDI R30,0x60
0034 E0F0 LDI R31,0
0035 E010 LDI R17,0
0036 36E0 CPI R30,0x60
0037 07F1 CPC R31,R17
0038 F011 BEQ 0x003B
0039 9201 ST R0,Z+
003A CFFB RJMP 0x0036
003B 8300 STD Z+0,R16
003C E5E4 LDI R30,0x54
003D E0F0 LDI R31,0
003E E6A0 LDI R26,0x60
003F E0B0 LDI R27,0
0040 E010 LDI R17,0
0041 35E4 CPI R30,0x54
0042 07F1 CPC R31,R17
0043 F021 BEQ 0x0048
0044 95C8 LPM
0045 9631 ADIW R30,1
0046 920D ST R0,X+
0047 CFF9 RJMP 0x0041
0048 940E004B CALL _main
_exit:
004A CFFF RJMP _exit
FILE: E:\MYDOCU~1\ICCAVR_Directory\4x4keys\getkey.c
(0001) /*--------------------------------------------------------------------------------
(0002) **工程名称:键盘扫描测试程序
(0003) **编译器:ICCAVR6.31A pro
(0004) **日期:2005.04.14
(0005) **作者:neutronlmk
(0006)
(0007) **芯片类型:M16
(0008) **时钟频率:外接4M
(0009)
(0010) ---------------------------------------------------------------------------------*/
(0011) #include <iom16v.h>
(0012) #include <macros.h>
(0013)
(0014) #define led_port PORTA
(0015) #define led_port_ddr DDRA
(0016) #define key_port PORTD
(0017) #define key_port_ddr DDRD
(0018) #define key_port_pin PIND
(0019)
(0020) /*------------------------------------函数声明----------------------------------*/
(0021) signed char get_key(void);
(0022) void delay_1us(void);
(0023) void delay_nus(unsigned int n);
(0024) void delay_1ms(void);
(0025) void delay_nms(unsigned int n);
(0026)
(0027) /*----------------------------------主函数--------------------------------------*/
(0028) void main(void)
(0029) {
(0030) //端口初始化
(0031) led_port_ddr=0xff;
_main:
key --> R22
004B EF8F LDI R24,0xFF
004C BB8A OUT 0x1A,R24
(0032) led_port=0x00;
004D 2422 CLR R2
004E BA2B OUT 0x1B,R2
(0033) key_port_ddr=0xf0;
004F EF80 LDI R24,0xF0
0050 BB81 OUT 0x11,R24
(0034) key_port=0xf0;
0051 BB82 OUT 0x12,R24
0052 C05C RJMP 0x00AF
(0035)
(0036) //死循环,获取键值,并在发光二极管上提示
(0037) while(1)
(0038) {
(0039) signed char key;
(0040) key=get_key();
0053 D05D RCALL _get_key
0054 2F60 MOV R22,R16
(0041) if(key!=0xff)
0055 3F0F CPI R16,0xFF
0056 F409 BNE 0x0058
0057 C057 RJMP 0x00AF
(0042) {
(0043) switch(key)
0058 2F46 MOV R20,R22
0059 2755 CLR R21
005A FD47 SBRC R20,7
005B 9550 COM R21
005C 3040 CPI R20,0
005D 0745 CPC R20,R21
005E F169 BEQ 0x008C
005F 3041 CPI R20,1
0060 E0E0 LDI R30,0
0061 075E CPC R21,R30
0062 F161 BEQ 0x008F
0063 3042 CPI R20,2
0064 E0E0 LDI R30,0
0065 075E CPC R21,R30
0066 F159 BEQ 0x0092
0067 3043 CPI R20,3
0068 E0E0 LDI R30,0
0069 075E CPC R21,R30
006A F151 BEQ 0x0095
006B 3044 CPI R20,4
006C E0E0 LDI R30,0
006D 075E CPC R21,R30
006E F149 BEQ 0x0098
006F 3045 CPI R20,5
0070 E0E0 LDI R30,0
0071 075E CPC R21,R30
0072 F141 BEQ 0x009B
0073 3046 CPI R20,6
0074 E0E0 LDI R30,0
0075 075E CPC R21,R30
0076 F139 BEQ 0x009E
0077 3047 CPI R20,7
0078 E0E0 LDI R30,0
0079 075E CPC R21,R30
007A F131 BEQ 0x00A1
007B 3048 CPI R20,0x8
007C E0E0 LDI R30,0
007D 075E CPC R21,R30
007E F129 BEQ 0x00A4
007F 3049 CPI R20,0x9
0080 E0E0 LDI R30,0
0081 075E CPC R21,R30
0082 F121 BEQ 0x00A7
0083 304A CPI R20,0xA
0084 E0E0 LDI R30,0
0085 075E CPC R21,R30
0086 F119 BEQ 0x00AA
0087 304B CPI R20,0xB
0088 E0E0 LDI R30,0
0089 075E CPC R21,R30
008A F111 BEQ 0x00AD
008B C023 RJMP 0x00AF
(0044) {
(0045) case 0:led_port=0x01;break;
008C E081 LDI R24,1
008D BB8B OUT 0x1B,R24
008E C020 RJMP 0x00AF
(0046) case 1:led_port=0x02;break;
008F E082 LDI R24,2
0090 BB8B OUT 0x1B,R24
0091 C01D RJMP 0x00AF
(0047) case 2:led_port=0x04;break;
0092 E084 LDI R24,4
0093 BB8B OUT 0x1B,R24
0094 C01A RJMP 0x00AF
(0048) case 3:led_port=0x08;break;
0095 E088 LDI R24,0x8
0096 BB8B OUT 0x1B,R24
0097 C017 RJMP 0x00AF
(0049) case 4:led_port=0x10;break;
0098 E180 LDI R24,0x10
0099 BB8B OUT 0x1B,R24
009A C014 RJMP 0x00AF
(0050) case 5:led_port=0x20;break;
009B E280 LDI R24,0x20
009C BB8B OUT 0x1B,R24
009D C011 RJMP 0x00AF
(0051) case 6:led_port=0x40;break;
009E E480 LDI R24,0x40
009F BB8B OUT 0x1B,R24
00A0 C00E RJMP 0x00AF
(0052) case 7:led_port=0x80;break;
00A1 E880 LDI R24,0x80
00A2 BB8B OUT 0x1B,R24
00A3 C00B RJMP 0x00AF
(0053) case 8:led_port=0x03;break;
00A4 E083 LDI R24,3
00A5 BB8B OUT 0x1B,R24
00A6 C008 RJMP 0x00AF
(0054) case 9:led_port=0x06;break;
00A7 E086 LDI R24,6
00A8 BB8B OUT 0x1B,R24
00A9 C005 RJMP 0x00AF
(0055) case 10:led_port=0x0c;break;
00AA E08C LDI R24,0xC
00AB BB8B OUT 0x1B,R24
00AC C002 RJMP 0x00AF
(0056) case 11:led_port=0x18;break;
00AD E188 LDI R24,0x18
00AE BB8B OUT 0x1B,R24
00AF CFA3 RJMP 0x0053
00B0 9508 RET
_get_key:
i --> R22
tem --> R10
00B1 940E0150 CALL push_gset3
(0057) default:break;
(0058) }
(0059) }
(0060) }
(0061) }
(0062)
(0063) /*----------------------------------------------获取按键函数---------------------------------*/
(0064) //获取键值函数,返回0~11号按键,无按键按下则返回0xff
(0065) signed char get_key(void)
(0066) {
(0067) unsigned char i,tem;
(0068) key_port_ddr=0x0f;//使能键盘口高四位的上拉电阻
00B3 E08F LDI R24,0xF
00B4 BB81 OUT 0x11,R24
(0069) key_port=0xff;
00B5 EF8F LDI R24,0xFF
00B6 BB82 OUT 0x12,R24
(0070) for(i=0;i<3;i++)//若4*4键盘,这里应为i<4,因为现在PD3悬空,PD3没电平变化,所以你改i<4也不会出错^__^
00B7 2766 CLR R22
00B8 C05C RJMP 0x0115
(0071) {
(0072) key_port=~(1<<i);//键盘线扫描,从PD0~PD2逐位电位变低
00B9 E001 LDI R16,1
00BA 2F16 MOV R17,R22
00BB 940E016B CALL lsl8
00BD 2E20 MOV R2,R16
00BE 9420 COM R2
00BF BA22 OUT 0x12,R2
(0073) delay_nus(100);//延时等待电平稳定
00C0 E604 LDI R16,0x64
00C1 E010 LDI R17,0
00C2 D05B RCALL _delay_nus
(0074) tem=key_port_pin&0xf0;//读键盘扫描信号(PD口高四位)状态,屏蔽低四位
00C3 B380 IN R24,0x10
00C4 7F80 ANDI R24,0xF0
00C5 2EA8 MOV R10,R24
(0075) if(tem!=0xf0)//若PD高四位不等于0xf0,则PD高四位引脚有可能被拉低(即有按键按下)
00C6 3F80 CPI R24,0xF0
00C7 F409 BNE 0x00C9
00C8 C049 RJMP 0x0112
(0076) {
(0077) delay_nms(15);//延时消抖动
00C9 E00F LDI R16,0xF
00CA E010 LDI R17,0
00CB D06B RCALL _delay_nms
(0078) tem=key_port_pin&0xf0;//再读键盘
00CC B380 IN R24,0x10
00CD 7F80 ANDI R24,0xF0
00CE 2EA8 MOV R10,R24
(0079) if(tem!=0xf0)//确认按键按下
00CF 3F80 CPI R24,0xF0
00D0 F409 BNE 0x00D2
00D1 C040 RJMP 0x0112
(0080) {
(0081) tem&=0xf0;
00D2 7F80 ANDI R24,0xF0
00D3 2EA8 MOV R10,R24
(0082) switch(tem)//计算键值
00D4 2F48 MOV R20,R24
00D5 2755 CLR R21
00D6 3B40 CPI R20,0xB0
00D7 E0E0 LDI R30,0
00D8 075E CPC R21,R30
00D9 F0F9 BEQ 0x00F9
00DA EB80 LDI R24,0xB0
00DB E090 LDI R25,0
00DC 1784 CP R24,R20
00DD 0795 CPC R25,R21
00DE F02C BLT 0x00E4
00DF 3740 CPI R20,0x70
00E0 E0E0 LDI R30,0
00E1 075E CPC R21,R30
00E2 F071 BEQ 0x00F1
00E3 C02C RJMP 0x0110
00E4 3D40 CPI R20,0xD0
00E5 E0E0 LDI R30,0
00E6 075E CPC R21,R30
00E7 F0C9 BEQ 0x0101
00E8 3D40 CPI R20,0xD0
00E9 E0E0 LDI R30,0
00EA 075E CPC R21,R30
00EB F124 BLT 0x0110
00EC 3E40 CPI R20,0xE0
00ED E0E0 LDI R30,0
00EE 075E CPC R21,R30
00EF F0C9 BEQ 0x0109
00F0 C01F RJMP 0x0110
(0083) {
(0084) case 0x70:tem=15-(3-i)*4;break;//这里可以改tem=11-(2-i)*4,不过一改4*4键就不适用了^___^
00F1 E013 LDI R17,3
00F2 1B16 SUB R17,R22
00F3 E004 LDI R16,4
00F4 0201 MULS R16,R17
00F5 E08F LDI R24,0xF
00F6 2EA8 MOV R10,R24
00F7 18A0 SUB R10,R0
00F8 C017 RJMP 0x0110
(0085) case 0xb0:tem=14-(3-i)*4;break;
00F9 E013 LDI R17,3
00FA 1B16 SUB R17,R22
00FB E004 LDI R16,4
00FC 0201 MULS R16,R17
00FD E08E LDI R24,0xE
00FE 2EA8 MOV R10,R24
00FF 18A0 SUB R10,R0
0100 C00F RJMP 0x0110
(0086) case 0xd0:tem=13-(3-i)*4;break;
0101 E013 LDI R17,3
0102 1B16 SUB R17,R22
0103 E004 LDI R16,4
0104 0201 MULS R16,R17
0105 E08D LDI R24,0xD
0106 2EA8 MOV R10,R24
0107 18A0 SUB R10,R0
0108 C007 RJMP 0x0110
(0087) case 0xe0:tem=12-(3-i)*4;break;
0109 E013 LDI R17,3
010A 1B16 SUB R17,R22
010B E004 LDI R16,4
010C 0201 MULS R16,R17
010D E08C LDI R24,0xC
010E 2EA8 MOV R10,R24
010F 18A0 SUB R10,R0
(0088) default:break;
(0089) }
(0090) return tem;//返回0~11号键
0110 2D0A MOV R16,R10
0111 C007 RJMP 0x0119
(0091) }
(0092) }
(0093) key_port=0xff;
0112 EF8F LDI R24,0xFF
0113 BB82 OUT 0x12,R24
0114 9563 INC R22
0115 3063 CPI R22,3
0116 F408 BCC 0x0118
0117 CFA1 RJMP 0x00B9
(0094) }
(0095) return 0xff;//无按键按下则返回0xff
0118 EF0F LDI R16,0xFF
0119 940E0149 CALL pop_gset3
011B 9508 RET
(0096) }
(0097)
(0098) /*--------------------------------------------延时函数------------------------------------*/
(0099) //1us延时函数
(0100) void delay_1us(void)
(0101) {
(0102) NOP();
_delay_1us:
011C 0000 NOP
011D 9508 RET
_delay_nus:
i --> R20
n --> R22
011E 940E0152 CALL push_gset2
0120 01B8 MOVW R22,R16
(0103) }
(0104)
(0105) //n us 延时函数
(0106) void delay_nus(unsigned int n)
(0107) {
(0108) unsigned int i;
(0109) for(i=0;i<n;i++)delay_1us();
0121 2744 CLR R20
0122 2755 CLR R21
0123 C003 RJMP 0x0127
0124 DFF7 RCALL _delay_1us
0125 5F4F SUBI R20,0xFF
0126 4F5F SBCI R21,0xFF
0127 1746 CP R20,R22
0128 0757 CPC R21,R23
0129 F3D0 BCS 0x0124
012A 940E0146 CALL pop_gset2
012C 9508 RET
(0110) }
(0111)
(0112) //1ms延时函数
(0113) void delay_1ms(void)
(0114) {
(0115) unsigned int i;
(0116) for(i=0;i<600;i++);
_delay_1ms:
i --> R16
012D 2700 CLR R16
012E 2711 CLR R17
012F C002 RJMP 0x0132
0130 5F0F SUBI R16,0xFF
0131 4F1F SBCI R17,0xFF
0132 3508 CPI R16,0x58
0133 E0E2 LDI R30,2
0134 071E CPC R17,R30
0135 F3D0 BCS 0x0130
0136 9508 RET
_delay_nms:
i --> R20
n --> R22
0137 940E0152 CALL push_gset2
0139 01B8 MOVW R22,R16
(0117) }
(0118)
(0119) //n ms延时函数
(0120) void delay_nms(unsigned int n)
(0121) {
(0122) unsigned int i;
(0123) for(i=0;i<n;i++)delay_1ms();
FILE: <library>
013A 2744 CLR R20
013B 2755 CLR R21
013C C003 RJMP 0x0140
013D DFEF RCALL _delay_1ms
013E 5F4F SUBI R20,0xFF
013F 4F5F SBCI R21,0xFF
0140 1746 CP R20,R22
0141 0757 CPC R21,R23
0142 F3D0 BCS 0x013D
0143 940E0146 CALL pop_gset2
0145 9508 RET
pop_gset2:
0146 E0E2 LDI R30,2
0147 940C0158 JMP pop
pop_gset3:
0149 E0E4 LDI R30,4
014A 940C0158 JMP pop
push_gset5:
014C 92FA ST R15,-Y
014D 92EA ST R14,-Y
push_gset4:
014E 92DA ST R13,-Y
014F 92CA ST R12,-Y
push_gset3:
0150 92BA ST R11,-Y
0151 92AA ST R10,-Y
push_gset2:
0152 937A ST R23,-Y
0153 936A ST R22,-Y
push_gset1:
0154 935A ST R21,-Y
0155 934A ST R20,-Y
0156 9508 RET
pop_gset1:
0157 E0E1 LDI R30,1
pop:
0158 9149 LD R20,Y+
0159 9159 LD R21,Y+
015A FDE0 SBRC R30,0
015B 9508 RET
015C 9169 LD R22,Y+
015D 9179 LD R23,Y+
015E FDE1 SBRC R30,1
015F 9508 RET
0160 90A9 LD R10,Y+
0161 90B9 LD R11,Y+
0162 FDE2 SBRC R30,2
0163 9508 RET
0164 90C9 LD R12,Y+
0165 90D9 LD R13,Y+
0166 FDE3 SBRC R30,3
0167 9508 RET
0168 90E9 LD R14,Y+
0169 90F9 LD R15,Y+
016A 9508 RET
lsl8:
016B 2311 TST R17
016C F019 BEQ 0x0170
016D 0F00 LSL R16
016E 951A DEC R17
016F CFFB RJMP lsl8
0170 9508 RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -