久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4070|回復: 14
打印 上一主題 下一主題
收起左側

51單片機要如何同時測定61個電子琴按鍵的力度(速度)

[復制鏈接]
跳轉到指定樓層
樓主
各位好!

我是新手,請大家多關照,最近想設計一臺用STC單片機做的61鍵無線藍牙電子琴,用現成的廉價電子琴來改裝,打算直接掃描16X8行列的狀態加以處理,這部分程序已經寫好測試妥當了(附程序),由于這是一個有力度感的鍵盤,一個鍵有2個觸點,通過測定觸點的接觸時間差計算出速度而換算為力度,原理是很簡單,但實施起來很困難,怎樣也想不通,所以特地來請教各位高手,原理是:運行單片機內的計時器(向上),當檢測到第一個接觸點時,讀取定時器數值存入相應的記憶1,等檢測到第二個接觸點時, 再讀取定時器數值存入相應的記憶2,兩個數字的差就是力度了。硬件上的設計確定一個琴鍵按下時,第一觸點一定比第二觸點快,所以記憶2的數值一定比記憶1的數值大,問題在于計數器溢出時就會是記憶2的數值一定比記憶1的數值小了,更大的問題是如果時間再長些,記憶2的數值又會比記憶1的數值大,變成無法分析而確定的難題了。不知道各位是否看過這方面的文獻介紹過解決這問題的方法,現實是有力度的電子琴滿街都在賣,廠家肯定已經解決問題了,就是我這新手笨,想不通,特來請教大家。

SCANNER:
;MOV 38H, #0
;MOV 39H, #0
;CPL P1.2
SCANP2:              ; SHIFT P2 AND READ P0
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 30H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
MOV 35H, #0          ;THIS WILL ADD TO ROW TO MAKE 0-7
CLR C
SCANP2A:
MOV A, 30H
RRC A
MOV 30H, A
MOV P2, A            ;P2 ONE ROW LOW
LCALL DELAY4         ;MUST WAIT STABLE
MOV A, P0            ;READ FROM P0
CPL A
JZ SCANNEXT1           ;NO KEY PRESS FOUND, READP1
LCALL STOREDATA
SCANNEXT1:
;LCALL DELAY2
DJNZ 32H, SCANP2A
MOV P2, #11111111B   ;END OF SCANP2
;JMP SCANNER

SCANP3:              ; SHIFT P3 AND READ P0
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 30H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
MOV 35H, #8          ;THIS WILL ADD TO ROW TO MAKE 0-7
CLR C
SCANP3A:
MOV A, 30H
RRC A
MOV 30H, A
MOV P3, A            ;P2 ONE ROW LOW
LCALL DELAY4         ;MUST WAIT STABLE
MOV A, P0            ;READ FROM P0
CPL A
JZ SCANNEXT2           ;NO KEY PRESS FOUND, READP1
LCALL STOREDATA
SCANNEXT2:
;LCALL DELAY2
DJNZ 32H, SCANP3A
MOV P3, #11111111B   ;END OF SCANP
;LCALL DELAY5
JMP SCANNER

STOREDATA:           ;32H CONTAIN ROW NUMBER THAT CAUSE LOW
PUSH PSW
MOV 34H, #8          ;8 BIT TO SHIFT
MOV 33H, A           ;A CONTAIN 8BITS WITH FEW HIGH(CAUSE BY KEYPRESS)
STOREDATA1:
MOV A, 33H
;MOV P0, A
CLR C
RLC A
MOV 33H, A
JNC NEXTBIT ;NOT PRESSED
LCALL COUNTPOSITION
LCALL KEYMAP
LCALL SENTONEBYTE2
LCALL SENTTIMER
;LCALL DELAY5
NEXTBIT:
DJNZ 34H, STOREDATA1

POP PSW
RET

SENTTIMER:
MOV A, 38H
LCALL SENTONEBYTE2
MOV A, 39H
LCALL SENTONEBYTE2

RET

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

COUNTPOSITION:
;ROWxCOLxCOL
PUSH PSW
MOV A, 32H        ;1-8
ADD A, 35H        ;+0=old or +8=16LEFT8(0-7) SO 1=16
MOV 37H, A
MOV A, #0
COUNT1:
ADD A, #8
DJNZ 37H, COUNT1  ;A WILL BE 8,16,24,32,40.......128
CLR C
SUBB A, #8        ;MAKE A 0-120
ADD A, 34H        ;(1-8)  A=1 TO 128
DEC A             ;MAKE 0-127 SYSTEM
POP PSW
RET

