找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3234|回复: 14
收起左侧

51单片机要如何同时测定61个电子琴按键的力度(速度)

[复制链接]
ID:283954 发表于 2018-2-13 14:49 | 显示全部楼层 |阅读模式
各位好!

我是新手,请大家多关照,最近想设计一台用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 赞一个!

查看全部评分

回复

使用道具 举报

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.
如果要分得更细,则需增加计数器的位数。
回复

使用道具 举报

ID:123289 发表于 2018-2-14 16:43 | 显示全部楼层
当然-1也可以,看你爱好。
回复

使用道具 举报

ID:283954 发表于 2018-2-14 17:56 | 显示全部楼层
yzwzfyz你好!
果然有好办法,我这两天试着自己想办法,把计数器的值写在记忆区的笨办法,越写越乱,快要放弃,但作为初学者,这种磨炼还是应该的,现在有好办法了,今晚应该就能写好了,多谢指教。
回复

使用道具 举报

ID:123289 发表于 2018-2-14 23:43 | 显示全部楼层
我看你是用汇编写程序的,是真想学好单片机的,故点一下。
回复

使用道具 举报

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

回复

使用道具 举报

ID:123289 发表于 2018-2-16 11:02 | 显示全部楼层
楼主果然聪明,一点就通,悟性好。未来不可限量。祝你春节快乐!
回复

使用道具 举报

ID:123289 发表于 2018-2-16 11:14 | 显示全部楼层
硬件上:你用了5个口,满算是40个IO
你需要:61*2=122个口
建议用:4路扫描,乘以31个口。扫描路数越少,用时越短。这个程序主要矛盾是速度!
回复

使用道具 举报

ID:123289 发表于 2018-2-16 14:21 | 显示全部楼层
硬件IO的排列有讲究。你需要用最短的扫描时间,捕捉到是哪个按键按下了。
所以同一个琴键是的两个键,不要放在同一个P口上。
要点:
1、不要用防弹动程序,以节省时间,一次即认可。
2、一次读8个键,无键立即转读下8个键,如此,在无键的情况下,读16次P口即可完成对所有键扫描。
3、如果有键,则再花点时间区分是哪个键,需要起动哪个计时器。
4、另一种更好的方案是,用IO口中断:
正常轮流扫四路通道,中断后先查是哪个Px产生了中断,再查扫描的是哪一路,就能确定是哪个键了。

回复

使用道具 举报

ID:123289 发表于 2018-2-16 14:28 | 显示全部楼层
时间中断后,轮查122个计时器。为0的放弃,不为0的+1计时。
扫到第一路键(合理的安排是,61个第一路键放于前两路扫描中;另61个第二路键放在后两路扫描中)置1,扫到第二路键取对应计时器值分析力度,用后清0.
回复

使用道具 举报

ID:123289 发表于 2018-2-16 14:29 | 显示全部楼层
真正的编程序,是你如何构思方案。写程序并不重要。

评分

参与人数 1黑币 +8 收起 理由
arthuryu + 8 很给力!

查看全部评分

回复

使用道具 举报

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 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

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 单片机教程网

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