找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2385|回复: 1
收起左侧

STC8F单片机电子琴键盘力度扫描底板改装制作 附源程序

[复制链接]
ID:283954 发表于 2020-8-2 17:21 | 显示全部楼层 |阅读模式
37key2.jpg 37key1.jpg

去年买四台37键的电钢琴打算组成一个小乐队在舞台给歌曲做伴奏用,一试之下大失所望,声音很小而且乐器的音质很差,毕竟只是四百元人民币的玩具琴,难登大雅之堂,没办法只好拆掉其控制盒,留下空键盘来做单片机键盘扫描的开发。

首先的拆掉一台琴的所有黑白键,露出键盘扫描的底板,逐点测量接触点到FHD接口的针位,总结出共有12个行和8个列,再购买测试FHD的实验板,确定无误后画底板,用的是32脚的STC8F1k08。

再把另一台琴挂上墙壁,接上底板开始写软件,不时上网搜寻单片机电子琴的文章参考,可惜都是简单的扫描软件,没有找到一款是有力度的,大概这些复杂的软件都是为电子琴公司开发的,不随便发表。还好前几年在这论坛问过力度测定的问题,得到一位前辈的指导,写过一个用STC15的键盘扫描程序,就用这个来改写吧!

从STC15单片机移植到STC8并不困难,就几个内部开关要改,另外就是串口的波特率,还有就是行列扫描线不同了,要重新测定每个键的扫描码,一切似乎很顺利,但做好之后发现偶尔会出现错误的音,原因一直找不到。

看过很多文章都强调键盘扫描都要有去抖动的功能,但在这个连续不断扫描的程序里要如何实现去抖动呢?想来想去,最后从单片机串口内部结构获得启示,就是连续小间隔读取三次,把三个数值比较,取二个相同的,如果三个都不同就让程序死机,问题终于得到解决,也不知其他人是如何解决同样的问题,总之我把原程序贴出来,以后想玩电子琴力度扫描的都可以参考一下。程序相当乱了,但已经在我的琴跑了几个月,不会死机。

单片机源程序如下:
;THIS IS FOR 37key KEYBOARD WITH 3 SCAN CODE 06/05/2020 USING STC8F
;THIS VERSION CHANGE CRYSTAL FROM 18M TO 11M, CHANGE AUXR.S2MODE TO ZERO 3/9/2018 output as midi
;30H NO USE
;31H NO USE
;32H FOR ROW COUNT LOOP
;33H FOR STORE SCAN DATA(MAY CONAIN FEW 0 THAT MEAN CONTACT)
;34H FOR LOOP
;35H FOR ADD TO ROW FORM 1-8 OR 9-16
;36H
;37H FOR CODESCAN LOOP
;38H
;39H
;3AH FOR KEYNUMBER
;3BH FOR VELOCITY
;3CH
;3DH
;3EH FOR SCAN CODE
;3FH
;40H
;41H FOR TEST
;42H

;MOV   T2L, #0D8H            //SET BYTE (65536-18432000/4/115200)
;MOV   T2H, #0FFH
;MOV   AUXR, #14H          //T2 IS 1T, AND RUN T2


;------------THIS FOR PCON.7=0 256-X=A THIS IS FOR STC12
;247(11.0592, 38400) 253(11.0592 115200) 245(11.0592 MIDI 31.4) 238(19200) 220(9600)
;251(18.4320 115200) 241(18.432 38400) 226(18.432, 19200) 196(18.432, 9600)
;250(22.1184 115200) 238(22.1184, 38400)
;229(33.1776. 38400) 247(33.1776, 115200) 202(33.1776,19200) 148(33.1776, 9600)
;------------THIS FOR PCON.7=1 ;STC12 BRT ALSO EFFECT BY PCON.7
;250(3.6864, 38400) 249(3.6864 32U MIDI)
;226(18.432, 38400) 219(18.4320, 2USx16=32U MIDI)
;238(11.0592, 38400) 250(11.0592, 115200) 220(11.0592, 19200) 184(11.0592, 9600) 234(11.0592, 31250 MIDI 2USx16=32US)
;202(33.1776. 38400) 193?(33.1776, 31250 MIDI) 238(33.1776, 115200) 148(33.1776,19200) 40(33.1776, 9600)

;THIS IS FOR T2 OF STC15, T2 USE 16BIT AUTO RELOAD MODE
;(AUXR-T2x12) 96(33.1776 38400) 202(33.1776 115200) 58(33.1776 31250)

FIRSTBUFFER EQU 80H
LASTBUFFER EQU 0FFH
T2HIGH EQU 0FFH        ;USE 22MH 0FFH
T2LOW EQU 112          ;112=38400 68-31250
IE2 EQU 0AFH           ;X, X, X, X, X, X, ESPI, ES2


S2CON EQU 9AH          ;S2SM0, S2SM1(RESRVE, MUST BE 1), S2SM2, S2R_ENABLE, S2TB8, S2RB8, S2TI, S2RI
S3CON EQU 0ACH         ;SAME AS S2CON
S4CON EQU 84H
S2BUF EQU 9BH
S3BUF EQU 0ADH
S4BUF EQU 85H

T2H EQU 0D6H           ;UART2 HIGH T2 AS
T2L EQU 0D7H           ;UART2 LOW
;P0 EQU 080H
;P1 EQU 090H
;P2 EQU 0A0H
;P3 EQU 0B0H
P4 EQU 0C0H
P5 EQU 0C8H
P6 EQU 0E8H
P7 EQU 0F8H
AUXR EQU 8EH
AUXR2 EQU 08FH
AUXR1 EQU 0A2H
WAKE_CLKO EQU 08FH ;NO MORE IN STC15
T4T3M EQU 0D1H
P_SW2 EQU 0BAH
P_SW1 EQU 0A2H

ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EXT_INT0 ;EXTERNAL INTERRUPT0
ORG 000BH
LJMP TIMER_0  ;TIMER0 INTERRUPT
ORG 0013H
LJMP EXT_INT1 ;EXTERNAL INTERRUPT1
ORG 001BH
LJMP TIMER_1  ;TIMER_1 INTERRUPT
ORG 0023H
LJMP UART1    ;UART1 RECEIVED INTERRUPT
ORG 002BH
LJMP ADC      
ORG 0033H
LJMP LVD
ORG 003BH
LJMP PCA
ORG 0043H
LJMP UART2    ;UART2 RECEIVED INTERRUPT
ORG 004BH
LJMP SPI
ORG 0053H
LJMP INT2
ORG 005BH
LJMP INT3
ORG 0063H
LJMP TIMER_2
ORG 0083H
LJMP INT4
ORG 008BH
LJMP UART3
ORG 0093H
LJMP UART4
ORG 009BH
LJMP TIMER_3
ORG 00A3H
LJMP TIMER_4
ORG 00ABH
LJMP COMPARER
ORG 00B3H
LJMP PWM
ORG 00BBH
LJMP PWM_ERR

ORG 0100H    ; PROGRAM SET

MAIN:

;-----------I/O CONFIGUE
MOV 93H, #00000000B      ;SET P0 0,0=I/0, 0,1=HIGH CURRENT OUTPUT, 1,0=HIGH IMPEDENY INPUT 1,1=OPEN COLLECTIVE OUTPUT
MOV 94H, #11111111B      ;P0=HIGH CURRENT OUTPUT
;MOV 94H, #00000000B      ;SET P0 (CONMAIN WITH 93H THIS IS SENCOND BIT)

MOV 91H, #00000000B      ;SET P1
MOV 92H, #00000000B      ;SET P1

MOV 95H, #00000000B      ;SET P2
MOV 96H, #11111111B
;MOV 96H, #00000000B      ;SET P2
MOV 0B1H, #00000000B     ;SET P3
MOV 0B2H, #00000000B     ;SET P3
MOV 0B3H, #00000000B     ;SET P4 AS I/0 (NEED THIS BECAUSE ALE,WR,RD DEFAULT AS HIGH IMP)
MOV 0B4H, #00010000B     ;SET P4 AS I/O
;MOV 0C9H, #00000000B    ;SETP5
;MOV 0CAH, #00000000B    ;SETP5
MOV 0CBH, #00000000B     ;SET P6
MOV 0CCH, #00000000B     ;SET P6
MOV 0E1H, #00000000B     ;SET P7
;MOV 0E2H, #11111111B     ;SET P7
MOV 0E2H, #00000000B     ;SET P7
;----I/O DISPLAY
;MOV P0, #0FFH
;MOV P1, #0FFH
;MOV P2, #0FFH
;MOV P3, #0FFH

;MOV P5, #0FFH
;MOV P6, #0FFH
;MOV P7, #0FFH

MOV P_SW1, #01000000B   ;SWITCH TO P3.6,3.7 BIT7=U1 S1-S1, 6=U1-S1-S0  
;MOV P_SW2, #00000110B    ;4=U4-SW TO  2=U3-SW 1=U1-SW

TESTLAH:
CLR P3.3
LCALL DELAY3
SETB P3.3
LCALL DELAY3
;JMP TESTLAH

;MOV 97H, #00001111B         ;SLOW DOWN
;MOV WAKE_CLKO,#00000000B     ;ENABLE BRT(=4),T1(=2) T0(=1) HAVE CLOCK OUTPUT T2@P1.0 T1@P3.5 T0@P3.4 ;MAY NO IN STC15
MOV T2H, #T2HIGH
MOV T2L, #T2LOW              ;212(22m 31250 2us) 214 162=57600 160=56000 112=38400
MOV AUXR,#00010101B          ;T0x12,T1x12,UART_M0x6,T2RUN,T2C/T,T2x12,EXTRAM,S1ST2 S12T2=S1SWITCHT2
;MOV AUXR1, #00010000B       ;MOVE TO TX2=P4.3 RX2=4.2
MOV AUXR2,#00000000B         ;x, EX4(EXTERNAL INTERRUPT), EX3, EX2, X, T2CLKO, T1CLK0, T0CLK0 ;T2@P3.0 T1@P3.4 T0@P3.5
MOV T4T3M, #00000000B        ;T4RUN, T4C/T, T4x12, T4OUT,

