【DIY参赛】AT89C2051制作的节拍器
本人偶尔弹一下吉它,有一个节拍器还是挺有帮助练习的。曾经想过用555振荡,CD4017指示做节拍器,却未付诸实施。但认识了单片机之后,很多想法都更容易实现了。最开始学习了51系列,用的是AT89S52——因为可以ISP,编程容易。2051/4051体积更小,但需要编程器。后来用AT89S52做了个2051的编程器,才把早前买的那芯片用起来。 当然,现在我喜欢用AVR系列了,这是题外话。节拍器的任务就是按照既定的延时提供声、光指示,2051完全可以胜任。我用4位共阳数码管(每个8字的阳极是连在一起的)来进行动态扫描显示,引脚正好够用。外围电路也没有独特的地方,四个按键是利用动态扫描的时候进行检测的。
还是洞洞板制作,用了一点贴片电阻。那时候还没有用贴片电容。虽然AT89C2051手册说需要3V电压以上,实际我用两节镍氢电池完全可以工作(6MHz),电流也不大,数码管不用限流电阻。
先前做的了一个送给朋友了,现在这个额外加了一点功能,跟节拍器无关,所以上面多了几个元件。这个芯片是4051,ROM大一点。
复位过后节拍器进入设置模式,第一个数字显示每小节几拍子(2/3/4/6/8),后三个数字显示每分钟多少拍(24-240调节)。三个按钮是设定这两参数用的。另一个按钮是进入节拍显示模式和蜂鸣开关。我这个板子上面多出来的一个按钮与节拍器无关。
2/3/4拍子利用数码管笔划中间那一横来指示,6/8拍子则用下面的两个竖笔划。在每小节第一拍,绿色LED闪亮和蜂鸣的声音都要长一点。
最后附上程序。我没用过C语言写51程序,也不打算用C来写51的程序,所以是汇编的。
;tempo.asm version 0.2,(Dec. 23rd, 2006)
;
;for AT89C2051/4051 with 6MHz crystal
led1equ 33h
led2equ 32h
led3equ 31h
led4equ 30h
displayequ 34h
tempo equ 35h
rlskeyequ 36h
tlong1equ 37h
tlong2equ 38h
rdelayequ 39h
tdelayL equ 3Ah
tdelayH equ 3Bh
beat equ 3Ch
bbequ 3Dh
dummy equ 3Eh
keydown equ 20h.7 ; bit flag
fastkey equ 20h.6
mmode equ 20h.5
bdark equ 20h.4
beep equ 20h.3
keypadequ 21h
mute equ 22h.2
pri equ 22h.1
indoffequ 22h.0
p0H equ 5Ah
p0L equ 28h
p1H equ 2Fh
p1L equ 53h
ORG 0
AJMP start
ORG 0Bh ; interrupt TF0
XCHA,display
JMP @A+DPTR
ORG 30h
start:
MOV SP, #60h
MOV display,#0
MOV keypad,#0Fh
MOV 20h, #0 ; clear all flags
MOV DPTR, #dispfunc
MOV R4, #3
MOV R3, #10
MOV A, tdelayH
CJNE A, p0H, resetmem
CJNE A, p1H, resetmem
MOV A, tdelayL
CJNE A, p0L, resetmem
CJNE A, p1L, resetmem
AJMP rmem
resetmem:
MOV tdelayH, #03h
MOV tdelayL, #0E8h; 1000 for 120 bpm
MOV tempo, #120
MOV beat, #4
MOV 22H, #2
rmem:
MOV R7, tdelayH
MOV R6, tdelayL
INC R7
MOV A, tempo
ACALL showtempo
ACALL showbeat
MOV TMOD, #02h ; Timer 0, 8bit auto reload mode
MOV TH0, #6 ; preset 250 counts, 0.5 ms for 6MHz crystal
MOV TL0, #6
MOV IE, #82h ; enable interrupts, set EA and ET0
SETB TR0 ; start timer 0
main: ;The main loop
ORL PCON,#1 ;Enter IDLE mode and wait for Timer interrupt
JNB beep, a1
CPL P3.0 ; generate 1000Hz square wave
a1: MOV A, keypad
CJNE A, #0Fh, chkkey
DJNZ rlskey, meter ; wait for 50ms before read next key
; auto exec every 256 cycles, when no key
MOV tlong1, #30
MOV tlong2, #40
CLR fastkey
CLR keydown ; reset key states
JB mmode, meter ; skip when in meter mode
DJNZ R4, meter ; R4 controls the freqency of blinking
JBC bdark, a2
SETB bdark ; next time it will go dark
MOV A, #0FFh
MOV led1, A
MOV led2, A
MOV led3, A
MOV led4, A ; clear digital display
MOV R4, #4
DJNZ R3, meter ; R3 controls the idle time of setting mode
MOV 22h, #4 ; initially muted
AJMP chmm ; auto change to beat mode, to save power
a2: MOV A, tempo
ACALL showtempo
ACALL showbeat
MOV R4, #3
meter:
DJNZ R5, a3 ; R5 controls the time of sound/light
SETB P3.1 ; turn off the flash LED
CLR beep
SETB P3.0
a3: DJNZ R6, main
MOV R6, #0
DJNZ R7, main
MOV R7, tdelayH
MOV R6, tdelayL ; reload values for R6 and R7
CJNE R6, #0, a4
DEC R7
a4: INC R7
AJMP showtick
chkkey:
JB keydown, keydelay
MOV R3, #10
SETB keydown
MOV rlskey, #100
which:CJNE A,#0Dh,key234
JB mmode, chms ; key 1
MOV A, tempo
CJNE A, #240, tinc
AJMP meter
key234: CJNE A,#0Eh,key34
JB mmode, chms ; key 1
MOV A, tempo
CJNE A, #24, tdec
AJMP meter
key34:CJNE A,#0Bh,key4
JB mmode, chms ; key 3
MOV A,beat
INC A
CJNE A,#5,sbn5
INC A ; 5 --> 6
sbn5: CJNE A,#7,sbn7
INC A ; 7 --> 8
sbn7: CJNE A,#9,sbn9
MOV A, #2 ; 9 --> 2
sbn9: MOV beat, A
ACALL showbeat
AJMP meter
key4: CJNE A,#7h, lwait
JNB fastkey, chls
AJMP poweroff ; turn off power if long hold this key
chms: CLR mmode
MOV A, tempo
ACALL showtempo
ACALL showbeat
AJMP meter
chmm: SETB mmode
MOV bb, #0
MOV R7,#1 ; cause no delay
lwait:AJMP meter
keydelay:
JB fastkey, repeat
DJNZ tlong1, lwait
MOV tlong1, #30
DJNZ tlong2, lwait
MOV tlong2, #40
SETB fastkey
MOV rdelay, #1
repeat: DJNZ rdelay, lwait
MOV rdelay, #30
AJMP which
tinc: MOV R0, A ; save the value
CLR EA ; disable interrupt
MOV DPTR, #(timetable-24)
MOVC A,@A+DPTR
MOV DPTR, #dispfunc
SETB EA
XCH A,tdelayL
CLR C
SUBB A,tdelayL
MOV tdelayL,A
JNC a10
DEC tdelayH
a10: MOV A, R0
INC A
MOV tempo, A
ACALL showtempo
AJMP meter
tdec: DEC A
MOV tempo, A
MOV R0, A
CLR EA ; disable interrupt
MOV DPTR, #(timetable-24)
MOVC A,@A+DPTR
MOV DPTR, #dispfunc
SETB EA
ADD A,tdelayL
MOV tdelayL,A
JNC a11
INC tdelayH
a11: MOV A, R0
ACALL showtempo
AJMP meter
chls: JNB mmode,chmm
MOV A,22H
INC A
ANL A, #7
CJNE A, #6, a12
CLR A
a12: MOV 22H, A
AJMP chmm
showtempo:
CLR EA ; disable interrupt
MOV DPTR,#ledtable
MOV B, #100
DIV AB
MOVC A,@A+DPTR
MOV led3, A
MOV A, #10
XCH A,B
DIV AB
MOVC A,@A+DPTR
MOV led2, A
XCH A,B
MOVC A,@A+DPTR
MOV led1, A
MOV DPTR,#dispfunc
SETB EA ; enable interrupt
RET
showbeat:
CLR EA ; disable interrupt
MOV DPTR,#ledtable
MOV A, beat
MOVC A,@A+DPTR
ANL A,#0DFh ; enable the "dot"
MOV led4, A
MOV DPTR,#dispfunc
SETB EA ; enable interrupt
RET
showtick:
CLR P3.1 ; turn on the flash LED
JB mmode, a5
MOV R5, #2 ; in setting mode, light 1 ms
AJMP main
tickone:
MOV R5, #200 ; light 100 ms, for the 1st tick
AJMP a6
a5: MOV A, bb
JZ tickone
MOV R5, #20 ; except the first tick, light 10 ms
JB pri, a7
a6: JB mute, a7
SETB beep
CLR P3.0 ; enable sound
a7: MOV A,#0FFh
MOV led1,A
MOV led2,A
MOV led3,A
MOV led4,A ; clear all LEDs
JB indoff, bbq ; skip display index
MOV A,beat
ADD A,#2
JB ACC.3, beat_68
ANL A, #3
JZ beat_2
; beat_34
MOV A, bb
ADD A, #led4
MOV R0, A
MOV @R0, #0F7h
AJMP bbq
beat_68:
MOV A,bb
JB ACC.0, ddot
MOV dummy, #07Fh
AJMP divby2
ddot:
MOV dummy, #0EFh
divby2:
RRC A ; C=0 since "ADD A,#2 will not overflow"
ADD A, #led4
MOV R0, A
MOV @R0, dummy
AJMP bbq
beat_2:
MOV A,bb
JZ bb2_0
MOV led2, #0F7h
AJMP bbq
bb2_0:
MOV led4, #0F7h
bbq:MOV A,bb
INC A
CJNE A, beat, bbx
CLR A
bbx:MOV bb,A
AJMP main
dispfunc:
SETB P3.3
MOV P1, led1
CLR P3.7
MOV A,#(show2-dispfunc)
XCH A,display
MOV C, P3.2
MOV keypad.0, C
RETI
show2:SETB P3.7
MOV P1, led2
CLR P3.5
MOV A,#(show3-dispfunc)
XCH A,display
MOV C, P3.2
MOV keypad.1, C
RETI
show3:SETB P3.5
MOV P1, led3
CLR P3.4
MOV A,#(show4-dispfunc)
XCH A,display
MOV C, P3.2
MOV keypad.2, C
RETI
show4:SETB P3.4
MOV P1, led4
CLR P3.3
MOV A,#0
XCH A,display
MOV C, P3.2
MOV keypad.3, C
RETI
poweroff:
MOV p0H, tdelayH
MOV p1H, tdelayH
MOV p0L, tdelayL
MOV p1L, tdelayL
MOV A, 22H
JNZ a30
MOV A, #6
a30:DEC A
MOV 22H, A
MOV led3, #28h
MOV led2, #71h
MOV led1, #71h
SETB P3.0
SETB P3.1
MOV R7, #6
a31:ORL PCON,#1
DJNZ R6, a31
MOV R6, #200
DJNZ R7, a31
MOV P1, #0FFh
MOV P3, #0FFh
ORL PCON, #2h ; power down mode
AJMP main ; no effect , powered down
ledtable:
DB 28h, 0EEh, 32h, 0A2h, 0E4h, 0A1h, 21h, 0EAh, 20h, 0A0h
timetable:
DB 200, 185, 171, 158, 148, 138, 129, 121, 114, 107, 100, 96, 90, 85, 81, 77,
DB 73, 70, 66, 64, 60, 58, 56, 53, 51, 49, 47, 45, 44, 42, 40, 39, 38, 36, 35,
DB 34, 33, 32, 30, 30, 29, 28, 27, 26, 26, 25, 24, 23, 23, 22, 22, 21, 21, 20,
DB 19, 19, 19, 18, 17, 17, 17, 17, 16, 15, 16, 15, 14, 15, 14, 13, 14, 13, 13,
DB 13, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 10, 9, 8,
DB 9, 9, 8, 8, 8, 8, 8, 8, 8, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 6, 6, 6,
DB 6, 6, 5, 6, 6, 5, 6, 5, 5, 6, 5, 5, 5, 5, 5, 5, 4, 5, 5, 4, 5, 4, 5, 4, 4,
DB 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 3, 4, 3, 4, 3, 4, 3, 3, 4, 3,
DB 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 2, 3, 2, 3,
DB 3, 2, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2
END
[ 本帖最后由 d3b7 于 2009-7-24 14:56 编辑 ] 能整单片机的在我眼里都很NB
貌似70年代《无线电》也有个节拍器电路 不知作用是不是一样的? 相当不错.:victory: 有注释就好了。:lol :lol :lol 有一个时期雅马哈琴的节拍显示是用数码管的小数点显示:lol
请问一下2051这个芯片的内部资源
俺好奇,在长汀购了几个,但现在没有电脑看不了它的文档,不知道它能用来干吗。俺想请问有它的图片形式的资料文档吗,俺用手机也只能看到图片。 楼主上个原理图好吧:lol :lol :lol
页:
[1]