由于一项任务的要求,我需要一个可以编程并且可以输出ttl信号的设备,于是我就开发了一个基于AT89s52的单片机系统,虽然花了不少功夫,但还是值得回忆的。
这个“电脑”并不是传统意义上的IBM PC,它使用了Atmel公司的AT89s52单片机,其中包括了它的处理器、内存和用于存储固件的闪存,它的主频并不高,仅仅12Mhz,但是用来控制周边的简单的硬件已经绰绰有余了。周边硬件也做了尽可能丰富的设计,它们是一个四段共阳极LED数码管,一个蜂鸣器,一组人体工程学设计的按键(其中有一个按键可以通过跳线设置不同的功能),两套供电接口,一个简易ISP/扩展按键接口,一个简易串行通讯接口,一个接线桥等等,这样设计的目的是考虑到以后的扩展问题,因为我不能为了一个任务制作一个设备,这样太耽误时间了。
这是硬件系统的俯视图,包含了一个25针并口的isp下载线,和一个5v的稳压电源,考虑到随身携带的需要,整个系统采用了坚固化设计,可以说上边没有任何元件会被轻易的弄倒,比较脆弱的元件我都将它“藏”了起,加以保护。
由于设备有限和电路的简化,全部元件都被安排到一张实验板上,其制作成本并不高,大约10块钱左右,加上附属设备也不过20元,功能尽可能通过程序实现是它的一个特点,比如LED数码管的动态显示,就完完全全的用程序实现的。
这是实验板的背面,是一个没有“桥”的布局,大大减少了由于老化造成的短路。
固件使用Keil uV3在Windows平台下开发,源代码为汇编语言,程序如下:
;at89s52
t2con data 0c8h
t2mod data 0c9h
rcap2l data 0cah
rcap2h data 0cbh
tl2 data 0cch
th2 data 0cdh
tr2 bit 0c8h.2
tf2 bit 0cfh
et2 bit 0a8h.5
;variables
disSwap equ 30h ;30h,31h,32h,33h
SysMark equ 34h
disWords equ 35h ;35h,36h,37h,38h
keyCode equ 39h
keyLast equ 3ah
subProgMark equ 3bh
org 0000h
jmp initialize
org 02bh
jmp systemProcess
org 0040h
;interrupts
systemProcess:
call ScanScreen
mov keyCode,p1
clr tf2
reti
;functions
transWords:
push dph
push dpl
push acc
mov dptr,#ledCodeTab
mov a,disWords
movc a,@a+dptr
mov disSwap,a
mov a,disWords+1
movc a,@a+dptr
mov disSwap+1,a
mov a,disWords+2
movc a,@a+dptr
mov disSwap+2,a
mov a,disWords+3
movc a,@a+dptr
mov disSwap+3,a
pop acc
pop dpl
pop dph
ret
ledCodeTab:
db 0a0h,0bbh,62h,2ah,39h,2ch,24h,0b8h,20h,38h,30h,25h,0e4h,23h,64h,74h
ScanScreen:
push acc
push b
mov a,r0
push acc
mov p2,#0
inc SysMark
mov a,SysMark
mov b,#4
div ab
mov a,b
add a,#disSwap
mov r0,a
mov p0,@r0
mov r0,b
inc r0
mov a,#01h
ScanScrA:
rr a
djnz r0,ScanScrA
mov p2,a
pop acc
mov r0,a
pop b
pop acc
ret
clean:
mov disSwap,#0ffh
mov disSwap+1,#0ffh
mov disSwap+2,#0ffh
mov disSwap+3,#0ffh
ret
getSubHead:
push acc
push b
mov dptr,#subProgEnt
mov b,#3
mov a,subProgMark
div ab
mov a,b
rl a
movc a,@a+dptr
push acc
mov a,b
rl a
inc a
movc a,@a+dptr
mov dpl,a
pop dph
pop b
pop acc
ret
;main
initialize:
;system
orl 8eh,#1
setb ea
mov p1,#0ffh
mov rcap2l,#80h
mov rcap2h,#0f0h
mov tl2,rcap2l
mov th2,rcap2h
setb et2
setb tr2
;welcome
mov subProgMark,#0
jmp leader
subProgEnt:
dw light,stopGame,monitor
leader:
call getSubHead
;display sub logo
clr a
movc a,@a+dptr
mov disSwap,a
mov a,#1
movc a,@a+dptr
mov disSwap+1,a
mov a,#2
movc a,@a+dptr
mov disSwap+2,a
mov a,#3
movc a,@a+dptr
mov disSwap+3,a
;scan keys
mov a,keyCode
cjne a,keyLast,leader_progKey
ajmp leader
leader_progKey:
mov b,a
anl a,#1h
jnz leader_progKeyNextA
inc subProgMark
leader_progKeyNextA:
mov a,b
anl a,#2h
jnz leader_progKeyNextB
dec subProgMark
leader_progKeyNextB:
mov a,b
anl a,#4h
jnz leader_progKeyNextc
mov a,#4
jmp @a+dptr
leader_progKeyNextC:
mov a,b
anl a,#8h
jnz leader_progKeyNextD
mov a,#4
jmp @a+dptr
leader_progKeyNextD:
mov keyLast,b
ajmp leader
;Subs
;light
light:
db 9bh,6eh,20h,6eh
jmp light_main
light_disFreq:
push acc
mov a,rcap2h
anl a,#0fh
mov disWords+1,a
mov a,rcap2h
anl a,#0f0h
swap a
mov disWords,a
pop acc
call transWords
ret
light_keyUDown:
inc rcap2h
call light_disFreq
ret
light_keyLDown:
inc rcap2h
call light_disFreq
ret
light_keyRDown:
dec rcap2h
call light_disFreq
ret
light_keyDDown:
dec rcap2h
call light_disFreq
ret
light_main:
mov disWords,#8
mov disWords+1,#8
mov disWords+2,#8
mov disWords+3,#8
call transWords
light_loop:
mov a,keyCode
cjne a,keyLast,light_progKey
ajmp light_loop
light_progKey:
mov b,a
anl a,#1h
jnz light_progKeyNextA
call light_keyUDown
light_progKeyNextA:
mov a,b
anl a,#2h
jnz light_progKeyNextB
call light_keyLDown
light_progKeyNextB:
mov a,b
anl a,#4h
jnz light_progKeyNextc
call light_keyRDown
light_progKeyNextC:
mov a,b
anl a,#8h
jnz light_progKeyNextD
call light_keyDDown
light_progKeyNextD:
mov keyLast,b
ajmp light_loop
;light end
;stopGame
stopGame:
db 42h,52h,52h,72h
ajmp stopGame_main
stopGame_main:
stopGame_loop:
call transWords
mov c,p1.0
mov a,disWords
addc a,#0
anl a,#0fh
mov disWords,a
mov c,p1.1
mov a,disWords+1
addc a,#0
anl a,#0fh
mov disWords+1,a
mov c,p1.2
mov a,disWords+2
addc a,#0
anl a,#0fh
mov disWords+2,a
mov c,p1.3
mov a,disWords+3
addc a,#0
anl a,#0fh
mov disWords+3,a
ajmp stopGame_loop
;stopGame end
;monitor
monitor:
db 0ah,0e4h,0eeh,0aah
ajmp monitor_main
monitor_main:
mov tmod,#20h
mov tl1,#0f3h
mov th1,#0f3h
mov pcon,#80h
clr es
setb tr1
mov scon,#50h
call clean
;clr et2
;clr tr2
;call ScanScreen
;call ScanScreen
;call ScanScreen
;call ScanScreen
monitor_loop:
jnb ri,$
clr ri
mov b,sbuf
mov a,b
anl a,#0fh
mov disWords+3,a
mov a,b
anl a,#0f0h
swap a
mov disWords+2,a
jnb ri,$
clr ri
mov b,sbuf
mov a,b
anl a,#0fh
mov disWords+1,a
mov a,b
anl a,#0f0h
swap a
mov disWords,a
call transWords
;setb et2
;setb tr2
jb p1.0,$
;clr et2
;clr tr2
ajmp monitor_loop
;monitor end
end
其中包括一个负责控制硬件的系统内核和三个小程序,用户可以根据自己的需要利用随意添加自己的小程序,格式很简单,模仿就可以了。
内核的大致思想是利用定时器2每隔一定的时间产生一个中断,在这个中断中系统干刷新屏幕(每次一位)、控制发声等事情,应用程序只需要告诉系统需要做什么(写到内存中),系统就会去处理,比如将需要显示的东西写到disSwap中,这些字符就会自动显示到LED上...
这套系统可以处理一些在单片机系统开发过程中的问题,他是一个面向开发者的工具,然而必定AT89s52功能是有限的,所以这个系统也不是万能的,但是他的确在我们的工作中起到了不可忽视的作用。随着认识的不断深入,现在已经是DSP+FPGA的时代了,所以我准备制作一个新的电脑来适应新的时代,今天随便写了点东西,回头看了看走过的路,看看踩出来的脚印而已。
没有评论:
发表评论