MOV TMOD, #00010001B         ;TIMER_1 AS MOD1 (16BIT COUNTER) ;TIMER_0 AS MOD 1 (16BIT COUNTER)
                             ;GATE, C/T,M1,M0(T1) GATE, C/T,M1,MO(T0)
MOV PCON, #10000000B         ;THIS DOUBLE THE BRT AND T0 T1 RATE, BUT NOT EFFECT T2
SETB ET1                     ;ENABLE T1 INTERRUPT
SETB TR1                     ;RUN T1

LCALL INITIAL_UART1          ;USE BRT AS SERIAL BAUD GENERATE FOR UART2
SETB  EA                     ;ENAABLE ALL INTERRUPT

LCALL CLEANRAM
;LCALL SETRAM ;TO FF

MOV R0, #FIRSTBUFFER         ;INIT THE BTYE TO SENT IN BUFFER POINTER
MOV R1, #FIRSTBUFFER         ;INIT THE POINTER FOR BYTE CAN STORE IN BUFFER

TEST: ;SENT 55H
;MOV P4, A
MOV A, #55H
LCALL SENTONEBYTE1
LCALL DELAY3
CPL P3.3
LCALL DELAY3
;JMP TEST

;TEST3:
;LCALL DELAY3
;MOV 5AH, #01H
;MOV 5BH, #03H
;MOV 5CH, #02H
;LCALL VERIFY
;JMP TEST3

MOV P1, #0FFH

SCANNER:
LCALL DELAY3
;LCALL OUTBUFFER
;MOV P4, #0FFH
MOV DPH, #2
MOV DPL, #0
SCANP2:  ;SHIFT P2 AND READ P1
MOV 35H, #0          ;THIS WILL ADD TO ROW TO MAKE 0-7
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
MOV P2, #11111111B   ;CLEAR P7 AFTER EVERY BIT SCAN
LCALL DELAY1   
CLR C                ;PUSH A ZERO INTO 50H AT FIRST ROTATE
SCANP2A:
MOV A, 50H
RRC A                ;FIRST ROTATE WILL BE A ZERO IN, AFTER THAT WILL BE ONE IN, AND ZERO BIT SHIFT TO RIGHT
MOV 50H, A           ;SAVE BACK TO 50H
;MOV P4, A            ;SHOW BY LED
MOV P2, A            ;P2 ONE ROW LOW
LCALL DELAY0
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
SETB C               ;BEFORE LOOP SET C FOR SHIFT ONE TO 50H
MOV P2, #11111111B   ;CLEAR P2 AFTER EVERY BIT SCAN
;MOV A, 50H
;MOV P2, A
LCALL DELAY1
DJNZ 32H, SCANP2A    ;8 TIME LOOP

SCANP0:              ; SHIFT P0 AND READ P1 ;ONLY P0.4567
MOV 35H, #8          ;THIS WILL ADD TO ROW TO MAKE 0-7
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P7
MOV P0, #11111111B   ;CLEAR P0 AFTER EVERY BIT SCAN
LCALL DELAY1   
CLR C                ;PUSH A ZERO INTO 50H AT FIRST ROTATE
SCANP7A:
MOV A, 50H
RRC A
MOV 50H, A           ;SAVE BACK
;MOV P4, A
MOV P0, A            ;P7 ONE ROW LOW
LCALL DELAY0
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
MOV A, P1            ;READ FROM P0
;LCALL SENTONEBYTE1
MOVX @DPTR, A
INC DPL
SETB C
MOV P0, #11111111B   ;CLEAR P0 AFTER EVERY BIT SCAN
LCALL DELAY1         ;
DJNZ 32H, SCANP7A
MOV P0, #11111111B   ;END OF SCAN P0
LCALL CODESCANA      ;P2
LCALL CODESCANB      ;P0
;LCALL SHOWSTORE
LCALL SCANNERFAKE
JNB 71H, SCANNEREXIT2 ;CHECK TIMER INT FLAG
CLR 71H
;MOV A, #77H
;LCALL SENTONEBYTE1
LCALL TIMERLOOP

SCANNEREXIT2:
JMP SCANNER

SCANNERFAKE:
SCANFAKEP2:              ;SHIFT P2 AND READ P0
MOV R1, #70H
MOV 35H, #0          ;THIS WILL ADD TO ROW TO MAKE 0-7
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
CLR C                ;PUSH A ZERO INTO 50H AT FIRST ROTATE
SCANFAKEP2A:
MOV A, 50H
RRC A                ;FIRST ROTATE WILL BE A ZERO IN, AFTER THAT WILL BE ONE IN, AND ZERO BIT SHIFT TO RIGHT
MOV 50H, A           ;SAVE BACK TO 50H
MOV A, @R1            ;READ FROM P0
INC R1
CPL A
LCALL STOREDATA
SETB C               ;BEFORE LOOP SET C FOR SHIFT ONE TO 50H
DJNZ 32H, SCANFAKEP2A    ;8 TIME LOOP

