微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 单片机 电子琴程序,矩阵按键扫描处理

单片机 电子琴程序,矩阵按键扫描处理

时间:10-02 整理:3721RD 点击:
项目要求电子琴程序能够实现8个音符、能播放歌曲,并且液晶屏显示操作的信息(按音符键液晶显示,按歌曲键则液晶屏显示歌词),还能变调,比如中1变为高1,这样
目前的话,网上找到一个独立按键的,修改之后适合在我板子上仅仅4个独立按键。前3个播放音符,后1个播放歌曲。这程序歌曲显示歌词,音符不显示操作信息
程序如下:(有部分程序因为不涉及,所以修改的时候没删去)主要关键在于中间键盘部分
RS BIT P2.4 ;定义液晶显示端口标号
      RW BIT P2.5
      E BIT  P2.6
;********************************************
           T0TH EQU 24H   ;T0两个暂存变量
           T0TL EQU 23H
       ORG 0000H
       LJMP INITION
       ORG 000BH
       LJMP T0INT
       ORG 0100H
;********************************************
;*************************液晶初始化******************
INITION:
MOV SP,#70H   
MOV P0,#01H  ;清屏
CALL ENABLE
MOV P0,#38H  ;8位,2行显示
CALL ENABLE
MOV P0,#0CH  ;屏显on,关光标  
CALL ENABLE
MOV P0,#06H  ;计数地址加1,自动右移
CALL ENABLE
;******************************************
;开机提示
;******************************************
MOV P0,#80H
CALL ENABLE
MOV DPTR,#TABLE0    ;写数据的第一行
CALL WRITE1
MOV P0,#00010000B         ;光标左移两位
CALL ENABLE
MOV P0,#00010000B
CALL ENABLE
CALL DEL0
LJMP MAIN   
;*********************************************写指令
ENABLE:
CLR RS
CLR RW
SETB E
CALL DEL0
CLR E
RET
;**********************************************写数据
WRITE1:
MOV R1,#00H                  ;查表程序,从表头到表尾
A1:
MOV A,R1
MOVC A,@A+DPTR
CALL WRITE2
INC R1
CJNE A,#00H,A1   ;未到字符串末尾继续
RET
WRITE2:
MOV P0,A          ;直接将数据写入液晶屏
SETB RS
CLR RW
SETB E
CALL DEL0
CLR E
RET
DEL0:MOV R4,#020H
C0:MOV R5,#020H
C1:   DJNZ R5,C1
   DJNZ R4,C0
   RET
;******************************************
TABLE0:DB 'WELCOM HERE',00H
;*************************内存初始化******************
INITIAL:      
MOV R3,#08H
MOV R0,#30H
M1:
MOV @R0,#00H
INC R0
DJNZ R3,M1         
RET
;*************************选择按键播放八个音调******************
MAIN:  MOV SP,#80H                     ;初始化堆栈
           MOV TMOD,#11H               ;定时器0工作方式0,定时器1工作
           SETB EA
       SETB ET0                        ;计数器0允许
       SETB ET1                        ;计数器1允许
START: SETB P1.0                                        ;关蜂鸣器
       CLR TR0                         ;定时器不允许
SCAN:                                  ;键盘扫描
       MOV A,P3                        
       CJNE A,#0FFH,SU_KEY                 ;判断键盘按下,跳到SU_KEY,若
       NOP
       LJMP SCAN
SU_KEY:
SU_KEY1:               
       JB P3.0,SU_KEY2      ;如果不是第1个键按下,转
       MOV DPH,#0FCH
           MOV DPL,#44H
       SJMP PLAY
SU_KEY2:       
       JB P3.1,SU_KEY3         ;如果不是第2个键按下,转
       MOV DPH,#0FCH
           MOV DPL,#0ACH
       SJMP PLAY                 
SU_KEY3:               
       JB P3.2,KEY1      ;如果不是第3个键按下,转
       MOV DPH,#0FDH
           MOV DPL,#09H
       SJMP PLAY
                         
PLAY:
       MOV T0TH,DPH         ;存高位字符
       MOV T0TL,DPL         ;存低位字符
           MOV TH0,T0TH
           MOV TL0,T0TL
       SETB TR0                 ;启动定时器0
       MOV R2,#01B                 ;1/4拍
       DJNZ R2,PLAY
           LCALL DELAY
           SJMP JUDGE
JUDGE:
       JB P3.5,START     ;按键未按下,则继续扫描,否则,开始放音乐
;*************************选择按键播放音乐******************
KEY1:
JB P3.3,NEXT_2          ;第一个键(P2.5)按下,放音音乐1
       MOV R2,#00H
       LCALL MODD                      ;歌曲号显示      
           MOV DPTR,#MU_TAB1
       AJMP MUSIC
NEXT_2: LJMP START                          ;返回
MUSIC:
       MOV TMOD,#01H
       MOV IE,#82H                      ;允许T0中断
           MOV R7,#00H
LOOP:
       CLR A
       MOVC A,@A+DPTR                  ;查表取代码
           MOV R1,A                               ;定时器高八位存R1
           INC DPTR
           PUSH DPH                                                   ;保
           PUSH DPL
GECI1:
JB P3.3,TIAOCHU          ;第一个键(P2.5)按下,显示歌词1      
           MOV DPTR,#GE1
       AJMP GECI
TIAOCHU:LJMP START
GECI:  
       LCALL QINGCHU
           MOV P0,#0C0H                                        ;显示的位置   

           CALL ENABLE
XIANSHI1:       MOV A,R7                                 ;查表取音乐汉
       MOVC A,@A+DPTR
       CALL WRITE2
           INC R7
           CJNE A,#00H,XIANSHI1
           MOV P0,#00010000B                                 ;将光标左移一
       CALL ENABLE
           MOV P0,#00010000B                                 ;将光标左移一
       CALL ENABLE
           POP DPL
           POP DPH
           CLR A
           MOVC A,@A+DPTR                      
           MOV R0,A                               ;定时器低八位存R0
           ORL A,R1
           JZ NEXT0                               ;相或结果全0为休止符
           MOV A,R0
           ANL A,R1
           CJNE A,#0FFH,NEXT               ;相与结果为0FFH表示乐曲结束
           MOV P0,#01H                     ;清屏
       CALL ENABLE
           LJMP INITION                            ;从头开始演奏              

NEXT:   MOV T0TH,R1                                ;装定时初值
        MOV TH0,T0TH
        MOV T0TL,R0
                MOV TL0,T0TL
            SETB TR0                        ;启动定时器
            SJMP NEXT1
NEXT0:  CLR TR0                                 ;关闭定时器
NEXT1:  CLR A
       INC DPTR
       MOVC A,@A+DPTR                    ;查延时常数
           MOV R2,A
LOOP1:
       ACALL D200
           DJNZ R2,LOOP1                      ;控制延时次数
           INC DPTR
           AJMP LOOP
D200:   MOV R3,#81H                                      ;延时程序
D200B:  MOV A,#0FFH
D200A:  DEC A
        JNZ D200A
                DEC R3
                CJNE R3,#00H,D200B
                RET
QINGCHU:MOV A,#00100000B
       MOV P0,#0C0H                            ;将第二行的第一位置0
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                        ;将第二行的第二位置0
       MOV P0,#0C1H
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                        ;将第二行的第三位置0
       MOV P0,#0C2H
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                     ;将第二行的第四位置0
       MOV P0,#0C3H
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                         ;将第二行的第五位置0
       MOV P0,#0C4H
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                          ;将第二行的第六位置0
       MOV P0,#0C5H
           LCALL ENABLE
           LCALL WRITE2
           MOV A,#00100000B                          ;将第二行的第七位置0
       MOV P0,#0C6H
           LCALL ENABLE
           LCALL WRITE2                                  ;将第二行的第三位置0
           ;以上等价程序如下
           ;GECI:MOV R3,#00H                ;控制循环次数
           ;QINGCHU:
           ;MOV A,#00100000B                ;置空格
           ;PUSH A
           ;MOV R4,#0C0H                         ;地址
           ;MOV        A,R4
           ;MOV P0,A
           ;POP A
           ;INC R4
           ;DEC R3                                         ;控制循环次数
           ;CJNE R3,#00H,QINGCHU         ;计满十次则执行转移
;***************************************************
;定时器0中断子程序,定时音乐
;***************************************************
T0INT:                                         ;中断服务子程序
                MOV TH0,T0TH
                MOV TL0,T0TL
                CPL P1.0                 ;反相输出,演示音乐
                RETI