STOREUPKEY: ;FIRST
RET

STOREDNKEY: ;SECOND
RET

TIMER_1:  ;USE FOR MICRO CLOCK 1MS 184, 30 ,100US=248 250
PUSH ACC
CPL P1.2
INC 38H   ;16BIT TIMER3
MOV A, 38H
JNZ TIMER3
CPL P1.5
INC 39H
MOV A, 39H
JNZ TIMER3
CPL P1.7
TIMER3:
MOV TH1, #248
MOV TL1, #250
POP ACC
RETI

SENTONEBYTE2:        ;A SENT OUT
MOV IE2, #00H        ;DISABLE THE SECONDARY UART INTERRUPT, ES2=0
MOV S2BUF, A         ;LOAD A TO BUFFER
MOV A, S2CON         ;1111,1101, CLEAR SECONDARY UART TRANSIMIT INTERRUPT FLAG
ANL A, #0FDH
MOV S2CON, A
UART2WAIT:
MOV A, S2CON
ANL A, #02H          ;0000,0010
CJNE A,#02H, UART2WAIT
MOV A, S2CON
ANL A, #0FDH         ;1111,1101, CLEAR SECONDARY UART TRANSIMIT INTERRUPT FLAG
MOV S2CON, A
MOV IE2, #01H        ;ENABLE THE SECONDARY UART INTERRUPT, ES2=1
NOP
NOP
RET

DELAY4:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET



評分

參與人數 1黑幣 +8 收起 理由
arthuryu + 8 贊一個!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:7485 發表于 2018-2-13 19:08 | 只看該作者
你的這個思路存在一定的問題。
1、當單片機檢測到第一按鍵閉合時,啟動定時器,當檢測到第二按鍵閉合時停止定時器,定時器的運行數就是時間差,不需要計算。
2、你有這么多的IO嗎?你需要擴展,或者需要模擬開關電路如cd4051之類的。

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

板凳
ID:283954 發表于 2018-2-13 21:59 | 只看該作者
你好!是一次過掃描16X8共128個接點的狀態,先儲存在記憶區,再讀取記憶區作處理,有琴鍵按下就向串口發出MIDI數據。再更新記憶區,如果是沒有力度感的電子琴,那就很簡單了,有力度感的就要記錄一個按鍵的兩個接點的接觸時間再作運算,相當麻煩。

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

地板
ID:123289 發表于 2018-2-14 16:41 | 只看該作者
你的構思是正確的,精心安排一下是可以實現的。
1、建議你將力度安排為255級,這樣一位就夠了。
2、時基要重新設計并制作,當計數=255時,設計為最慢的時間,比此時間更慢就不認可。
3、第一個鍵后計數器設置為1.
4、當計數器=0時,不計數。
5、當計數器<>0時,每個時基+1
6、如此,第二個鍵時,讀到0就作未按處理,不是0就計算速度(力度)。用過了清0。
要點:設計適當的時基,即多久+1.
如果要分得更細,則需增加計數器的位數。
回復

使用道具 舉報

5#
ID:123289 發表于 2018-2-14 16:43 | 只看該作者
當然-1也可以,看你愛好。
回復

使用道具 舉報

6#
ID:283954 發表于 2018-2-14 17:56 | 只看該作者
yzwzfyz你好!
果然有好辦法,我這兩天試著自己想辦法,把計數器的值寫在記憶區的笨辦法,越寫越亂,快要放棄,但作為初學者,這種磨煉還是應該的,現在有好辦法了,今晚應該就能寫好了,多謝指教。
回復

使用道具 舉報

7#
ID:123289 發表于 2018-2-14 23:43 | 只看該作者
我看你是用匯編寫程序的,是真想學好單片機的,故點一下。
回復

使用道具 舉報

8#
ID:283954 發表于 2018-2-16 03:04 | 只看該作者
寫了兩個晚上才測試妥當,只要邏輯正確,其他可慢慢修改了,這東西難寫處在于io口幾乎用完,無法用LED燈檢查結果,另外運行時T1會中斷修改一些寄存器如DPL, 增加調試的困難,無論如何算是寫成了,就上載給大家參考了, 再謝yzwzfyz 總工。

