📄 ps2_kb.lst
字号:
0172 DFDA RCALL _LCD1602_sendbyte
(0089) Delayms(2);// 清屏指令写入后,2ms 的延时是很必要的!!!
0173 E002 LDI R16,2
0174 E010 LDI R17,0
(0090) }
0175 CF7C RJMP _Delayms
_LCD1602_readBF:
busy --> R20
0176 940E02E1 CALL push_gset1
(0091) /*******************************************
(0092) 函数名称: LCD1602_readBF
(0093) 功 能: 1602液晶清屏
(0094) 参 数: 无
(0095) 返回值 : busy--为1时忙,为0时可以接收指令
(0096) /********************************************/
(0097) uchar LCD1602_readBF(void)
(0098) {
(0099) uchar busy;
(0100) busy=LCD1602_readbyte(iCmd); //读回BF标志和地址
0178 2700 CLR R16
0179 DFBB RCALL _LCD1602_readbyte
017A 2F40 MOV R20,R16
(0101) if(busy&0x80) //忙
017B FF07 SBRS R16,7
017C C002 RJMP 0x017F
(0102) busy=1;
017D E041 LDI R20,1
017E C001 RJMP 0x0180
(0103) else //不忙,可以写入
(0104) busy=0;
017F 2744 CLR R20
(0105) return busy;
0180 2F04 MOV R16,R20
0181 940E02E4 CALL pop_gset1
0183 9508 RET
_LCD1602_gotoXY:
Col --> R20
Row --> R22
0184 940E02F8 CALL push_gset2
0186 2F42 MOV R20,R18
0187 2F60 MOV R22,R16
(0106) }
(0107) /*******************************************
(0108) 函数名称: LCD1602_gotoXY
(0109) 功 能: 移动到指定位置
(0110) 参 数: Row--指定的行
(0111) Col--指定的列
(0112) 返回值 : 无
(0113) /********************************************/
(0114) void LCD1602_gotoXY(uchar Row, uchar Col)
(0115) {
(0116) switch (Row) //选择行
0188 2777 CLR R23
0189 3062 CPI R22,2
018A E0E0 LDI R30,0
018B 077E CPC R23,R30
018C F009 BEQ 0x018E
018D C005 RJMP 0x0193
(0117) {
(0118) case 2:
(0119) LCD1602_sendbyte(iCmd, LCDa_L2 + Col); break; //写入第2行的指定列
018E 2F24 MOV R18,R20
018F 5420 SUBI R18,0x40
0190 2700 CLR R16
0191 DFBB RCALL _LCD1602_sendbyte
0192 C004 RJMP 0x0197
(0120) default:
(0121) LCD1602_sendbyte(iCmd, LCDa_L1 + Col); break; //写入第1行的指定列
0193 2F24 MOV R18,R20
0194 5820 SUBI R18,0x80
0195 2700 CLR R16
0196 DFB6 RCALL _LCD1602_sendbyte
(0122) }
(0123) }
0197 940E02FC CALL pop_gset2
0199 9508 RET
(0124) /*******************************************
(0125) 函数名称: LCD1602_initial
(0126) 功 能: 1602液晶初始化
(0127) 参 数: 无
(0128) 返回值 : 无
(0129) /********************************************/
(0130) void LCD1602_initial(void)
(0131) {
(0132) Delayms(100); // 等待内部复位
_LCD1602_initial:
019A E604 LDI R16,0x64
019B E010 LDI R17,0
019C DF55 RCALL _Delayms
(0133) LCD1602_portini(); //端口初始化
019D DF90 RCALL _LCD1602_portini
(0134)
(0135) LCD1602_sendbyte(iCmd, LCDa_FUNCTION); // 功能、模式设定
019E E328 LDI R18,0x38
019F 2700 CLR R16
01A0 DFAC RCALL _LCD1602_sendbyte
(0136) while(LCD1602_readBF());
01A1 DFD4 RCALL _LCD1602_readBF
01A2 2300 TST R16
01A3 F7E9 BNE 0x01A1
(0137) LCD1602_sendbyte(iCmd, LCDa_ON); //打开显示
01A4 E02C LDI R18,0xC
01A5 2700 CLR R16
01A6 DFA6 RCALL _LCD1602_sendbyte
(0138) while(LCD1602_readBF());
01A7 DFCE RCALL _LCD1602_readBF
01A8 2300 TST R16
01A9 F7E9 BNE 0x01A7
(0139) LCD1602_clear(); //清屏
01AA DFC5 RCALL _LCD1602_clear
(0140) while(LCD1602_readBF());
01AB DFCA RCALL _LCD1602_readBF
01AC 2300 TST R16
01AD F7E9 BNE 0x01AB
(0141) LCD1602_sendbyte(iCmd, LCDa_ENTRY); // 输入模式设定
01AE E026 LDI R18,6
01AF 2700 CLR R16
(0142) } 01B0 CF9C RJMP _LCD1602_sendbyte
FILE: C:\icc\examples.avr\AVR_PQ1A_DEMO\19_PS2\PS2_KB.C
(0001) /*******************************************
(0002) 文件:PS2_KB.C
(0003) 环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
(0004) 硬件:ATMEGA16芯片
(0005) 日期:2006年12月10日
(0006) 功能:驱动开发板上的PS2接口,实现PS2键盘(支持第2套扫描码)
(0007) 备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)
(0008) /******************************************/
(0009) #include <iom16v.h> //包含型号头文件
(0010) #include <macros.h> //包含"位"操作头文件
(0011) #include <stdio.h> //标准输入输出头文件
(0012) #include <AVR_PQ1A.h> //包含自定义常量头文件
(0013) #include "YJ1602.C"
(0014)
(0015) #pragma interrupt_handler Int0:2 //外部中断0中断函数声明
(0016) #pragma data:code //将译码表放在FLASH
(0017) const uchar unshifted[][2]= //shift键没按下译码表
(0018) {
(0019) 0x0e,'`',
(0020) 0x15,'q',
(0021) 0x16,'1',
(0022) 0x1a,'z',
(0023) 0x1b,'s',
(0024) 0x1c,'a',
(0025) 0x1d,'w',
(0026) 0x1e,'2',
(0027) 0x21,'c',
(0028) 0x22,'x',
(0029) 0x23,'d',
(0030) 0x24,'e',
(0031) 0x25,'4',
(0032) 0x26,'3',
(0033) 0x29,' ',
(0034) 0x2a,'v',
(0035) 0x2b,'f',
(0036) 0x2c,'t',
(0037) 0x2d,'r',
(0038) 0x2e,'5',
(0039) 0x31,'n',
(0040) 0x32,'b',
(0041) 0x33,'h',
(0042) 0x34,'g',
(0043) 0x35,'y',
(0044) 0x36,'6',
(0045) 0x39,',',
(0046) 0x3a,'m',
(0047) 0x3b,'j',
(0048) 0x3c,'u',
(0049) 0x3d,'7',
(0050) 0x3e,'8',
(0051) 0x41,',',
(0052) 0x42,'k',
(0053) 0x43,'i',
(0054) 0x44,'o',
(0055) 0x45,'0',
(0056) 0x46,'9',
(0057) 0x49,'.',
(0058) 0x4a,'/',
(0059) 0x4b,'l',
(0060) 0x4c,';',
(0061) 0x4d,'p',
(0062) 0x4e,'-',
(0063) 0x52,'\'',
(0064) 0x54,'[',
(0065) 0x55,'=',
(0066) 0x5b,']',
(0067) 0x5d,'\\',
(0068) 0x61,'<',
(0069) 0x69,'1',
(0070) 0x6b,'4',
(0071) 0x6c,'7',
(0072) 0x70,'0',
(0073) 0x71,'.',
(0074) 0x72,'2',
(0075) 0x73,'5',
(0076) 0x74,'6',
(0077) 0x75,'8',
(0078) 0x79,'+',
(0079) 0x7a,'3',
(0080) 0x7b,'-',
(0081) 0x7c,'*',
(0082) 0x7d,'9',
(0083) 0,0
(0084) };
(0085) const uchar shifted[][2]= //shift键按下译码表
(0086) {
(0087) 0x0e,'~',
(0088) 0x15,'Q',
(0089) 0x16,'!',
(0090) 0x1a,'Z',
(0091) 0x1b,'S',
(0092) 0x1c,'A',
(0093) 0x1d,'W',
(0094) 0x1e,'@',
(0095) 0x21,'C',
(0096) 0x22,'X',
(0097) 0x23,'D',
(0098) 0x24,'E',
(0099) 0x25,'$',
(0100) 0x26,'#',
(0101) 0x29,' ',
(0102) 0x2a,'V',
(0103) 0x2b,'F',
(0104) 0x2c,'T',
(0105) 0x2d,'R',
(0106) 0x2e,'%',
(0107) 0x31,'N',
(0108) 0x32,'B',
(0109) 0x33,'H',
(0110) 0x34,'G',
(0111) 0x35,'Y',
(0112) 0x36,'^',
(0113) 0x39,'L',
(0114) 0x3a,'M',
(0115) 0x3b,'J',
(0116) 0x3c,'U',
(0117) 0x3d,'&',
(0118) 0x3e,'*',
(0119) 0x41,'<',
(0120) 0x42,'K',
(0121) 0x43,'I',
(0122) 0x44,'O',
(0123) 0x45,')',
(0124) 0x46,'(',
(0125) 0x49,'>',
(0126) 0x4a,'?',
(0127) 0x4b,'L',
(0128) 0x4c,':',
(0129) 0x4d,'P',
(0130) 0x4e,'_',
(0131) 0x52,'"',
(0132) 0x54,'{',
(0133) 0x55,'+',
(0134) 0x5b,'}',
(0135) 0x5d,'|',
(0136) 0x61,'>',
(0137) 0x69,'1',
(0138) 0x6b,'4',
(0139) 0x6c,'7',
(0140) 0x70,'0',
(0141) 0x71,'.',
(0142) 0x72,'2',
(0143) 0x73,'5',
(0144) 0x74,'6',
(0145) 0x75,'8',
(0146) 0x79,'+',
(0147) 0x7a,'3',
(0148) 0x7b,'-',
(0149) 0x7c,'*',
(0150) 0x7d,'9',
(0151) 0,0
(0152) };
(0153) #pragma data:data //将以后的变量放在RAM
(0154) void Decode(uchar scancode);//声明函数原型
(0155) uchar edge, bitcount,ascii=' '; //edge为0下降沿中断,为1上升沿中断
(0156) //bitcount为位计数值
(0157) //ascii为翻译后的ASCII码,初值为空格
(0158)
(0159) /*******************************************
(0160) 函数名称: Init_kb
(0161) 功 能: 初始化PS2函数
(0162) 参 数: 无
(0163) 返回值 : 无
(0164) /********************************************/
(0165) void Init_kb(void)
(0166) {
(0167) MCUCR = 2; //设置INT0为下降沿触发中断
_Init_kb:
01B1 E082 LDI R24,2
01B2 BF85 OUT P35,R24
(0168) edge = 0; //0为下降沿中断标志,1为上升沿中断标志
01B3 2422 CLR R2
01B4 92200070 STS R2,_edge
(0169) bitcount = 11; //每次11位数据,一个起始位(0),8个数据位,一个奇偶校验位,一个停止位(1)
01B6 E08B LDI R24,0xB
01B7 9380006F STS R24,_bitcount
(0170) DDRD&=~BIT(PD2); //配置中断管脚为输入
01B9 988A CBI P11,2
(0171) PORTD|=BIT(PD2); //使能中断管脚的上拉
01BA 9A92 SBI P12,2
(0172) DDRA&=~BIT(PA0); //配置键盘数据输入口为输入
01BB 98D0 CBI P1A,0
(0173) PORTA|=BIT(PA0); //使能数据输入管脚的上拉
01BC 9AD8 SBI P1B,0
(0174) SREG|=BIT(GLOBAL);//打开全局中断
01BD 9478 BSET 7
(0175) GICR|=BIT(EXTINT0);
01BE B78B IN R24,P3B
01BF 6480 ORI R24,0x40
01C0 BF8B OUT P3B,R24
(0176) }
01C1 9508 RET
_Disp_ascii:
ascii --> R20
01C2 940E02E1 CALL push_gset1
01C4 2F40 MOV R20,R16
(0177) /*******************************************
(0178) 函数名称: Disp_ascii
(0179) 功 能: 在1602液晶上显示键盘上的ASCII码
(0180) 参 数: ascii--将要显示的ASCII码
(0181) 返回值 : 无
(0182) /********************************************/
(0183) void Disp_ascii(uchar ascii)
(0184) {
(0185) LCD1602_gotoXY(1,2);
01C5 E022 LDI R18,2
01C6 E001 LDI R16,1
01C7 DFBC RCALL _LCD1602_gotoXY
(0186) LCD1602_sendstr("KEY_ASCII:");
01C8 E603 LDI R16,0x63
01C9 E010 LDI R17,0
01CA DF95 RCALL _LCD1602_sendstr
(0187) LCD1602_sendbyte(iDat,ascii);
01CB 2F24 MOV R18,R20
01CC E001 LDI R16,1
01CD DF7F RCALL _LCD1602_sendbyte
(0188) }
01CE 940E02E4 CALL pop_gset1
01D0 9508 RET
_Int0:
01D1 940E02B3 CALL push_lset
(0189) /*******************************************
(0190) 函数名称: Int0
(0191) 功 能: 外部中断0的中断服务函数,上升沿中断读入11位数据,下降沿调用解码程序
(0192) 参 数: 无
(0193) 返回值 : 无
(0194) /********************************************/
(0195) void Int0(void)
(0196) {
(0197) static uchar data; // 声明局部静态变量来保存扫描码
(0198) if (!edge) // 如果是下降沿触发中断
01D3 90200070 LDS R2,_edge
01D5 2022 TST R2
01D6 F4D1 BNE 0x01F1
(0199) {
(0200) if(bitcount < 11 && bitcount > 2) //3到10位是数据,起始位,校验位和停止位忽略
01D7 9180006F LDS R24,_bitcount
01D9 308B CPI R24,0xB
01DA F480 BCC 0x01EB
01DB E082 LDI R24,2
01DC 9020006F LDS R2,_bitcount
01DE 1582 CP R24,R2
01DF F458 BCC 0x01EB
(0201) {
(0202) data = (data >> 1); //右移保存数据
01E0 9020006E LDS R2,0x6E
01E2 9426 LSR R2
01E3 9220006E STS R2,0x6E
(0203) if(PINA&0x01)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -