|
終于把板子給焊上了,之所以會(huì)這么久是因?yàn)樽龊玫腜CB還必須集運(yùn)才送來(lái),得十天八天,影響開(kāi)發(fā)速度,軟件方面就容易得多,因?yàn)槲抑耙呀?jīng)做了兩款掃描電子琴琴鍵的軟件,有88鍵的,包含力度感應(yīng),相當(dāng)復(fù)雜,當(dāng)初幸好有網(wǎng)友yzwzfyz指點(diǎn)一番,不然還真做不出來(lái)。
現(xiàn)在這個(gè)就非常簡(jiǎn)單了,只用到8條X線,5條Y線,可檢測(cè)40個(gè)鍵,所以把舊軟件簡(jiǎn)化,用了兩晚就解決了,編程思路如下:
1. 向某一條Y線送出0, 其他保持1,讀取X線的值(8位),這8位有某個(gè)按鍵被按下,該位是0。
2. 由于8位連接的按鍵會(huì)同時(shí)被按下,所以得用移位逐個(gè)檢測(cè)每個(gè)位,并結(jié)合Y的值算出是琴上的那個(gè)鍵被按下。
3. 確定被按下的鍵必須在記憶區(qū)相應(yīng)的位置設(shè)定標(biāo)記1,然后送出NOTEON的MIDI碼。
4. 沒(méi)有按下的鍵也必須在其記憶區(qū)相應(yīng)的位置檢查標(biāo)記,若為1表示之前已經(jīng)送出NOTEON,所以必須送出NOTEOFF的MIDI碼,再把標(biāo)記設(shè)為0.
5. 按鍵不必有防抖程序,因?yàn)槊恳淮螔呙钑?huì)有間隔,不會(huì)出現(xiàn)連續(xù)開(kāi)關(guān)的情況,經(jīng)過(guò)測(cè)試的確如此。
注:Y線是連接二極管的負(fù)極,X線是連接二極管的正極。
無(wú)標(biāo)題123.jpg (259.94 KB, 下載次數(shù): 71)
下載附件
2023-9-29 18:21 上傳
SCANNER: ;鍵盤掃描主程序
;LCALL DELAY3 ;這個(gè)試驗(yàn)時(shí)可開(kāi),但正式使用要關(guān)。
SCANP1: ;輸出到P1,其中一列是0,然后從P2讀入,8位代表列,如某行有按下則為0,否則為1,8行都有可能同時(shí)按下。
MOV 35H, #0 ;THIS WILL ADD TO ROW TO MAKE 0-7
MOV 32H, #5 ;8 BITS TO SHIFT
MOV 50H, #11111111B ;THIS BYTE FOR SHIFT AND OUTPUT TO P1
MOV P1, #11111111B ;CLEAR P1 AFTER EVERY BIT SCAN
LCALL DELAY1
CLR C ;PUSH A ZERO INTO 50H AT FIRST ROTATE
SCANP1A:
MOV A, 50H
RLC A ;改用左移,第一次(C=0)被推入,變成11111110,而C變成1,第二次移0被左移,變成11111101
MOV 50H, A ;保留進(jìn)50H,下次再用
MOV P1, A ;輸出到P1
;MOV P1, #11101111B ;第一步:這個(gè)用來(lái)檢測(cè)每一根輸出線(逐個(gè)放0,只有5根線BIT0-BIT4)
LCALL DELAY0 ;稍等
MOV A, P2 ;READ FROM P2
;LCALL SENTONEBYTE1
LCALL EACHDATA
SETB C ;BEFORE LOOP SET C FOR SHIFT ONE TO 50H
MOV P1, #11111111B ;CLEAR P1 AFTER EVERY BIT SCAN
LCALL DELAY1
;LCALL DELAY3
DJNZ 32H, SCANP1A ;5 TIME LOOP
JMP SCANNER
EACHDATA: ;32H 從8逐漸減到1,代表是那一列被設(shè)為0,與監(jiān)測(cè)到0的行相乘就得到掃描號(hào)碼。
PUSH PSW
MOV 34H, #8 ;8行檢測(cè)
MOV 33H, A ;A 是由P2 讀來(lái)的8BIT,每個(gè)BIT代表一個(gè)掃描線與P1那個(gè)被設(shè)定為0之間的按鍵是否有按下,按下則為零。
EACHDATA1: ;8次重復(fù)由34H控制
MOV A, 33H
LCALL COUNTPOSITION ;先算出當(dāng)前鍵的位置
MOV 3EH, A ;回來(lái)后A是按鍵數(shù)目
LCALL KEYMAP ;查表得到該按鍵在鍵盤上的排列號(hào)碼
MOV 3AH, A ;保存鍵盤號(hào)碼到3AH
MOV A, 33H
RLC A ;向左移,檢查C看是1還是0
MOV 33H, A ;SAVE BACK FOR NEXT ROTATE
JNC DOKEY1 ;CONTACT POINT NOT CONTACT GO NOTEOFF SUBROTINE
LCALL NOTEOFFLAH ;NOTE OFF SUBROUTINE
JMP DOKEY2
DOKEY1:
MOV A, 3AH ;按鍵碼
;LCALL SENTONEBYTE1
LCALL NOTEONLAH ;保存區(qū)相應(yīng)位置放1
DOKEY2:
DJNZ 34H, EACHDATA1 ;8 LOOP NEEDED
DOKEYEXIT:
POP PSW
RET
NOTEOFFLAH:
MOV DPH, #0
MOV DPL, 3AH
MOVX A, @DPTR ;READ OLD DATA
JZ NOTEOFFX
MOV A, #0
MOVX @DPTR, A ;標(biāo)志為1
LCALL SENTNOTEOFF ;送出NOTEOFF,只限一次
NOTEOFFX:
RET
NOTEONLAH:
MOV DPH, #0
MOV DPL, 3AH
MOVX A, @DPTR ;READ OLD DATA
JNZ NOTEONX
MOV A, #1
MOVX @DPTR, A ;標(biāo)志為1
LCALL SENTNOTEON ;送出NOTEON,只限一次
NOTEONX:
RET
SENTNOTEOFF:
MOV A, #10000000B ;MIDI NOTEOFF CHANNEL1
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
MOV A, 3AH
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
MOV A, #0
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
RET
SENTNOTEON:
MOV A, #10010000B ;MIDI NOTEON CHANNEL1
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
MOV A, 3AH
ANL A, #01111111B ;MASKING BIT7 音符
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
MOV A, #7FH ;力度
LCALL SENTONEBYTE1
LCALL SENTONEBYTE2
RET
COUNTPOSITION: ;這個(gè)算法不一般
PUSH PSW
MOV A, 32H ;列ROW POSITION 1-8
MOV B, #8 ;8 CONTACT POINT FOR EACH ROW
MUL AB ;得到的數(shù)字是 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 1-8 行COLUME
POP PSW
RET
KEYMAP: ;由于此款排列順序,無(wú)需查表,直接運(yùn)算
MOV A, #50H ;從小變大!
CLR C
SUBB A, 3EH
RET
|
|