SCANFAKEP7:          ; SHIFT P7 AND READ P0 ;ONLY P7.4567
MOV 35H, #8          ;THIS WILL ADD TO ROW TO MAKE 0-7
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
CLR C                ;PUSH A ZERO INTO 50H AT FIRST ROTATE
SCANPFAKE7A:
MOV A, 50H
RRC A
MOV 50H, A           ;SAVE BACK
MOV A, @R1           ;READ FROM P0
INC R1
CPL A
LCALL STOREDATA
SETB C
DJNZ 32H, SCANPFAKE7A
RET

CODESCANA:
MOV R1, #70H
MOV DPH, #2
MOV DPL, #0
CODESCANA1:
MOVX A, @DPTR
MOV 5AH, A
INC DPL
MOVX A, @DPTR
MOV 5BH, A
INC DPL
MOVX A, @DPTR
MOV 5CH, A
INC DPL
LCALL VERIFY
MOV A, DPL
CJNE A, #24, CODESCANA1
RET

CODESCANB: ;P0
CODESCANB1:
MOVX A, @DPTR
MOV 5AH, A
INC DPL
MOVX A, @DPTR
MOV 5BH, A
INC DPL
MOVX A, @DPTR
MOV 5CH, A
INC DPL
LCALL VERIFY           ;THREE CODE COMPARE
MOV A, DPL
CJNE A, #48, CODESCANB1
RET

;VERIFY:
MOV 41H, #0
MOV A, 5AH
XRL A, 5BH
JZ VERIFY1
MOV A, 41H
ADD A, #1
MOV 41H, A
VERIFY1:
MOV A, 5AH
XRL A, 5CH
JZ VERIFY2
MOV A, 41H
ADD A, #2
MOV 41H, A
VERIFY2:
MOV A, 5BH
XRL A, 5CH
JZ VERIFY3
MOV A, 41H
ADD A, #4
MOV 41H, A
VERIFY3:
MOV A, 41H
LCALL SENTONEBYTE1
MOV A, 41H
JNZ VERIFY3
RET

VERIFY:
CJNE A, 5BH, CODE1  ;3,2
LCALL STORECODE
JMP CODEEXIT
CODE1:              ;3,1
CJNE A, 5AH, CODE2
LCALL STORECODE
JMP CODEEXIT
CODE2:              ;1,2
MOV A, 5AH
CJNE A, 5BH, CODE3  ;1,2
LCALL STORECODE
JMP CODEEXIT
CODE3:
MOV A, #55H ;ERROR CODE
MOV P4, #01010101B
MOV A, 5AH
LCALL SENTONEBYTE1
MOV A, 5BH
LCALL SENTONEBYTE1
MOV A, 5CH
LCALL SENTONEBYTE1
CODE4:
JMP CODE4
LCALL STORECODE
CODEEXIT:
RET

STORECODE: ;STORE 16 VERIFIED SCANDATA OF P2,P7 FOR USE USING 70-7F MEMORY
MOV @R1, A
INC R1
RET

SHOWSTORE:
MOV R1, #70H
STORESHOW1:
MOV A, @R1
LCALL SENTONEBYTE1
INC R1
MOV A, R1
CJNE A, #80H, STORESHOW1
RET

;STOREDATA:
CJNE A, #0FFH, STORE1
JMP STOREEXIT
STORE1:
LCALL SENTONEBYTE1
STOREEXIT:
RET

STOREDATA:           ;32H CONTAIN ROW UMBER THAT CAUSE LOW
PUSH PSW
MOV 34H, #8          ;8 BIT TO SHIFT
MOV 33H, A           ;ACC CONTAIN 8BITS WITH FEW HIGH(CAUSE BY KEYPRESS)
STOREDATA1:          ;WILL LOOP 8 TIMES CHECKING EVERY BIT, CONTROL BY 34H
MOV A, 33H
LCALL COUNTPOSITION  ;CODE BY SCANNER 4C 54 COUNT BY
MOV 3EH, A           ;SAVE SCAN CODE
LCALL KEYMAP         ;RETURN KEYNUMBER A AFTER LOOKUP THE MAP THAT REPRESENT KEYNUMBER(0-60), IF FIRST KEY THEN 0(UPPER),80(LOWER)
MOV 3AH, A           ;SAVE KEYNUMBER TO 3AH, 0-127 IS UPPER KEY, 128-255 IS LOWER KEY
MOV A, 33H           
RLC A                ;CHECK EACH BIT OF 33H SEE 0 OR 1 AND DECIDE WHERE TO GO
MOV 33H, A           ;SAVE BACK FOR NEXT ROTATE
JNC DOKEY1           ;CONTACT POINT NOT CONTACT GO NOTEOFF SUBROTINE

;MOV A, 3AH
;LCALL SENTONEBYTE1   ;SHOW KEYNUMBER
;MOV A, 3EH
;LCALL SENTONEBYTE1   ;SHOW SCANCODE