;THIS IS FOR KEYBOARD TESTING
;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
;37H FOR LOOP CONVERT ROW NUMBER TO KEYNUMBER
;3AH FOR KEYNUMBER


FIRSTBUFFER EQU 80H
LASTBUFFER EQU 0FFH
BRT EQU 09CH
BRTLOAD EQU 226        ;226(18.432, 38400 SMOD=1) 241(18.432, 38400) 250(3.68, 38400) 247(11.0592, 38400), 251(18.432, 115200)
S2CON EQU 9AH          ;S2SM0, S2SM1, S2SM2, S2REN, S2TB8, S2RB8, S2TI, S2RI
IE2 EQU 0AFH           ;X, X, X, X, X, X, ESPI, ES2
S2BUF EQU 9BH
P4 EQU 0C0H
AUXR EQU 8EH
AUXR1 EQU 0A2H
WAKE_CLKO EQU 08FH   


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 0100H    ; PROGRAM SET

MAIN:
MOV P0, #0FFH
MOV P1, #0FFH
MOV P2, #0FFH
MOV P3, #0FFH
MOV P4, #0FFH

;MOV 97H, #00000101B         ;SLOW DOWN
MOV WAKE_CLKO,#00000000B     ;ENABLE BRT(=4),T1(=2) T0(=1) HAVE CLOCK OUTPUT BRT@P1.0 T1@P3.5 T0@P3.4
MOV BRT, #BRTLOAD            ;RELOAD 1152000
MOV AUXR,#01011101B          ;T0x12,T1x12,UART_M0x6,BRTRUN,S2SMOD,BRTx12,EXTRAM,S1BRS
;MOV AUXR1, #00010000B        ;MOVE UART2 TO TX2=P4.3 RX2=4.2
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
SETB ET1                     ;ENABLE T1 INTERRUPT
SETB TR1                     ;RUN T1

LCALL INITIAL_UART2          ;USE BRT AS SERIAL BAUD GENERATE FOR UART2
SETB  EA                     ;ENAABLE ALL INTERRUPT
MOV P2, #10101010B           ;SHOW START   
LCALL CLEANRAM

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

SCANNER:
SCANP2:              ; SHIFT P2 AND READ P0
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
MOV 35H, #0          ;THIS WILL ADD TO ROW TO MAKE 0-7
CLR C
SCANP2A:
MOV A, 50H
RRC A
MOV 50H, A
MOV P2, A            ;P2 ONE ROW LOW
LCALL DELAY4         ;MUST WAIT STABLE
MOV A, P0            ;READ FROM P0
CPL A
LCALL STOREDATA
SCANNEXT1:
DJNZ 32H, SCANP2A
MOV P2, #11111111B   ;END OF SCANP2

SCANP3:              ; SHIFT P3 AND READ P0
MOV 32H, #8          ;8 BITS TO SHIFT
MOV 50H, #11111111B  ;THIS BYTE FOR SHIFT AND OUTPUT TO P2
MOV 35H, #8          ;THIS WILL ADD TO ROW TO MAKE 0-7
CLR C
SCANP3A:
MOV A, 50H
RRC A
MOV 50H, A
MOV P3, A            ;P2 ONE ROW LOW
LCALL DELAY4         ;MUST WAIT STABLE
MOV A, P0            ;READ FROM P0
CPL A
LCALL STOREDATA
SCANNEXT2:
DJNZ 32H, SCANP3A
MOV P3, #11111111B   ;END OF SCANP
NOP                  ;CHECK BUFFER AND SENT
MOV A, R0            
XRL A, R1
JZ SCANNEREXIT       ;R0 R1 EQUAL NO NEW BYTE
LCALL OUTBUFFER
SCANNEREXIT:
JMP SCANNER

PUTBUFFER:
MOV @R1, A
CJNE R1, #LASTBUFFER, NEXTR1
MOV R1, #FIRSTBUFFER
JMP PUTBUFFEREXIT
NEXTR1:
INC R1  ;POINT TO NEXT BUFFER
PUTBUFFEREXIT:
RET

OUTBUFFER:
MOV A, @R0
LCALL SENTONEBYTE2
CJNE R0, #LASTBUFFER, NEXTR0
MOV R0, #FIRSTBUFFER
JMP OUTBUFFEREXIT
NEXTR0:
INC R0  ;POINT TO NEXT BUFFER
OUTBUFFEREXIT:
RET

STOREDATA:           ;32H CONTAIN ROW UMBER THAT CAUSE LOW
PUSH PSW
MOV 34H, #8          ;8 BIT TO SHIFT
MOV 33H, A           ;A CONTAIN 8BITS WITH FEW HIGH(CAUSE BY KEYPRESS)
STOREDATA1:
LCALL COUNTPOSITION  ;CODE BY SCANNER 4C 54 COUNT BY
LCALL KEYMAP         ;RETURN KEYNUMBER A AFTER LOOKUP THE MAP 3D BD
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
JNC DOKEY1           ;CONTACT POINT NOT CONTACT GO NOTEOFF SUBROTINE
LCALL NOTEON         ;NOTEON CHECK
JMP STOREDATANEXT
DOKEY1:
LCALL NOTEOFF        ;NOTEOFFCHECK
STOREDATANEXT:
DJNZ 34H, STOREDATA1
DOKEYEXIT:
POP PSW
RET

NOTEON:
CLR TR1              ;TIMER1 STOP
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
MOV A, #1
MOVX @DPTR, A        ;CONTACT JUST START, PUT 1 FOR COUNT UP BY TIMER EVERY 1MS
JMP NOTEONEXIT
;-----------------
NOTEON1:
MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7
MOV DPH, #0
MOV DPL, A
MOVX A, @DPTR        ;READ VELOCITY
JZ NOTEONEXIT        ;UPPER KEY NOT YET CONTACTED, DO NOTHING
MOV 3BH, A           ;SAVE VELOCITY
INC A
JZ NOTEONEXIT        ;IF FFH THEN ZERO MEAN NOTE ALREADY OUTPUT, NEED WAIT FOR NOTEOFF, DO NOTHING
MOV A, #10010000B    ;MIDI NOTEON CHANNEL1
LCALL PUTBUFFER      ;SENT KEY NUMBER
MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7
LCALL PUTBUFFER      ;SENT KEY NUMBER
MOV A, 3BH
LCALL PUTBUFFER      ;SENT VELOCITY   
MOV A, 3AH
ANL A, #01111111B    ;MASKING BIT7
MOV DPH, #0
MOV DPL, A
MOV A, #0FFH
MOVX @DPTR, A        ;MARK AS FFH WAIT FOR RELEASE AND SENT NOTEOFF
NOTEONEXIT:
SETB TR1
RET

NOTEOFF:
CLR TR1
MOV A, 3AH      
RLC A                ;CHECK UPPER OR LOWER
JC NOTEOFFEXIT       ;LOWER KEY SO DO NOTHING
NOP                  ;UPPER KEY RELEASE, CHECK 0FFH FOR SENT NOTEOFF
MOV DPH, #0
MOV DPL, 3AH
MOVX A, @DPTR        ;READ OLD DATA
INC A
JNZ NOTEOFFEXIT      ;IF FFH THEN ZERO MEAN NO NOTE OFF NEED, DO NOTHING
;--SENT NOTEOFF
MOV A, #10000000B    ;MIDI NOTEON CHANNEL1
LCALL PUTBUFFER      ;SENT KEY NUMBER
MOV A, 3AH
LCALL PUTBUFFER
MOV A, #0
LCALL PUTBUFFER
MOV DPH, #0
MOV DPL, 3AH
MOV A, #0
MOVX @DPTR, A        ;MARK THAT KEY LOCATION 0 TO RECEIVED NEW CONTACT PRESS
NOTEOFFEXIT:
SETB TR1
RET

COUNTPOSITION:
PUSH PSW
MOV A, 32H        ;ROW POSITION 1-8
ADD A, 35H        ;IF P2 THEN ADD 0(REMAIN 1-8), IF P3 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.....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

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

TIMER_1:  ;USE FOR MICRO CLOCK 1MS 184, 30 ,100US=248 250
PUSH ACC
PUSH PSW
MOV 42H, #128
MOV DPH, #0
TIMERLOOP:
MOV DPL, 42H
MOVX A, @DPTR
JZ TIMER_1NEXT
CJNE A, #0FFH, TIMERLOOP1  ;NOTEOFF NEED
CPL P1.7
JMP TIMER_1NEXT
TIMERLOOP1:
CJNE A, #0FEH, TIMER_1A    ;NOT YET MAX
JMP TIMER_1NEXT
TIMER_1A:
INC A
MOVX @DPTR, A
TIMER_1NEXT:
DJNZ 42H, TIMERLOOP
TIMER_1EXIT:
MOV TH1, #248
MOV TL1, #250
POP PSW
POP ACC
RETI

