标题:
我想用4乘4矩阵键盘,LCD1602,蜂鸣器实现单片机电子琴但是中断有问题麻烦大家看看
[打印本页]
作者:
zzzzzzzzlhv
时间:
2022-5-17 16:26
标题:
我想用4乘4矩阵键盘,LCD1602,蜂鸣器实现单片机电子琴但是中断有问题麻烦大家看看
RS EQU P2^6
RW EQU P2^5
E EQU P2^7
LCD EQU P0
BF EQU P0^7
ORG 0000H
LJMP INIT
ORG 000BH
LJMP MAIN
ORG 0060H
;初始化
INIT:
CLR P2^7// 使能清0
MOV R0,#0
MOV R1,#0
MOV R0,#38H //设置16乘2显示,5乘7点阵,8位数据接口
ACALL WRITE_COM
MOV R0,#0
MOV R0,#0CH //设置开显示,不显示光标
ACALL WRITE_COM
MOV R0,#0
MOV R0,#06H // 写一个字符后地址指针加1
ACALL WRITE_COM
MOV R0,#0
MOV R0,#01H //显示清0,数据指针清0
ACALL WRITE_COM
RET
;写指令函数,调用前先把指令码放到R0中
DELAY:
MOV R6,#5
W2:MOV R7,#239
W1:DJNZ R7,W1
DJNZ R6,W2
RET
WRITE_COM:
CLR P2^6//RS清0
MOV P0,R0 //R0中放指令代码
ACALL DELAY
SETB P2^7//使能置1
ACALL DELAY
CLR P2^7
RET
;写数据函数,调用前先把指令放到R1中
WRITE_DATA:
SETB P2^6
MOV P0,R1
ACALL DELAY
SETB P2^7
ACALL DELAY
CLR P2^7
RET
MAIN:MOV SP,#70H
MOV TMOD,#11H //定时器初始化
SETB EA
SETB ET0
MOV DPTR,#TAB
CLR A
ACALL INIT
MOV R0,#80H//定位到第一行
ACALL WRITE_COM
ACALL DELAY
ACALL KEYSCAN
JMP $
;线反转法找被按下的键
KEYSCAN:
MOV P1,#0F0H //给P1赋值,为了读列线
MOV A,P1 //此时按键的状态
ANL A,#0F0H //与
// 找出被按下的列线
JNZ DELAY10MS
DELAY10MS: ;误差 0us
MOV R7,#01H
DL1:
MOV R6,#26H
DL0:
MOV R5,#82H
DJNZ R5,$
DJNZ R6,DL0
DJNZ R7,DL1
RET //延时去抖
MOV A,P1
ANL A, #0F0H
MOV R0,A //此时列线状态记录在R0
JNZ KEYSCAN1
LJMP KEYSCAN
KEYSCAN1:
MOV A,#00H //清零
MOV P1,#0FH //置位读行线
MOV A ,P1 //此时按键的状态
ANL A ,#0FH
MOV R1,A //此时行线状态记录在R1
ANL A ,#0FH
JNZ NUM
LJMP KEYSCAN
NUM:
MOV A ,R0
MOV B,R1
ORL A,B//A或上B,数据保存在A
SJMP DISP0
DISP0:
CJNE A,#0EEH,DISP1
MOV A ,#01H
MOVC A ,@A+DPTR
MOV P0,A//LCD1602显示屏输出音律
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#22H
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP1:
CJNE A ,#0EDH,DISP2
MOV A ,#02H
MOVC A,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#4FH
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP2:
CJNE A ,#0EBH,DISP3
MOV A ,#03H
MOVC A ,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#85H
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP3:
CJNE A,#0E7H,DISP4
MOV A,#04H
MOVC A ,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#9AH
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP4:
CJNE A,#0DEH,DISP5
MOV A, #05H
MOVC A ,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#0C1H
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP5:
CJNE A,#0DDH,DISP6
MOV A ,#06H
MOVC A ,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#0E4H
MOV TH0,#0FEH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DISP6:
CJNE A,#0DBH,KEY
MOV A ,#07H
MOVC A ,@A+DPTR
MOV P0,A
ACALL WRITE_DATA
ACALL DELAY
MOV TL0,#03H
MOV TH0,#0FFH
LCALL DELAY1
LCALL SOUND
LJMP KEYSCAN
DELAY1:MOV R2,#0FH
LOOP10:MOV R3,0FAH
LOOP20:DJNZ R3,LOOP20
DJNZ R2,LOOP10
RET
SOUND:
SETB TR0
SETB P3^0 //输出高电平,开始鸣叫
MOV R4,#4H
LOOP:MOV R3,#0F9H
LOOP1: DJNZ R3,LOOP1
DJNZ R4,LOOP
CLR P3^0 //输出低电平,停止鸣叫
RETI
KEY:LJMP MAIN
TAB:DB 31H,32H,33H,34H,35H,36H,37H
END
复制代码
作者:
188610329
时间:
2022-5-18 00:07
ORG 0000H
LJMP INIT
ORG 000BH
LJMP MAIN
开头看了这4行,我就有不祥的预感……
再往下一核对……,稍微找了一下。
MAIN:MOV SP,#70H
MOV TMOD,#11H //定时器初始化
SETB EA
SETB ET0
MOV DPTR,#TAB
CLR A
ACALL INIT
MOV R0,#80H//定位到第一行
ACALL WRITE_COM
ACALL DELAY
ACALL KEYSCAN
JMP $
看到这里,我确定了,这代码不用看了。 你如果不是疏忽,就不要学汇编了。汇编不适合你。
难怪没人回复,我也不知道怎么回复了,改用 C 吧,或者汇编从最基本的开始重新回炉学吧……
作者:
yzwzfyz
时间:
2022-5-18 17:28
1、先画出逻辑框图,走通框图后,再写程序。
2、搞清楚各中断入口地址。
问题1:
程序开始后,直接转入INIT,INIT的未句是 RET,执行RET时,程序就跑飞了。
RET 指令是从SP所指的位置中取运行地址。开机时SP=07,即RET的返回地址在[07H][06H]中,
这时你的[07H][06H]中放的是什么里?没有给出,很随机,所以程序飞了。
即使侥幸放的是0000,返回0000运行,又会执行到RET,而这时SP已于上次RET时-2了,即SP=05,于是又从[05H][06H]中,取地址运行,如此下去必跑飞,死机。
问题2:
不要用DELAY,它占用CPU的时间!在DELAY时CPU不能干其它活。
……
作者:
lyonkon
时间:
2022-5-20 23:32
我觉得程序写的很好,写程序是为了达到创意。程序格式是有点问题,不用气馁慢慢修改渐渐就会了。org0000h ljmp main 意思是程序开始后跳转到主程序 org 000bh ljmp init 意思是如果t0溢出则跳转到init子程序,org 0060h 意思是程序从60h开始写。中断子程序init 返回不用ret
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1