LCALL NOTEON         ;NOTE ON SUBROUTINE
JMP STOREDATANEXT
DOKEY1:
LCALL NOTEOFF        ;NOTEOFF SUBROUTINE
STOREDATANEXT:
DJNZ 34H, STOREDATA1 ;8 LOOP NEEDED
DOKEYEXIT:
POP PSW
RET

COUNTPOSITION:
PUSH PSW
MOV A, 32H        ;ROW POSITION 1-8 P2,P7
ADD A, 35H        ;IF P2 THEN ADD 0(REMAIN 1-8), IF P7 THEN ADD 8(BECOME 9-16)
MOV B, #8         ;8 CONTACT POINT FOR EACH ROW
MUL AB            ;NUMBER 8,16,24,32,40.......128
CLR C
SUBB A, #8        ;MAKE A 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120
ADD A, 34H        ;34H CONTAIN 1-8 COLUME NUMBER(EACH BIT OF 33H) FORM 1 TO 128
;DEC A             ;MAKE AS 0-127 SYSTEM
POP PSW
RET

NOTEON:           ;KEY CONTACT DETECTED
CLR P3.3
MOV A, 3AH      
RLC A             ;CHECK UPPER OR LOWER
JC NOTEON1        ;LOWER KEY SO DO OUTPUT

;----------UPPER
MOV DPH, #0
MOV DPL, 3AH
MOVX A, @DPTR     ;READ OLD DATA
JNZ NOTEONEXIT    ;ALREADY CONTACTED, DO NOTHNG SO EXIT

;;---DELAY TIME CHECK
;MOV DPH, #1
;MOV DPL, 3AH
;MOVX A, @DPTR     ;READ LOCATION #2 OLD DATA
;JNZ NOTEONEXIT    ;NOT REACH 0 SO MUST WAIT SO EXIT

MOV DPH, #0
MOV DPL, 3AH
MOV A, #1
MOVX @DPTR, A     ;CONTACT JUST START, PUT 1 FOR COUNT UP BY TIMER EVERY 1MS
NOP
NOP
JMP NOTEONEXIT

;----------LOWER
NOTEON1:
MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7
MOV DPH, #0
MOV DPL, A
MOVX A, @DPTR        ;READ VELOCITY
MOV 3BH, A           ;SAVE VELOCITY
JZ NOTEONEXIT        ;UPPER KEY NOT YET CONTACTED, DO NOTHING GO EXIT
DEC A
JZ NOTEONEXIT        ;UPPER KEY JUST CONTACTED @1, DO NOTHING GO EXIT

MOVX A, @DPTR        ;READ VELOCITY
MOV 3BH, A           ;SAVE VELOCITY
INC A                ;INC 1 TO SEE, IF FFH THEN WILL BE ZERO
JZ NOTEONEXIT        ;IF FFH THEN WILL ZERO MEAN NOTE ALREADY OUTPUT, NEED WAIT FOR NOTEOFF SENT, DO NOTHING GO EXIT
INC A
JZ NOTEONEXIT        ;IF FEH THEN WILL ZERO MEAN NOTE ALREADY OUTPUT, NEED WAIT FOR UPPERKEY RELEASE, DO NOTHING GO EXIT

MOV A, #10010000B    ;MIDI NOTEON CHANNEL1
LCALL SENTONEBYTE1
;LCALL PUTBUFFER     ;SENT STATUS

MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7   
LCALL SENTONEBYTE1
;LCALL PUTBUFFER      ;SENT KEY NUMBER

MOV A, 3BH
CLR C
SUBB A, #175        ;LIMIT
JC NOTEON1A
MOV 3BH, #175
NOTEON1A:
MOV A, 3BH
CPL A                ;PROCESS VELOCITY, CPL AND DIV BY 2
MOV B, #2
DIV AB
ADD A, #5            ;MOVE UP VELOCITY FROM 78 TO 7D
LCALL SENTONEBYTE1
;LCALL PUTBUFFER      ;SENT VELOCITY   
MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7
NOP
NOP
MOV DPH, #0
MOV DPL, A
MOV A, #0FEH
MOVX @DPTR, A        ;MARK AS FEH WAIT FOR RELEASE FOR SENT NOTEOFF
LCALL DELAY0
NOTEONEXIT:
RET

NOTEOFF:             ;KEY NOT-CONTACT DETECTED
SETB P3.3
MOV A, 3AH      
RLC A                ;CHECK UPPER OR LOWER
JNC NOTEOFF1         ;UPPER KEY SO DO NOTEOFF

