文章目录
一、简介
定时器/计数器,是存在于单片机内部的一个独立的硬件部分,依赖晶振产生固定的时间间隔,产生了一定量的固定时间间隔后会引发定时器中断,从而将其产生的时间信息传送给由CPU执行的主程序中。
CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生); CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断 。
二、寄存器
1.定时器控制寄存器TCON
位地址 | 8FH | 8EH | 8DH | 8CH | 8BH | 8AH | 89H | 88H |
---|---|---|---|---|---|---|---|---|
位序号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
位名称 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
外部中断:
IE0/IE1:外部中断请求标志位
(当INT0(INT1)引脚出现有效的请求信号,此位由单片机自动置1,
CPU开始响应,处理中断,而当入中断程序后由单片机自动置0. )
IT0/IT1:外部中断触发方式控制位
IT0/IT1=1:脉冲触发方式,下降沿有效。
IT0/IT1=0:电平触发方式,低电平有效。
内部中断:
TF0/TF1:内部定时器/计数器溢出中断标志位
当定时器、计数器计数溢出的时候,此位由单片机自动置1,
cpu开始响应,处理中断,而当进入中断程序后由单片机自动置0.
//内部中断实际上就是利用内部的计数器,
只不过提供计数的脉冲来自单片机自身。
TR0(TR1):定时器/计数器启动位 //启动定时器
TR0/TR1=1;启动定时器/计数器0
TR0/TR1=0;关闭定时器/计数器0
2.定时器、计数器模式控制寄存器TMOD
定时器/计数器模式控制寄存器TMOD是一个逐位定义的8位寄存器,但只能使用字节寻址,其字节地址为89H。
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
GATE | C/T | M1 | MO | GATE | C/T | M1 | M0 |
GATE——门控制
●GATE=1时,“与门”的输出信号K由INTx输入电平和TRx位的状态一起决定(即此时K=TRx·INTx),当且仅当TRx=1,INTx=1(高电平)时,计数启动;否则,计数停止。
当INT0引脚为高电平时且TR0置位,TR0=1;启动定时器T0;
当INT1引脚为高电平时且TR1置位,TR1=1;启动定时器T1。
●GATE=0时,“或门”输出恒为1,“与门”的输出信号K由TRx决定(即此时K=TRx),定时器不受INTx输入电平的影响,由TRx直接控制定时器的启动和停止。
当TR0=1,启动定时器T0。
当TR1=1,启动定时器T1。
C/T——功能选择位
C/T=0时为定时功能: 加1计数器对脉冲f进行计数,每来一个脉冲,计数器加1,直到计时器TFx满溢出;
C/T=1时为计数功能: 加1计数器对来自输入引脚T0(P3.4)和T1(P3.5)的外信号脉冲进行计数,每来一个脉冲,计数器加1,直到计时器TFx满溢出;
M0、M1——方式选择功能
定时器T0有4种工作方式:方式0,方式1,方式2,方式3。
定时器T1有3种工作方式:方式0,方式1,方式2。
M1 | M0 | 工作方式 | 功能说明 |
---|---|---|---|
0 | 0 | 方式0 | 13位定时器/计数器 |
0 | 1 | 方式1 | 16位定时器/计数器 |
1 | 0 | 方式2 | 自动重载8位定时器/计数器 |
1 | 1 | 方式3 | T0分为2个8位独立计数器/T1无方式3 |
3.中断允许控制寄存器IE
用于控制所有中断源的开放或禁止,以及每个中断源是否被允许。
位地址 | AFH | AEH | ADH | ACH | ABH | AAH | A9H | A8H |
---|---|---|---|---|---|---|---|---|
位序号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
位名称 | EA | - | - | ES | ET1 | EX1 | ET0 | EX0 |
EX0/EX1:外部中断允许控制位
EX0=1 外部中断0开关闭合
EX0=0 外部中断0开关断开
ET0/ET1:定时中断允许控制位
ET0=1 定时器中断0开关闭合
ET0=0 定时器中断0开关断开
ES:串口中断允许控制位
ES=1 串口中断开关闭合
ES=0 串口中断开关断开
EA :中断总允许位。
三、定时器与中断编程的顺序
1.定时器编程的顺序
第一:设置特殊功能寄存器TMOD,配置好工作模式。
第二:设置计数寄存器TH0和TL0的初值。
第三:设置TCON,通过TR0置1来让定时器开始计数。
第四:判断TCON寄存器的TF0位,监测定时器溢出情况。
2.中断编程的顺序
第一:设置中断允许控制寄存器IE,打开所需中断开关和终端总开关EA。
第二:编写中端服务函数
四、秒表实验
硬件说明:IAP15F2K61S2
实验目标:在CT107D单片机综合训练平台上,利用定时器T0、数码管模块和2个独立按键(J5的2-3短接),设计一个秒表,具有清零、暂停、启动功能。
实验要求:
1.显示格式为: 分-秒- 0.05秒(即50ms),例:08-26-18表示: 8分 26秒900毫秒。
2.独立按键S4为:暂停|启动;独立按键S5为:清零 ,按键均为按下有效。
程序代码:
#include "reg52.h"
sbit S4 = P3^3;
sbit S5 = P3^2;/*独立按键*/
unsigned char t_m = 0;/*分*/
unsigned char t_s = 0;/*秒*/
unsigned char t_005s = 0;/*50毫秒*/
unsigned char code SMG_NoDot[18] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};/*共阳数码管真值*/
void SelectHC573(unsigned char channel)/*74HC573锁存器*/
{
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
void DisplaySMG_Bit(unsigned char value, unsigned char pos)/*数码管显示函数*/
{
P0 = 0xff;
SelectHC573(6);
P0 = 0x01 << pos;
SelectHC573(7);
P0 = value;
}
void DelaySMG(unsigned int t)/*数码管延时函数*/
{
while(t--);
}
void DisplayTime()/*设置数码管显示内容*/
{
DisplaySMG_Bit(SMG_NoDot[t_005s%10],7);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_005s/10],6);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],5);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s%10],4);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s/10],3);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],2);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m%10],1);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m/10],0);
DelaySMG(500);
}
//=============定时器相关函数========================
void InitTimer0() /*定时器0初始化*/
{
TMOD = 0x01;
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
ET0 = 1;
EA = 1;
TR0 = 1;
}
//定时器中断服务函数
void ServiceTimer0() interrupt 1 //默认中断优先级 1
{
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
t_005s++;
if(t_005s == 20)
{
t_s++;
t_005s = 0;
if(t_s == 60)
{
t_m++;
t_s = 0;
}
if(t_m == 99)
{
t_m = 0;
}
}
}
//==================按键相关函数=================================
void DelayK(unsigned char t) /*按键延时函数*/
{
while(t--);
}
void ScanKeys() /*按键读值并设置按键功能*/
{
if(S4 == 0) //秒表启动与暂停
{
DelayK(100);
if(S4 == 0)
{
TR0 = ~TR0;
while(S4 == 0)
{
DisplayTime();
}
}
}
if(S5 == 0) //秒表清零
{
DelayK(100);
if(S5 == 0)
{
t_005s = 0;
t_s = 0;
t_m = 0;
while(S5 == 0)
{
DisplayTime();
}
}
}
}
//==================朱函数=================================
void main()
{
InitTimer0();
while(1)
{
DisplayTime();
ScanKeys();
}
}