SENTONEBYTE2:        ;A SENT OUT
PUSH ACC
MOV IE2, #00H        ;DISABLE THE SECONDARY UART INTERRUPT, ES2=0
MOV S2BUF, A         ;LOAD A TO BUFFER
MOV A, S2CON         ;1111,1101, CLEAR SECONDARY UART TRANSIMIT INTERRUPT FLAG
ANL A, #0FDH
MOV S2CON, A
UART2WAIT:
MOV A, S2CON
ANL A, #02H          ;0000,0010
CJNE A,#02H, UART2WAIT
MOV A, S2CON
ANL A, #0FDH         ;1111,1101, CLEAR SECONDARY UART TRANSIMIT INTERRUPT FLAG
MOV S2CON, A
MOV IE2, #01H        ;ENABLE THE SECONDARY UART INTERRUPT, ES2=1
NOP
NOP
POP ACC
RET

DELAY4:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET

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

UART1:
RETI

ADC:
RETI

PCA:
RETI

LVD:
RETI

SPI:
RETI

UART2: ;NO READ
RETI

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

CLEANRAMB:
MOV DPH,#1
MOV DPL, #0
CLEANRAMB1:
MOV A, #0
MOVX @DPTR, A
INC DPL
MOV A, DPL
JNZ CLEANRAMB1
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 SCAN CODE POSITION
;OPTAIN LOWER CONTACT POINT'S SCAN CODE MANUALLY AND PUT KEYNUMBER+128 AT SCAN CODE POSITION

;  00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 0BH 0CH 0DH 0EH 0FH
;  ---------------------------------------------------------------
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  0F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  1F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  2F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  3F
DB 00H,00H,00H,00H,00H,00H,00H,00H,39H,3AH,3BH,3CH,3DH,00H,00H,00H ;0 80  4F
DB 0B9H,0BAH,0BBH,0BCH,0BDH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 96  5F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;0 16  6F
DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H ;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

回復

使用道具 舉報

9#
ID:123289 發表于 2018-2-16 11:02 | 只看該作者
樓主果然聰明,一點就通,悟性好。未來不可限量。祝你春節快樂!
回復

使用道具 舉報

10#
ID:123289 發表于 2018-2-16 11:14 | 只看該作者
硬件上:你用了5個口,滿算是40個IO
你需要:61*2=122個口
建議用:4路掃描,乘以31個口。掃描路數越少,用時越短。這個程序主要矛盾是速度!
回復

使用道具 舉報

11#
ID:123289 發表于 2018-2-16 14:21 | 只看該作者
硬件IO的排列有講究。你需要用最短的掃描時間,捕捉到是哪個按鍵按下了。
所以同一個琴鍵是的兩個鍵,不要放在同一個P口上。
要點:
1、不要用防彈動程序,以節省時間,一次即認可。
2、一次讀8個鍵,無鍵立即轉讀下8個鍵,如此,在無鍵的情況下,讀16次P口即可完成對所有鍵掃描。
3、如果有鍵,則再花點時間區分是哪個鍵,需要起動哪個計時器。
4、另一種更好的方案是,用IO口中斷:
正常輪流掃四路通道,中斷后先查是哪個Px產生了中斷,再查掃描的是哪一路,就能確定是哪個鍵了。

回復

使用道具 舉報

12#
ID:123289 發表于 2018-2-16 14:28 | 只看該作者
時間中斷后,輪查122個計時器。為0的放棄,不為0的+1計時。
掃到第一路鍵(合理的安排是,61個第一路鍵放于前兩路掃描中;另61個第二路鍵放在后兩路掃描中)置1,掃到第二路鍵取對應計時器值分析力度,用后清0.
回復

使用道具 舉報

13#
ID:123289 發表于 2018-2-16 14:29 | 只看該作者
真正的編程序,是你如何構思方案。寫程序并不重要。

評分

參與人數 1黑幣 +8 收起 理由
arthuryu + 8 很給力!

查看全部評分