;=====LOWER KEY
MOV A, 3AH
ANL A, #01111111B    ;MASKING
NOP                  ;LOWER KEY RELEASE, PUT FF
NOP
MOV DPH, #0
MOV DPL, A
MOVX A, @DPTR        ;READ OLD DATA
INC A
JZ NOTEOFFEXIT        ;IF FF THEN ZERO DO NOTING SO EXIT
INC A
JNZ NOTEOFFEXIT      ;IF NOT FEH THEN WILL BE NOT ZERO MEAN NOTEON NOT YET SENT, DO NOTHING SO EXIT
MOV A, #0FFH
MOVX @DPTR, A        ;MARK THAT KEY LOCATION #FF THAT ALLOW NOTEOFF SENT IF UPPER KEY ALSO RELEASE
LCALL DELAY0
JMP NOTEOFFEXIT

;UPPER KEY
NOTEOFF1:
NOP                  ;UPPER KEY RELEASE, CHECK 0FFH FOR SENT NOTEOFF
NOP
MOV DPH, #0
MOV DPL, 3AH
MOVX A, @DPTR        ;READ OLD DATA
INC A
JNZ VELOCITYRESET      ;IF NOT FFH THEN WILL BE NOT ZERO MEAN NOTEON NOT YET SENT OR N0T YET RELAESE, DO NOTHING SO EXIT

SENTNOTEOFF:
MOV A, #10000000B    ;MIDI NOTEOFF CHANNEL1
LCALL SENTONEBYTE1
;LCALL PUTBUFFER      ;SENT NOTEOFF STATUS BYTE
MOV A, 3AH
LCALL SENTONEBYTE1
;LCALL PUTBUFFER      ;SENT KEYNUMBER
MOV A, #0
LCALL SENTONEBYTE1
;LCALL PUTBUFFER      ;SENT ZERO VELOCITY

MOV DPH, #0
MOV DPL, 3AH
MOV A, #0
MOVX @DPTR, A         ;MARK THAT KEY LOCATION 0 TO RECEIVED NEW CONTACT PRESS

MOV DPH, #1           ;PUT A VALUE TO KEY LOCATION DPL#1 FOR CONTROL REPEAT (DELAY)
MOV DPL, 3AH
MOV A, #05H           ;THIS IS THE VALUE!! ;30H
MOVX @DPTR, A         ;SENT VALUE TO KEY LOCATION DPL#1 NOW
NOP
JMP NOTEOFFEXIT
VELOCITYRESET:       ;DUE TO ON/OFF NOISE
MOV DPH, #0
MOV DPL, 3AH
MOV A, #0
MOVX @DPTR, A         ;MARK THAT KEY LOCATION 0 TO RECEIVED NEW CONTACT PRESS

NOTEOFFEXIT:
RET

TIMER_1:              ;USE FOR MICRO CLOCK 1MS 184, 30 ,100US=248 250
SETB 71H
PUSH ACC
PUSH PSW
PUSH DPH
PUSH DPL
MOV DPH, #0
MOV DPL, #0
LCALL TIMERLOOP
POP DPL
POP DPH
POP PSW
POP ACC
MOV TH1, #255; 251; #200;#248 254
MOV TL1, #5;#250
RETI

TIMERLOOP:
MOVX A, @DPTR
JZ TIMER_1NEXT              ;ZERO MEAN NOT UPPER KEY NOT YET PRESS, SO NO ADD
CJNE A, #0FFH, TIMERLOOP1A  ;NOT FF THEN CHECK FE
JMP TIMER_1NEXT             ;IS FF MEAN LOWER KEY HAD RELEASE BUT UPPER NO YET RELEASE,SO EXIT
TIMERLOOP1A:
CJNE A, #0FEH, TIMERLOOP1   ;NOT FE THEN CHECK FD
JMP TIMER_1NEXT             ;FE MEAN LOWER KEY HAS CONTACT AND NOTEON SEND, BUT LOWER NOT YET RELEASE, SO EXIT

TIMERLOOP1:                 ;HERE CHECK NOT YET MAX THEN ADD
CJNE A, #0FDH, TIMER_1A     ;NOT YET MAX, SO ADD
JMP TIMER_1NEXT             ;MAX, NO ADD
TIMER_1A:                  
INC A                       ;INCREASE
MOVX @DPTR, A               ;PUT BACK

TIMER_1NEXT:
INC DPL
MOV A, DPL
CJNE A, #75, TIMERLOOP     ;LOOP UP UNTIL EVERY KEY
TIMER_1EXIT:
RET

