我这个51单片机定时器程序哪里算错了?

时间:2021-10-18 23:35:25
我想用定时器中断实现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

7 个解决方案

#1


org 1bh大致看了一下,此处错了
改为org 000bh

#2


欢迎到51汇编吧做客

#3


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

      
     看看我的一秒中断,这是个交通灯程序,数码管一秒计数一次

#4


效果还是一样,8秒闪烁一次。
引用 1 楼  的回复:
org 1bh大致看了一下,此处错了
改为org 000bh

#5


你采用的是方式1,我这个是方式0,方式1我做过,正常运行。
引用 3 楼  的回复:
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
;**************……

#6


改为org 000bh

#7


关键不是中断入口,即使不改也可以进行计时。
引用 6 楼  的回复:
改为org 000bh

#1


org 1bh大致看了一下,此处错了
改为org 000bh

#2


欢迎到51汇编吧做客

#3


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

      
     看看我的一秒中断,这是个交通灯程序,数码管一秒计数一次

#4


效果还是一样,8秒闪烁一次。
引用 1 楼  的回复:
org 1bh大致看了一下,此处错了
改为org 000bh

#5


你采用的是方式1,我这个是方式0,方式1我做过,正常运行。
引用 3 楼  的回复:
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
;**************……

#6


改为org 000bh

#7


关键不是中断入口,即使不改也可以进行计时。
引用 6 楼  的回复:
改为org 000bh