;******************************************
;显示     
;******************************************
MODD:  
MOV P0,#8EH
LCALL ENABLE         
MOV A,R2
MOV DPTR,#TABLE12
MOVC A,@A+DPTR
LCALL WRITE2      
RET
TABLE12:DB 31H,32H,33H
GE1: db 'xin',00h,'nian',00h,'hao',00h,'ya',00h,'xin',00h,'nian',00h,'hao',00h,'ya',00h
       db 'zhu',00h,'fu',00h,'da',00h,'jia',00h,'xin',00h,'nian',00h,'hao',00h
GE2: DB 'liang',00H,'zhi',00H,'lao',00H,'hu',00H,'liang',00H,'zhi',00H,'lao',00H,'hu',00H,'pao',00H,'de',00H,'kuai',00H
       DB 'pao',00H,'de',00H,'kuai',00H,'yi',00H,'zhi',00H,'mei',00H,'you',00H,'yan',00H,'jing',00H,'yi',00H,'zhi',00H
           DB 'mei',00H,'you',00H,'er',00h,'duo',00h,'zhen',00h,'qi',00h,'guai',00h,'zhen',00h,'qi',00h,'guai',00h
GE3: DB 'wo',00h,'ai',00h,'bei',00h,'jing',00h,'tian',00h,'an',00h,'men',00h,'tian',00h,'an',00h
;*************************延时子程序******************
DELAY:MOV 30H,#100                       ;延长时间等待,键盘消抖
   D1:MOV R5,#200
   D2:DJNZ R5,D2
      DJNZ 30H,D1
      RET
;*******************新年好******************************
MU_TAB1: DB 0FEH,25H,04H,0FEH,25H,04H
  DB 0FEH,25H,06H,0FDH,80H,06H
  DB 0FEH,84H,04H,0FEH,84H,04H
  DB 0FEH,84H,06H,0FEH,25H,06H
  DB 0FEH,25H,04H,0FEH,84H,04H
  DB 0FEH,0C0H,04H,0FEH,84H,04H
  DB 0FEH,98H,04H,0FEH,84H,04H
  DB 0FEH,57H,06H
  DB 0FFH,0FFH
;*******************两只老虎****************************
MU_TAB2: DB 0FCH,44H,06H,0FCH,0ACH,06H,0FDH,09H,06H,0FCH,44H,06H
  DB 0FCH,44H,06H,0FCH,0ACH,06H,0FDH,09H,06H,0FCH,44H,06H
  DB 0FDH,09H,06H,0FDH,34H,06H,0FDH,0A6H,06H
  DB 0FDH,09H,06H,0FDH,34H,06H,0FDH,0A6H,06H
  DB 0FBH,04H,04H,0FDH,0C8H,04H,0FBH,04H,04H,0FDH,34H,04H
  DB 0FDH,09H,04H,0FCH,44H,04H,0FBH,04H,04H,0FDH,0C8H,04H
  DB 0FBH,04H,04H,0FDH,34H,04H,0FDH,09H,04H,0FCH,44H,04H
  DB 0FCH,44H,06H,0FDH,0A6H,06H,0FCH,44H,06H
  DB 0FCH,44H,06H,0FDH,0A6H,06H,0FCH,44H,06H
  DB 0FFH,0FFH
;*******************我爱北京天安门****************************
MU_TAB3: DB 0FDH,82H,06H,0FEH,22H,04H,0FDH,82H,04H,0FDH,34H,04H
  DB   0FDH,09H,04H,0FCH,0ACH,04H,0FCH,44H,06H
  DB   0FFH,0FFH,0FFH,0FFH
END
目前小编是打算把中间独立键盘部分改成矩阵扫描程序,有两个方向的想法,第一个是矩阵行列状态扫描确定具体是某个按键按下后,给予这个按键响应的子程序播放赋给的音符/歌曲/其他操作信息,第二个方向是矩阵按键行列状态扫描时,比如行扫描,那么在确定哪一行扫描之后,第一二行给予查8个音符表,其他两行给予其他子程序。
首先先求解小编思路对不对 = =个人认为第一种每个按键赋予具体的子程序的话,那么项目要求里的变调就有点难实现了。但是第二种方向,改了好多个代码都不行,TAT
上述独立按键部分修改如下:
;*************************选择按键播放八个音调******************
MAIN:  MOV SP,#80H                     ;初始化堆栈
           MOV TMOD,#11H               ;定时器0工作方式0,定时器1工作方式0
           SETB EA
       SETB ET0                        ;计数器0允许
       SETB ET1                        ;计数器1允许