UART2:                       ;THIS NEVER ACTIVE IN THIS PROGRAM
;/*----------------------------
;UART2 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
MOV  A, S2CON                ;READ UART2 CONTROL REGISTER
ANL A, #00000001B            ;ANL, IF S2RI=0 THEN 0
JZ UART2CHECKTI
MOV A, S2BUF
ANL S2CON, #11111110B         ;CLEAR S2RI BIT
JMP UART2EXIT
UART2CHECKTI:               
ANL S2CON, #11111101B        ;CLEAR S2TI BIT
CLR 41H
UART2EXIT:
POP    PSW
POP    ACC
RETI

EXT_INT0:            ;IF P3.2 H2L COME HERE SET TIMER, ONLY FIRST H2L WILL ACT
RETI
TIMER_0:             ;CHECK INPUT MIDI SIGNAL AT P3.2
RETI
EXT_INT1:            ;USE FOR INFRA RED
RETI

;INITIAL_UART2:           ;USE FOR SENT MIDI DATA
;MOV S2CON, #01010000B    ;SET AS BAUD VERIABLE, NO ODD/EVEN CHECK
;MOV IE2, #01H            ;ENABLE UART2 INTERRUPT
;RET

;-----INTERUPT
;UART1:
;RETI

ADC:
RETI
PCA:
RETI
LVD:
RETI
SPI:
RETI

INT2:
RETI
INT3:
RETI
TIMER_2:
RETI
INT4:
RETI
UART3:
RETI
UART4:
RETI
TIMER_3:
RETI
TIMER_4:
RETI
COMPARER:
RETI
PWM:
RETI
PWM_ERR:
RETI

CLEANRAM:
MOV DPH,#0
MOV DPL, #0
CLEANRAM1:
MOV A, #0
MOVX @DPTR, A
INC DPL
MOV A, DPL
JNZ CLEANRAM1
INC DPH
MOV A, DPH
CJNE A, #4, CLEANRAM1
RET

SETRAM:
MOV DPH,#0
MOV DPL, #0
SETRAM1:
MOV A, #0FFH
MOVX @DPTR, A
INC DPL
MOV A, DPL
JNZ SETRAM1

RET



;SCANCODE
;POSIT:01 02 03 04 05 06 07 08 09 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
;PORT  D7 D0 D1 D2 D3 D4 D5 D6 D7 D0 D1 D2 D3 D4 D5 D6 D7 D0 D1 D2 D3 D4 D5 D6 D7 D0 D1 D2 D3 D4 D5 D6 D7 D0 D1 D2 D3
;UPKEY:77 76 76 76 76 76 76 76 76 27 27 27 27 27 27 27 27 26 26 26 26 26 26 26 26 23 23 23 23 23 23 23 23 22 22 22 22
;DNKEY:74 75 75 75 75 75 75 75 75 24 24 24 24 24 24 24 24 25 25 25 25 25 25 25 25 20 20 20 20 20 20 20 20 21 21 21 21

DELAY0: ;0 LOOP SUPER FAST
MOV 55H, #50
SLOWDOWN0_0:
DJNZ 55H, SLOWDOWN0_0
RET

DELAY1: ;1 LOOP DELAY FAST
MOV 55H, #250
SLOWDOWN1_0:
DJNZ 55H, SLOWDOWN1_0
RET

DELAY2: ;2 LOOP DELAY SHORT
MOV 55H, #10
SLOWDOWN2_0:
MOV 56H, #1; #8 ;#6
SLOWDOWN2_1:
DJNZ 56H, SLOWDOWN2_1
DJNZ 55H, SLOWDOWN2_0
RET

DELAY3: ;3 LOOP DELAY LONY
CPL P3.3
MOV 55H, #255
SLOWDOWN3_0:
MOV 56H, #255
SLOWDOWN3_1:
MOV 57H, #2
SLOWDOWN3_2:
DJNZ 57H, SLOWDOWN3_2
DJNZ 56H, SLOWDOWN3_1
DJNZ 55H, SLOWDOWN3_0
RET

DELAY4: ;3 LOOP DELAY LONG LOG
MOV 55H, #255
SLOWDOWN4_0:
MOV 56H, #255
SLOWDOWN4_1:
MOV 57H, #100
SLOWDOWN4_2:
DJNZ 57H, SLOWDOWN4_2
DJNZ 56H, SLOWDOWN4_1
DJNZ 55H, SLOWDOWN4_0
RET

SHOWSCAN:
MOV DPH, #2
MOV DPL, #0
SHOWSCAN1:
;MOVX A, @DPTR
;LCALL SENTONEBYTE1
MOV A, DPL
LCALL SENTONEBYTE1
INC DPL
MOV A, DPL
CJNE A, #48, SHOWSCAN1
RET



KEYMAP:
PUSH DPL
PUSH DPH
MOV DPH, #10H
MOV DPL, #00H
MOVC A,@A+DPTR
ADD A, #35
POP DPH
POP DPL
RET

INITIAL_UART1:  
MOV SCON, #01010000B           ;SET AS BAUD VERIABLE, NO ODD/EVEN CHECK
SETB PS                        ;SERIAL PORT PRORITY HIGH
SETB ES                        ;ENABLE UART1 INTERRUPT
RET

SENTONEBYTE1:                   ;SENT OUT DATA IN R4
PUSH ACC
PUSH PSW
CHECKBUSY1:
JB 40H, CHECKBUSY1
SETB 40H                        ;MARK BUSY BIT
MOV SBUF, A
POP PSW
POP ACC
RET

UART1:
;/*----------------------------
;UART1 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
JNB RI, UART1CHECKTI
CLR RI
MOV A, SBUF                     ;READ THE CHARACTER FROM THE SERIAL PORT
MOVX @R1, A
;LCALL NEXTBUFFER1
JMP UART1EXIT
UART1CHECKTI:
CLR TI
CLR 40H                         ;CLEAR BUSY BIT
UART1EXIT:
POP PSW
POP ACC
RETI



;SENTONEBYTE1:                ;SENT OUT DATA IN A
;CHECKBUSY2:
;JB 41H, CHECKBUSY2
;SETB 41H
;MOV S2BUF, A
;RET


ORG 1000H ;KEY MAPPING CONVERT SCANNER NUMBER TO KEYBOARD PHYSICAL POSITION (MUSIC KEY 1-61)  
;UPPER-KEY+128=LOWER-KEY
;OPTAIN UPPER CONTACT POINT'S SCAN CODE MANUALLY AND PUT KEYNUMBER AT SCANCODE VALUE POSITION
;OPTAIN LOWER CONTACT POINT'S SCAN CODE MANUALLY AND PUT KEYNUMBER+128 AT SCANCODE VALUE POSITION
;EXAMPLE: IF KEY#38H, UPPER KEY SCANCODE IS 28H,PUT 28H POSITION AS 38H, LOWER KEY SCANCODE IS 30H,
;PUT 30H POSITION AS 8+38H=B8H

; 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 0BH 0CH 0DH 0EH 0FH
;  ---------------------------------------------------------------
   
DB 00H,9AH,9BH,9CH,9DH,9EH,9FH,0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,00H,00H,00H ;0 16  0F
DB 00H,22H,23H,24H,25H,00H,00H,00H,00H,1AH,1BH,1CH,1DH,1EH,1FH,20H ;0 16  1F
DB 21H,8AH,8BH,8CH,8DH,8EH,8FH,90H,91H,92H,93H,94H,95H,96H,97H,98H ;0 16  2F
DB 99H,12H,13H,14H,15H,16H,17H,18H,19H,0AH,0BH,0CH,0DH,0EH,0FH,10H ;0 16  3F
DB 11H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  4F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  5F
DB 00H,00H,00H,00H,00H,00H,00H,00H,81H,82H,83H,84H,85H,86H,87H,88H ;0 16  6F
DB 89H,02H,03H,04H,05H,06H,07H,08H,09H,00H,00H,00H,00H,00H,00H,00H ;0 16  7F

DB 01H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  8F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  9F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  AF
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  BF
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  CF
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  DF
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  EF
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  FF


;  00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 0BH 0CH 0DH 0EH 0FH
;  ---------------------------------------------------------------
;DB 00H,0A2H,0A3H,0A4H,0A5H,00H,00H,00H,00H,22H,23H,24H,25H,00H,00H,00H ;0 16  0F
;DB 00H,1AH,1BH,1CH,1DH,1EH,1FH,20H,21H,8AH,8BH,8CH,8DH,8EH,8FH,90H ;0 16  1F
;DB 91H,92H,93H,94H,95H,96H,97H,98H,99H,12H,13H,14H,15H,16H,17H,18H ;0 16  2F
;DB 19H,0AH,0BH,0CH,0DH,0EH,0FH,10H,11H,00H,00H,00H,00H,00H,00H,00H ;0 16  3F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  4F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  5F
;DB 81H,82H,83H,84H,85H,86H,87H,88H,89H,02H,03H,04H,05H,06H,07H,08H ;0 16  6F
;DB 09H,00H,00H,00H,00H,00H,00H,00H,01H,9AH,9BH,9CH,9DH,9EH,9FH,0A0H ;0 16  7F

;DB 0A1H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  8F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  9F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  AF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  BF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  CF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  DF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  EF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  FF

;DB 20H,21H,22H,23H,24H,25H,26H,27H,30H,31H,32H,33H,34H,35H,36H,37H ;0 16  0F
;DB 0B0H,0B1H,0B2H,0B3H,0B4H,0B5H,0B6H,0B7H,28H,29H,2AH,2BH,2CH,2DH,2EH,2FH ;0 16  1F
;DB 0A8H,0A9H,0AAH,0ABH,0ACH,0ADH,0AEH,0AFH,38H,39H,3AH,3BH,3CH,00H,00H,00H ;0 16  2F
;DB 0B8H,0B9H,0BAH,0BBH,0BCH,00H,00H,00H,90H,91H,92H,93H,94H,95H,96H,97H ;0 16  3F
;DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0AH,0BH,0CH,0DH,0EH,0FH ;0 80  4F
;DB 88H,89H,8AH,8BH,8CH,8DH,8EH,8FH,80H,81H,82H,83H,84H,85H,86H,87H ;0 96  5F
;DB 10H,11H,12H,13H,14H,15H,16H,17H,98H,99H,9AH,9BH,9CH,9DH,9EH,9FH ;0 16  6F
;DB 18H,19H,1AH,1BH,1CH,1DH,1EH,1FH,0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,0A6H,0A7H ;0 16  7F

;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  8F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  9F
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  AF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  BF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  CF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  DF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  EF
;DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  FF


END




评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:65956 发表于 2020-8-6 11:23 | 显示全部楼层
看到汇编程程序也让我想起了我的起步学单片机编程也是用汇编,所以先在这边支持一下,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表