单片机学习笔记第8章:定时器详解与实践
IAP15W4K58S4定时/计数器结构工作原理
定时器工作方式控制寄存器TMOD
不能进行位寻址,只能对整个寄存器进行赋值
寄存器 | 地址 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 复位值 |
TMOD | 89H | GATE | C/(T低电平有效) | M1 | M0 | GATE | C/(T低电平有效) | M1 | M0 | 00000000B |
D0-D3为T0控制,D4-D7为T1控制
GATE:门控位
GATE用于选通控制。
GATE=1时,INT1或INT0为高电平且TR1或TR0置1,T1或T0才能启动计数。
GATE=0时,只要TR1或TR0被置1,T1或T0就启动计数
C/(T低电平有效) :功能选择位
C/(T低电平有效) =1,为计数器功能
C/(T低电平有效) =0,为定时器功能
M1和M0:方式选择位
M1 | M0 | 工作方式 | 功能说明 |
0 | 0 | 0 | 16位自动装载的定时器/计数器 |
0 | 1 | 1 | 16位的定时器计数器 |
1 | 0 | 2 | 可自动重装的8位计数器 |
1 | 1 | 3 |
T1:停止计数 T0:不可屏蔽中断的16位自动装载的定时器/计数器 |
定时器控制寄存器TCON
寄存器 | 地址 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 复位值 |
TCON | 88H | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 | 00000000B |
TF1和TF0:
T1和T1溢出标志位,为1时请求中断
TR1和TR0:
T1和T0的运行控制位,GATE=0,TR1=1启动计数,TR1=0停止计数
可以把初值写入THX,TLX用于控制计数长度
装入计数/定时器的初值的计算方法
16位的最大时间间隔:65.536ms
8位的最大时间间隔:256us
计算方法:
16位定时器:
T机=1/(fosc/12)
(-初值)*T机=定时时间
定时量程的扩展:
在定时器中断服务程序中对定时器中断请求计数,当中断请求的次数达到要求的值时,才进行相应的处理
eg.50ms*20次=1s
即每20次进行一次事件的处理
使用定时器 T0,在 P1.7 引脚输出周期位 1S 的方波,输出 10 个后停止。
;使用定时器 T0,在 P1.7 引脚输出周期位 1S 的方波,输出 10 个后停止。
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0_ISR
ORG 0100H
MAIN:
MOV R0,#10
MOV R1,#20
MOV TMOD,#01H
MOV TL0,#0B0H ;50MS
MOV TH0,#3CH
SETB ET0
SETB EA
SETB TR0
JZ STOP
T0_ISR:
MOV TL0,#0B0H ;50MS
MOV TH0,#3CH
DJNZ R0,DON
CPL P1.7
DEC R1
MOV A,R1
MOV R0,#10
DON:RETI
STOP:CLR ET0
CLR EA
CLR TR0
RET
END
上述代码存在的问题
JZ STOP
语句位置有误:JZ STOP
这个语句在定时器启动之后马上执行,而此时R0
、R1
等计数器还未开始工作,R0
初始值为 10,并非 0,所以这个判断没有意义,而且会导致程序过早地跳到STOP
处停止。- 方波计数逻辑有问题:在中断服务程序里,
DJNZ R0,DON
是用来判断是否达到半个周期(这里以 50ms 为一次中断,20 次中断即 1s 为一个周期),但对于方波个数的计数,在DEC R1
之后没有对R1
是否为 0 进行判断,所以无法准确停止输出方波。 - 程序结束逻辑有误:
RET
指令一般用于子程序返回,而这里程序结束时不应该使用RET
,可以使用SJMP $
让程序进入死循环,从而停止运行。
修改后:
;使用定时器 T0,在 P1.7 引脚输出周期位 1S 的方波,输出 10 个后停止。
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0_ISR
ORG 0100H
MAIN:
MOV R0, #10 ; 半个周期的中断次数(20 次中断为 1 秒周期)
MOV R1, #20 ; 方波个数计数器
MOV TMOD, #01H ; 设置定时器 T0 为模式 1
MOV TL0, #0B0H ; 定时 50ms 的初值
MOV TH0, #3CH
SETB ET0 ; 使能定时器 T0 中断
SETB EA ; 全局中断使能
SETB TR0 ; 启动定时器 T0
SJMP $ ; 等待中断
T0_ISR:
MOV TL0, #0B0H ; 重新加载定时 50ms 的初值
MOV TH0, #3CH
DJNZ R0, DON ; 半个周期未到,继续等待
CPL P1.7 ; 半个周期到,取反 P1.7 引脚电平
MOV R0, #10 ; 重置半个周期计数器
DJNZ R1, DON ; 方波个数未达到 10 个,继续
CLR ET0 ; 关闭定时器 T0 中断
CLR EA ; 关闭全局中断
CLR TR0 ; 停止定时器 T0
; SJMP $ ; 程序停止
DON:
RETI ; 中断返回
END
T0 定时 100ms 实现 1s 定时控制 P1.7 小灯亮灭闪烁,增加一个 P1.6 小灯用 T1定时 100ms 实现 0.5S 定时控制 P1.6 小灯闪烁。
;T0 定时 100ms 实现 1s 定时控制 P1.7 小灯亮灭闪烁,增加一个 P1.6 小灯用 T1定时 100ms 实现 0.5S 定时控制 P1.6 小灯闪烁。
LED1 EQU P1.7
LED2 EQU P1.6
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0_ISR
ORG 001BH
LJMP T1_ISR
ORG 0100H
MAIN:
LCALL TIM_Init
SETB ET0
SETB ET1
SETB EA
SJMP $
TIM_Init:MOV R0,#20
MOV R1,#10
MOV TMOD,#011H
MOV TL0, #0B0H ; 定时 50ms 的初值
MOV TH0, #3CH
MOV TL1, #0B0H ; 定时 50ms 的初值
MOV TH1, #3CH
SETB TR0
SETB TR1
RET
T0_ISR:MOV TL0, #0B0H ; 定时 50ms 的初值,重赋初值
MOV TH0, #3CH
DJNZ R0,DON_0
CPL LED1
MOV R0,#20
DON_0:RETI
T1_ISR:MOV TL1, #0B0H ; 定时 50ms 的初值,重赋初值
MOV TH1, #3CH
DJNZ R1,DON_1
CPL LED2
MOV R1,#10
DON_1:RETI
END
T0 定时 100ms 实现 1s 定时控制 P1.7 小灯
使用定时/计数器延时,使 P1.0 和 P1.1 间两灯按 1S 间隔互相闪烁
; 使用定时/计数器延时,使 P1.0 和 P1.1 间两灯按 1S 间隔互相闪烁。
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0_ISR
ORG 0100H
MAIN:
LCALL TIM_Init
LCALL LED_Init
SETB ET0
SETB EA
SJMP $
LED_Init:SETB P1.0
SETB P1.1
RET
TIM_Init:
MOV R0,#20 ;1S
MOV TMOD,#01H
MOV TH0,#3CH ;50MS
MOV TL0,#0B0H
SETB TR0;开始计数
RET
T0_ISR:
MOV TH0, #3CH ; 重装 50ms 定时初值
MOV TL0, #0B0H
DJNZ R0, DON0 ; 判断是否达到 1s
MOV R0, #20 ; 重置计数器
JB P1.0, TURN_OFF_P10 ; 如果 P1.0 为高电平,关闭 P1.0 打开 P1.1
SETB P1.0
CLR P1.1
SJMP DON0
TURN_OFF_P10:
CLR P1.0
SETB P1.1
DON0:RETI
END
使用定时/计数器延时,使 P1.0 和 P1.1 间两灯按
用定时器 1,控制 P1.0 口输出 1ms 等宽方波,分别以查询方式和中断方式完成。
;定时器中断方式定时
ORG 0000H
LJMP MAIN
ORG 001BH
LJMP TINT1
ORG 0100H
MAIN:MOV TMOD,#11H;
MOV TH1,#0FEH ;0.5MS
MOV TL1,#0CH
SETB TR1 ;启动定时
SETB ET1
SETB EA
SJMP $
TINT1:MOV TH1,#0FEH ;0.5MS
MOV TL1,#0CH
CPL P1.0
DON:RETI
END
;定时器查询方式定时
ORG 0000H
MOV TMOD, #10H;
MOV TH1,#0FEH ;0.5MS
MOV TL1,#0CH
SETB P1.0
SETB TR1
WAIT: JNB TF1,WAIT
CLR TF1
MOV TH1,#0FEH ;0.5MS
MOV TL1,#0CH
CPL P1.0
LJMP WAIT
END
用 P2口控制 8 只 LED 闪烁,INT0 与按键 K1 连接,INT1 与按键 K2 连接。
(1)当奇数次按下按键 K1 时,8 个 LED 同时点亮 4 个,点亮 3 次,即 D0~D3 与D4~D7 交叉点亮 3 次。
(2)偶数次按下按键 K1 时, D0~ ~D7 进行左移和右移两次。
(3)当按下按键 K2 时,产生报警,K2 按键的中断优于 K1 按键中断。
;用 P2口控制 8 只 LED 闪烁,INT0 与按键 K1 连接,INT1 与按键 K2 连接。
;1)当奇数次按下按键 K1 时,8 个 LED 同时点亮 4 个,点亮 3 次,即 D0~D3 与D4~D7 交叉点亮 3 次。
;2)偶数次按下按键 K1 时, D0~ ~D7 进行左移和右移两次。
;3)当按下按键 K2 时,产生报警,K2 按键的中断优于 K1 按键中断。
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP IT0_ISR
ORG 000BH
LJMP T0_ISR
ORG 0013H
LJMP IT1_ISR
ORG 0100H
MAIN:
LCALL TIM_Init
SETB IT0;下降沿触发
SETB IT1
SETB PX1;INT1优先于INT0
SETB ET0
SETB EX0
SETB EX1
SETB EA
SJMP $
TIM_Init:
MOV R0,#20 ;1S
MOV TMOD,#01H
MOV TH0,#3CH ;50MS
MOV TL0,#0B0H
SETB TR0;开始计数
RET
IT0_ISR:
PUSH ACC
PUSH PSW
INC R1; 按键按下次数加 1
MOV A, R1
ANL A, #01H;将按键按下的次数和01H相与,奇数为01H,偶数为00H
JZ EVEN_PRESS ; 偶数次按下
MOV R2, #3 ; 奇数次按下,闪烁次数
LOOP1:
MOV P2, #0F0H ;1111 0000B
LCALL DELAY_1S
MOV P2, #0FH ;0000 1111B
DJNZ R2, LOOP1
SJMP INT0_END
EVEN_PRESS:; 偶数次按下
MOV R3, #2 ; 左右移次数
SETB C
SHIFT_LOOP:
MOV A, #0FEH;1111 1110B
LEFT_SHIFT:
MOV P2, A
LCALL DELAY_1S
RLC A
JB P2.7,LEFT_SHIFT
MOV A, #7FH;0111 1111B
RIGHT_SHIFT:
MOV P2, A
LCALL DELAY_1S
RRC A
JB P2.0, RIGHT_SHIFT
DJNZ R3, SHIFT_LOOP
POP PSW
POP ACC
INT0_END:RETI
IT1_ISR:
CPL P3.7
RETI
T0_ISR:
MOV TH0,#3CH ;50MS
MOV TL0,#0B0H
DJNZ R0,DON
SETB TF0 ; 延时时间到,设置定时器溢出标志
MOV R0,#20
DON:RETI
DELAY_1S:
MOV R0, #20 ; 重新初始化 1s 计数
WAIT_TF0:JNB TF0, WAIT_TF0 ; 等待定时器溢出
CLR TF0 ; 清除定时器溢出标志
RET
END
用 P2口控制 8 只 LED 闪烁,INT0 与按键 K1
作者:RaLi和夕