START: SETB P1.0                                        ;关蜂鸣器
       CLR TR0                         ;定时器不允许
SCAN:                                  ;键盘扫描
       MOV A,P3                        
       CJNE A,#0FFH,KS                 ;判断键盘按下,跳到KS,若未按,继续扫描
       NOP
       LJMP SCAN
KS:
        MOV    DPTR,#7FFFH
     CLR    P3.4
     MOVX   A,@DPTR
     MOV    37H,A
     CPL    A
     JZ     KSK1
     LCALL  DELAY
     MOVX   A,@DPTR
     XRL    A,37H
     JZ     KS1
KSK1:SETB   P3.4
     CLR    P3.5
     MOVX   A,@DPTR
     MOV    37H,A
     CPL    A
     JZ     KSK2
     LCALL   DELAY
     MOVX   A,@DPTR
     XRL    A,37H
     JZ     KS1
KSK2:SETB   P3.5
     CLR    P3.6
         MOVX   A,@DPTR
     MOV    37H,A
     CPL    A
     JZ     KSK3
     LCALL   DELAY
     MOVX   A,@DPTR
     XRL    A,37H
     JZ     KS1
KSK3:SETB   P3.6
     CLR    P3.7
         MOVX   A,@DPTR
     MOV    37H,A
     CPL    A
     JZ     KSK4
     LCALL   DELAY
     MOVX   A,@DPTR
     XRL    A,37H
     JZ     KS1
KSK4:AJMP   KS5
KS1: MOVX   A,@DPTR
     CPL    A
     JNZ    KS1
     MOV    A,37H
     JB     ACC.0,KS2
     MOV    37H,#00H
     AJMP   KS6
KS2: JB     ACC.1,KS3
     MOV    37H,#01H
     AJMP   KS6
KS3: JB     ACC.2,KS4
     MOV    37H,#02H
     AJMP   KS6
KS4: JB     ACC.3,KS5
     MOV    37H,#03H
     AJMP   KS6

KS5: SETB   ACC.3
     AJMP   KS7
KS6:
        MOV A,37H
        ANL    A,#0FEH                                ;?待确定
     JNB    P3.4,KS7
         ANL   A,#0FDH                                ;?待确定
         JNB P3.5,KS8
         ANL   A,#0FBH                           ;?待确定
         JNB P3.6,KS9
         ANL   A,#0F7H                          ;?待确定
         JNB P3.7,KS10
KS7:
         MOV DPTR,#TABLE1
         MOVC A,@A+DPTR
         MOV DPH,A
         MOV 21H,A
         MOV A,22H
         RL A
         INC A
         MOVC A,@A+DPTR
         MOV DPL,A
         MOV 20,A
       SJMP PLAY
KS8: MOV DPTR,#TABLE2
         MOVC A,@A+DPTR
         MOV DPH,A
         MOV 21H,A
         MOV A,22H
         RL A
         INC A
         MOVC A,@A+DPTR
         MOV DPL,A
         MOV 20,A
       SJMP PLAY
;9和10暂未处理
KS9: ORL    P3,#03H
     MOV    37H,A
     JB ACC.2,KS10                                   ;如果不是第3个键按下,则转
     MOV DPH,#0FDH
           MOV DPL,#09H
       SJMP PLAY
KS10: ORL    P3,#03H
     MOV    37H,A
     JB ACC.3,KEY1                                   ;如果不是第4个键按下,则转
     MOV DPH,#0FDH
           MOV DPL,#34H
       SJMP PLAY       
                         
PLAY:
       MOV T0TH,DPH         ;存高位字符
       MOV T0TL,DPL         ;存低位字符
           MOV TH0,T0TH
           MOV TL0,T0TL
       SETB TR0                 ;启动定时器0
       MOV R2,#01B                 ;1/4拍
       DJNZ R2,PLAY
           LCALL DELAY
           SJMP JUDGE
JUDGE:
       JB P1.5,KS8     ;按键未按下,则继续扫描,否则,开始放音乐
TABLE1: DW 64021,64103,64260,64400  ;低音3,低音4,低音5,低音6
TABLE2:        DW 64524,64580,64684,64777           ;低音7,中音1,中音2,中音3

求解这部分程序如何修改能符合项目要求。跪谢!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top