回復

使用道具 舉報

14#
ID:283954 發表于 2018-2-16 16:57 | 只看該作者
我剛測定過,空鍵時掃描一次的時間包括處理為1.584ms, 一鍵時是1.592ms, 五鍵同按是1.618ms, 一秒鐘能檢測到大概500次按鍵,以電子琴來說速度可以了,這琴鍵按鈕是拆廠家成品電子琴來試的,是16X8的行列,16位兩個接口P2P3為輸出,8位為輸入P0, 所以得根據這樣的結構編程, 我在寫的時候才發現就算沒有什么鍵按下還得逐個檢查記憶體的,因為要查出0FFH再發出noteoff信號,這里面有個憂慮就是擔心在檢查記憶體時產生時鐘中斷改變了DPL而讀錯,  所以開始時先關掉時鐘,檢查完再開時鐘,應該會影響到時鐘進位的精度。那個LCALL DELAY2 是個惡夢,不是防抖動用的,原來STC單片機的輸出有滯后,在輸出0后,再回復1會滯后,造成誤讀,所以要延時讓輸出穩定,這現象讓我花費了一天時間才發現。關于用IO中斷,STC單片機好像沒有提供這個功能,無法實現。
這程序若可以用我就會制作一個電路板來試,可以的話就用來取代原來那臺電子琴的電路板,變成無線電子琴了。

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

15#
ID:283954 發表于 2018-2-20 15:02 | 只看該作者
過年前得高人指點,得61鍵力度點子,經二夜碼字,DIY電子琴看來得以誕生,又經春節三日無事干,畫線路為樂,得線路板設計一片,上載與電子愛好者共享:

這板子上右好幾個IC, 從右邊起:

1。第一個CPU專門掃描琴鍵用,掃好的碼本來通過UART輸出midi碼就可以讓音源發出聲音了,但標準MIDI的串口波特率是31250BPS,十個位元得等待320us, 會影響力度進位時鐘t1的運作,所以改用并口p1輸出到第二個CPU處理。

2。第二個CPU接收到第一個CPU送來的MIDI碼后,經過分析處理后再送往UART2的藍牙模塊發送,由于市場上的藍牙模塊只支持38400的波特率,為了能同時支持標準的5pin midi 插口輸出,打算同時用UART1作標準31250輸出。

3.  充電模塊TP4056,由于采用18650鋰電池供電,得有充電裝置。

4.  穩壓IC HT7833 讓電壓保持3.3V,另有HT7030電壓檢測IC,當電池電壓小于3.0V時關閉HT7833,防止電池過度放電而損壞。

5。觸摸開關TTP223,通常DIY最難看的是部分是開關和按鈕,改用觸摸開關就好看許多。

6。USB MIDI CH345 IC 提供電腦接口,在不使用無線方式時可直接插入電腦使用,也同時為電池充電。

等過年后淘寶開店讓電路板公司打樣10片就能測試了。



評分

參與人數 1黑幣 +100 收起 理由
admin + 100 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91久色| 亚洲九九 | 国产精品久久久久久久久免费高清 | 国产视频在线观看一区二区三区 | 一本一道久久a久久精品综合蜜臀 | 亚洲精品在线免费 | 在线观看中文字幕视频 | 欧美日韩精品在线免费观看 | 国产精品一区二区日韩 | 午夜合集 | 欧美日韩不卡 | 亚洲精品第一页 | 国产福利在线播放 | 精品一二 | 欧美精品在线播放 | 精品二三区 | 国产精品久久久久久久久免费高清 | 日韩一区二区三区在线 | 久久国产精品-久久精品 | 在线第一页 | 日韩一区二区在线播放 | 亚洲国产高清高潮精品美女 | www.玖玖玖 | 成人精品视频在线观看 | 一区二区三区在线播放视频 | 国产精品久久久久久久久久免费看 | 日韩一区二区三区四区五区六区 | 国内精品视频免费观看 | 国产精品福利网 | 国产精品久久久亚洲 | 国产91精品久久久久久久网曝门 | 蜜桃视频在线观看免费视频网站www | 国产一区二区在线播放 | 中国黄色在线视频 | 亚洲高清在线观看 | 国产一区二区三区在线 | 一级片网址 | 精品国产99 | 高清一区二区 | 精品国产免费一区二区三区五区 | 成人精品一区二区 |