我这个51单片机定时器程序哪里算错了?
我想用定时器中断实现LED每隔1s闪烁一次,采用方式0.
我是这样计算的,12M晶振,一个周期为1μs,令T0寄存器初值为X则(FF1F-X)*1μs=1ms(因为方式0TLX只用了低5位,所以是FF1F),得X=1C17。要产生每秒1次的闪烁效果则要间隔1000此中断,也就是3E8次中断。我用31H的全位和30H的低4位作为计数器,初始化31H为3E,30H为08,每次中断对30H进行减1,如果30H为0则置30H为0F,同时对31H减1,如果此时31H也为0则对P0.0取反,LED闪烁一次,并置31H为3E。
但是奇怪的是在proteus模拟时却要等8s,LED才闪一次。而如果切换成方式1,更改相应的T0寄存器值运行又基本正常了,是我方式0的寄存器值算错了吗?
;T0定时器方式0,每1ms产生一次中断
;每1000次中断后对LED取反,即每隔1sLED闪一下
;采用12M晶振,AT89C51单片机,proteus软件模拟
CNTH EQU 31H ;计数器的高8位
CNTL EQU 30H ;计数器的低8位,只使用其低4位
org 0000
ajmp main ;跳转到主程序
org 1bh ;T0中断入口程序
ajmp INT_T0
org 2bh ;主程序
main:
mov sp,#60h;初始化堆栈
acall INIT_T0;初始化T0中断
HERE:AJMP HERE ;死循环
INIT_T0:
MOV TMOD,#00 ;设置T0为方式0,定时器模式
SETB TR0 ;打开定时器
SETB ET0 ;允许T0中断
SETB EA ;允许CPU中断
MOV TH0,#1CH ;初始化T0寄存器高位
MOV TL0,#17H ;初始化T0寄存器低位
MOV CNTH,#3EH;初始化计数器高位
MOV CNTL,#17H;初始化计数器低位,计数器初始值为1000
CLR P0.0 ;点亮LED
RET
INT_T0:
MOV TH0,#1CH ;重新初始化T0寄存器高位
MOV TL0,#17H ;重新初始化T0寄存器低位
DJNZ CNTL,EXIT_SUB;如果计数器低位减1后不为0就退出中断子程序
MOV CNTL,#0FH ;如果计数器低位减1后为0就置为0FH,因为只使用其低4位
DJNZ CNTH,EXIT_SUB;如果计数器高8位减1后不为0,就退出中断子程序
MOV CNTH,#3EH ;否则重新置高8位为3EH
CPL P0.0 ;对P0.0取反
EXIT_SUB: RETI ;中断返回
END
[解决办法]
org 1bh大致看了一下,此处错了
改为org 000bh
[解决办法]
欢迎到51汇编吧做客
[解决办法]
dxnb bit 0
green_dx equ p3.4
red_dx equ p3.2
yellow_dx equ p3.3
green_nb equ p2.4
yellow_nb equ p2.3
red_nb equ p2.2
times equ 30h
time50ms equ 31h
led1 equ 32h
led2 equ 33h
;**************************
org 0000h
sjmp main
org 000bh
ajmp interrupt
org 0030h
main:
mov sp,#60h
mov dptr, #tab
mov times,#59
mov th0,#3ch
mov tl0,#0bh
mov time50ms,#0
mov tmod,#00000001b
setb tr0
mov p0,#11111111b
clr dxnb
setb ea
setb et0
;0为东西,1为南北
while:
jb dxnb,nb
;东西方向
clr green_dx;东西绿灯亮
setb red_dx ;东西红灯灭
setb yellow_dx;东西黄灯灭
setb green_nb ;南北绿灯灭
clr red_nb ;南北红灯亮
setb yellow_nb ;南北黄灯灭
sjmp while_call
nb:;南北方向
clr green_nb;南北绿灯亮
setb red_nb ;南北红灯灭
setb yellow_nb;南北黄灯灭
setb green_dx ;东西绿灯灭
clr red_dx ;东西红灯亮
setb yellow_dx ;东西黄灯灭
;-------------------------------
while_call:
call huang_deng ;处理黄灯程序
call display ;显示程序
sjmp while
;****************************************
huang_deng:
mov a,times
cjne a,#3,cjne_2
sjmp huang_deng_setb
cjne_2:
cjne a,#2,cjne_1
sjmp huang_deng_setb
cjne_1:
cjne a,#1,huang_deng_out
huang_deng_setb:
setb green_dx;东西绿灯亮
setb red_dx ;东西红灯灭
clr yellow_dx;东西黄灯灭
setb green_nb ;南北绿灯灭
setb red_nb ;南北红灯亮
clr yellow_nb ;南北黄灯灭
huang_deng_out:
ret
;********************************************
display:
mov a,times
mov b,#10
div ab
mov led1,a
mov led2,b
;----------------
mov a,led1
movc a,@a+dptr
mov p0,a
setb p2.0
clr p2.1
call delay
mov p0,#0ffh
clr p2.0
;------------------
mov a,led2
movc a,@a+dptr
mov p0,a
setb p2.1
call delay
mov p0,#0ffh
clr p2.1
ret
;**********************************
delay:
mov r6,#200
delay_r6:mov r7,#100
delay_r7:djnz r7,delay_r7
djnz r6,delay_r6
ret
;***********************************
interrupt:
push acc
inc time50ms
mov a,time50ms
cjne a,#20,interrupt_out
mov time50ms,#0
dec times
mov a,times
cjne a,#0,interrupt_out
mov times,#59
cpl dxnb
interrupt_out:
mov th0,#3ch
mov tl0,#0bh
pop acc
reti
;***********************************
tab:
db 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h
end
看看我的一秒中断,这是个交通灯程序,数码管一秒计数一次
[解决办法]
效果还是一样,8秒闪烁一次。