我想用定时器中断实现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 |