目录
用Proteus设计一个16bit的霓虹灯,闪烁规律自定,闪烁频率可手动按钮调整,能仿真演示。(使用定时器)
一、作业二要求
用Proteus设计一个16bit的霓虹灯,闪烁规律自定,闪烁频率可手动按钮调整,能仿真演示。(使用定时器)
二、定时/计数器 基础知识
2.1定时器概述
- 定时:对周期已知的脉冲信号计数
- 计数:对外部事件计数,对周期未知的外来脉冲信号计数,它们都有定时和对外部事件计数的功能,可用于定时控制、延时、对外部事件检测和计数等场合。
- 定时/计数器的可编程特性 : ⑴ 确定其工作方式是定时还是计数;⑵ 预置定时或计数初值;⑶ 当定时时间到或计数终止时,要不要发中断请;⑷ 如何启动定时或计数器工作 。
- 定时器的结构:2个16位T/C分别由8位计数器TH0、TL0(T0 P3.4),TH1、TL1(T1 P3.5 )组成; 加“1”计数器;控制寄存器TCON:控制T/C的启停、中断等;方式寄存器TMOD:控制T/C的工作方式。
- 定时/计数器工作原理:定时器:T/C计数内部机器周期信号的个数 ,由计数个数可以计算出定时时间 。每一个机器周期做一次“+1”运算,直至计满回零后自动产生溢出中断请求,表示定时时间到 。f=12MHz,一个机器周期是1 μs)计数器:T/C计数来自引脚T0(P3.4)和T1(P3.5)的外部脉冲信号的个数。输入脉冲由1变0的下降沿时,计数器的值增加1直到回零产生溢出中断,表示计数已达预期个数。最高计数频率为振荡频率的1/24,即计数周期>=2机器周期。
2.2定时器/计数器的控制
2.2.1方式寄存器TMOD(89H)
一个逐位定义的8位寄存器,只能字节寻址
GATE = 0 不受外部中断控制 GATE = 1 受外部中断控制
C/ = 0 为定时功能 C/ = 1 为计数功能
M1、M0 操作模式控制 四种工作模式
2.2.2控制寄存器(TCON)
可字节寻址也可位寻址
注:在这里不理解为什么有两个88H的话可以去查一下字节寻址和位寻址的区别
TF1(TCON.7):T1溢出标志(硬件)= 1 溢出,= 0 未溢出
TR1(TCON.6):T1运行控制位(软件)= 1 启动,=0 关闭
TF0(TCON.5):T0溢出标志(硬件)= 1 溢出,= 0 未溢出
TR0(TCON.4):T0运行控制位(软件) = 1 启动,=0 关闭
2.2.3四种工作方式
方式0 M1M0 = 00 ( = 8192)
13位的定时计数器,由TH的8位和TL的低5位组成。
方式1 M1M0 = 01 ( = 65526)
16位的定时计数器,由TH的8位和TL的8位组成。
方式2 M1M0 = 10 ( = 256)
可自动重装载的8位计数器 ,其中TL1(TL0)被定义为计数器,TH1(TH0)被定义为赋值寄存器
方式3 M1M0 = 11 ( = 256)
T0被分成2个相互独立的8位计数器TL0 、TH0
TL0使用自己本身的一些控制位C/T、GATE、TR0、TF0、INT0等
TH0只能做定时器,并使用T1的控制位TR1、TF1,同时占用T1的中断源
2.2.4定时/计数器初始化
步骤:
1> 确定工作方式,对方式寄存器TMOD赋值
2> 预置定时或计数初值,直接将其写入T0、T1中
3> 根据需要对中断允许寄存器有关位赋值,以开放或禁止定时/计数器中断
4> 启动定时/计数器,将TRi 赋值为“1”
三、完成过程分析与实现
3.1分析
3.1.1要求分析
一个16bit的霓虹灯,闪烁规律自定。我选择当开关闭合时改变闪烁间隔时间。那么就使用两个定时器控制时间,定时器有两种控制时间的方法,查询和中断,我选择使用查询方式完成程序。(其实如果不使用定时器的话,使用延时子函数也能完成内容要求的说,但是学会定时器的使用很重要啊,学习51就一定要把这个学好. )
3.1.2电路搭建
RN1和RN2是两个排阻,不想用排阻的话可以使用电阻。2.4口的电路是为了使2.4口能够恢复高电平状态,按钮不能太过频繁地按。
3.1.3程序分析
16bit灯相当于控制2组8bit的灯,开关断开时灯的间隔为1s,开关闭合时灯的间隔为0.5s。两个定时器选择方式1进行定时控制,T0为1s时间控制,T1为0.5s时间控制。开关按下时,在下一轮的循环时,间隔时间改变。
初值计算: 因为我使用的是12MHz的晶振,所以T = 1us,产生50000us=0.005s的方波,所以1s是重复200次,0.5s是重复100次。置入初值为-50000=15536。15536转换成16进制为3CB0,则TH=3C,TL=B0。方式1和方式0的初值计算方式不同,具体想要知道方式0的初值计算可以翻翻书或者百度。
//以T0为例
//一次计时
TIME:MOV TH0, #3CH
MOV TL0, #B0H
SETB TR0 ;启动T0工作
JNB TF0,$ ;$为当前指令指针地址
CLR TF0
MOV TH0, #3CH
MOV TL0, #B0H
END
//多次计时(例如20次)
TIME:MOV TH0, #3CH
MOV TL0, #B0H
MOV R7,#20
SETB TR0 ;启动T0工作
JNB TF0,$ ;$为当前指令指针地址
CLR TF0
DJNZ R7,TIME ;R7=0时顺序执行
MOV TH0, #3CH
MOV TL0, #B0H
END
查询法整体程序如下:
BUTTON BIT P2.4 ;定义2.4口名字为BUTTON
ORG 0000H
AJMP START
ORG 0100H
START: MOV TMOD,#11H
MOV A,#0FEH
MOV R2,#8
MOV R5,#2
LOOP: MOV R1,#08H
MOV R6,#08H
MOV R4,#08H
MOV R3,#08H
LOOP1: JNB BUTTON,CYCLE1 ;BUTTO=0时跳转,即开关按下
MOV P1,A
RL A
ACALL TIME1
DJNZ R4,LOOP1
MOV P1,#0FFH
ACALL TIME1
LOOP2: MOV P0,A
RL A
ACALL TIME1
DJNZ R3,LOOP2
MOV P0,#0FFH
ACALL TIME1
AJMP LOOP
CYCLE1: JBC BUTTON,START
MOV P1,A
RL A
ACALL TIME2
DJNZ R6,CYCLE1
MOV P1,#0FFH
ACALL TIME2
CYCLE2: MOV P0,A
RL A
ACALL TIME2
DJNZ R1,CYCLE2
MOV P0,#0FFH
ACALL TIME2
AJMP START
TIME1: MOV TH0,#3CH ;置入初值
MOV TL0,#0B0H
SETB TR0 ;启动T0工作
JNB TF0,$ ;等待TF0溢出
CLR TF0
DJNZ R2,TIME1
MOV TH0, #3CH
MOV TL0, #0B0H
MOV R2,#8
RET
TIME2: MOV TH1, #3CH
MOV TL1, #0B0H
SETB TR1 ;启动T1工作
JNB TF1,$ ;等待TF1溢出
CLR TF1
DJNZ R5,TIME2
MOV H1, #3CH
MOV TL1, #0B0H
MOV R5,#2
RET
END
总结
相对于查询方式中断方式会稍微难一些,查询方式好理解一点。由于作业完成的比较仓促,不太清楚程序中有什么其他的问题,要是在帖子中遇到问题,希望朋友们能够指正,谢谢!