[蓝桥杯单片机]学习笔记——定时器原理及其应用

一、原理部分

1、什么是定时/计数器

        定时/计数器,是一种能够对内部时钟信号或外部输入信号进行计数,当计数值达到设定要求时,向CPU提出中断处理请求,从而实现定时或者计数功能的外设。定时/计数器的最基本工作原理是进行计数。作为定时器时,计数信号的来源选择周期性的内部时钟脉冲;用作计数器时,计数信号的来源选择非周期性的外部输入信号

2、蓝桥杯单片机定时器资源

        该单片机有两个定时/计数器T0和T1,均为16位加法计数器,由低8位TLx高8位THx两个寄存器组成,最大计数值为65535个计数脉冲

该加1计数器的计数脉冲来源有2个:
    ①系统时钟振荡器输出的12分频。
    ②T0或T1引脚输入的外部脉冲信号。

        每接收到一个计数脉冲,计数器就会加1,当计数值达到峰值时,再输入一个计数脉冲,计数器便会溢出回零,并且将TCON寄存器的TF0或TF1置1,同时向内核提出中断请求。

        如果定时/计数器工作于定时模式,则表示间隔定时时间到,如果工作与计数模式,则表示计数值已满。

        假设单片机的外部晶振为12MHz,那么,经过12分频后输入计数器的计数脉冲为1MHz,即每个脉冲的周期为1us。因此定时器T0的16位工作模式最大的定时时间为65535us,65.5ms。如果要定时10ms的话,计数器就不能够从0开始计数了,必须给它一个计数初值。怎么计算这个初值呢?

        要定时10ms,则相当于计数10000个脉冲后计数器的值就到达65535了,那么开始计数的这个地方就是计数初值。
    65535 - 10000 = 55535 = 0xd8ef
把这个计算得到的初值写入TH0和TL0寄存器即可:
    TH0 = 0xd8;或者 TH0 = (65535 - 10000+1) / 256;
    TL0 = 0xef; 或者  TL0 = (65535 - 10000+1) % 256;

3、配置定时器

配置前需要了解一下定时器相关寄存器 

(1)TCON:定时器/计数器控制寄存器

 TF1: 定时器/计数器T1溢出标志。

        T1被允许计数以后,从初值开始加1计数。当最高位产生溢出时由硬件置“1”TF1,向CPU请求中断,一直保持到CPU响应中断时,才由硬件清“0”TF1 (TF1也可由程序查询清“0”)。
TR1:定时器T1的运行控制位。

        该位由软件置位和清零。

        当GATE (TMOD.7) =0,TR1=1时就允许T1开始计数,TR1=0时禁止T1计数。

        当GATE (TMOD.7) =1,TR1=1且INT1输入高电平时,才允许T1计数。
TF0:定时器/计数器TO溢出中断标志。

        T0被允许计数以后,从初值开始加1计数,当最高位产生溢出时,由硬件置“1”TF0,向CPU请求中断,一直保持CPU响应该中断时,才由硬件清“0”TF0 ( TF0也可由程序查询清“0”)。
TR0:定时器T0的运行控制位。

        该位由软件置位和清零。

        当GATE (TMOD.3) =0,TR0=1时就允许T0开始计数,TR0=0时禁止T0计数。

        当GATE (TMOD.3) =1,TR1=0且INT0输入高电平时,才允许T0计数。

 

若使用定时器0,则TCON应该设置为:

TR0=1;开启定时器

(2)TMOD:定时器/计数器工作模式寄存器

GATE:GATE=0时,由TR0和TR1控制定时器,GATE=1时,由INT0和INT1控制定时器

C/T:C/T=0时,为定时功能,C/T=1时,为计数功能

M1、M0:定时器定时器/计数器1模式选择
        ①M1=0,M0=0->16位自动重装定时器,当溢出时将RL_TH1和RL_TL1存放的值自动重装入TH1和TL1中。
        ②M1=0,M0=1->16位不可重装载模式,TL1、TH1全用,计数溢出后需要手动设置计数值
        ③M1=1,M0=0->8位自动重装载定时器,当溢出时将TH1存放的值自动重装入TL1
        ④M1=1,M0=1->定时器/计数器1此时无效(停止计数) 。

 

一般选择16位自动重装定时器,不用手动设置计数值。

若使用定时器0,此时TMOD设置为:

TMOD&=0xf0;

将低四位置0,即GATE、C/T、M1、M0均为0,设置为16位自动重装定时器

(3)AUXR辅助寄存器

        这个寄存器主要用于设置定时器分频,定时器0、定时器1,和定时器2复位后是传统8051的速度,即12分频,这是为了兼容传统8051。但也可不进行12分频,通过设置新增加的特殊功能寄存器AUXR,将T0,T1,设置为1T。

(4)IE和IP:定时器T0和T1的中断控制寄存器

IE:中断允许寄存器 (可位寻址)

EA:CPU的总中断介许控制位

        EA=1,CPU开放中断

        EA=0,CPU屏两所有的中新申请

        EA的作用是使中断允许形成多级控制,即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。
ET1:定时/计数器T1的溢出中断允许位

        ET1=1,允许T1中断

        ET1=0,禁止T1中断

ET0: T0的溢出中断允许位

        ET0=1允许T0中断

        ET0=0禁止T0中断 

IP:中断优先级控制寄存器 (可位寻址)

 PT1:定时器1中断优先级控制位。

        当PT1=0时,定时器1中断为最低优先级中断(优先级0)

        当PT1=1时,定时器1中断为最高优先级中断(优先级1)
PT0:定时器0中断优先级控制位。
        当PT0=0时,定时器0中断为最低优先级中断(优先级0)

        当PT0=1时,定时器0中断为最高优先级中断(优先级1)

若使用定时器0,此时IE和IP设置为:

    ET0=1;
    EA=1;

4、定时器框架编写

定时器设计使用中,一般需要编写两个函数:初始化函数中断服务函数

(1)初始化函数
①配置工作模式,即对TMOD寄存器编程。
②计算计数初值,即对THx和TLx寄存器进行赋值。
③使能定时/计数器中断,即ET0或ET1置1。
④打开总中断,即EA =1。
⑤启动定时器,即TR0或TR1置1。

(2)中断服务函数(记住中断号!!)
①如果不是自动重装模式,需要对THx和TLx重新赋值。
②一定时间间隔后执行相应逻辑。

5、STC-ISP生成定时器初始化函数

使用STC-ISP中的定时器计算器可以生成定时器初始化函数。 

二、程序案例

 例子:使用定时器T0和数码管制作能够显示分、秒、0.05秒的秒表,按键S5秒表清零,按键S4用于秒表的暂停与启动

#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;//用于记录0.05秒

unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//数码管段码表

/*****************************************************************
*@Function: SelectHC573     //
*@Description: 选择锁存器    //
*@Input:channel:选择通道 //
*@Output:无 //
*@Return:无  //
*@Others:无  //
/*****************************************************************/
void SelectHC573(unsigned char channel)
{
	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;
	}
}

/*****************************************************************
*@Function: DelaySMG     //
*@Description: 用于数码管延时    //
*@Input:t:延时长短 //
*@Output:无 //
*@Return:  无//
*@Others:  无//
/*****************************************************************/
void DelaySMG(unsigned int t)
{
	while(t--);
}

/*****************************************************************
*@Function: DisplaySMG_Bit     //
*@Description:单位数码管显示     //
*@Input: value:显示的内容
*		pos:显示的位置//
*@Output: 无//
*@Return: 无 //
*@Others: 无 //
/*****************************************************************/
void DisplaySMG_Bit(unsigned char value,unsigned char pos)
{
	SelectHC573(6);
	P0=0x01<<pos;
	SelectHC573(7);
	P0=value;
}

/*****************************************************************
*@Function: DisplayTime     //
*@Description:显示时间     //
*@Input: 无//
*@Output: 无//
*@Return:  无//
*@Others: 无 //
/*****************************************************************/
void DisplayTime()
{
	DisplaySMG_Bit(SMG_duanma[t_005s%10],7);
	DelaySMG(500);
	DisplaySMG_Bit(SMG_duanma[t_005s/10],6);
	DelaySMG(500);
	DisplaySMG_Bit(SMG_duanma[16],5);
	DelaySMG(500);
	
	DisplaySMG_Bit(SMG_duanma[t_s%10],4);
	DelaySMG(500);
	DisplaySMG_Bit(SMG_duanma[t_s/10],3);
	DelaySMG(500);
	DisplaySMG_Bit(SMG_duanma[16],2);
	DelaySMG(500);
	
	DisplaySMG_Bit(SMG_duanma[t_m%10],1);
	DelaySMG(500);
	DisplaySMG_Bit(SMG_duanma[t_m/10],0);
	DelaySMG(500);
}

/*****************************************************************
*@Function: InitTimer0     //
*@Description:初始化定时器0 //
*@Input:无 //
*@Output: 无//
*@Return:  无//
*@Others: 无 //
/*****************************************************************/
void InitTimer0()
{
	TMOD=0x01;//设置定时器模式
	TH0=(65535-50000+1)/256;//设置计数初始值
	TL0=(65535-50000+1)%256;
	ET0=1;//使能定时器T0中断
	EA=1;//使能总中断
	TR0=1;//开启T0时钟
}

/*****************************************************************
*@Function: ServiceTimer0     //
*@Description:定时器T0中断函数     //
*@Input: 无//
*@Output: 无//
*@Return: 无 //
*@Others:无  //
/*****************************************************************/
void ServiceTimer0 () interrupt 1
{
	TH0=(65535-50000+1)/256;
	TL0=(65535-50000+1)%256;
	
	t_005s++;
	if(t_005s==20)//如果满足20个0.05秒,则t_005s清零,t_s加1,即秒数加1
	{
		t_s++;
		t_005s=0;
		if(t_s==60)//如果满60秒,t_s清零,t_m加1,即分钟加1
		{
			t_m++;
			t_s=0;
		}
		if(t_m==99)//如果分钟满99分,则清零
		{
			t_m=0;
		}
	}
}

/*****************************************************************
*@Function: DelayK     //
*@Description:用于按键消抖延时 //
*@Input:无 //
*@Output: 无//
*@Return:  无//
*@Others: 无 //
/*****************************************************************/
void DelayK(unsigned char t)
{
	while(t--);
}

/*****************************************************************
*@Function: ScanKeys     //
*@Description: 按键S4,S5扫描    //
*@Input:无 //
*@Output: 无//
*@Return: 无 //
*@Others: 无 //
/*****************************************************************/
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();
	}
}

感谢大家的观看

欢迎大家提出问题并指正~

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
数码管是一种常见的数字显示器件,可以用于显示各种数字、字母等字符。在单片机应用中,数码管通常用于显示计数器、计时器、温度、湿度等实时数据。 数码管的种类有很多,包括共阳数码管、共阴数码管、共阳共阴混合数码管等。其中,共阳数码管是最常见的一种,也是本文所涉及的数码管类型。 单片机控制数码管的原理是通过对数码管的各个管脚进行控制,使其显示相应的数字或字符。数码管的控制方式有两种,即静态显示和动态显示。 静态显示是指将要显示的数字或字符的每一位分别输出到数码管的每个管脚上,然后使其保持不变,从而实现显示效果。静态显示的缺点是需要使用大量的I/O口,且不能灵活地改变显示内容。 动态显示是指将要显示的数字或字符的每一位依次输出到数码管的每个管脚上,并在短时间内快速切换下一个数字或字符,从而形成连续的显示效果。动态显示的优点是可以使用较少的I/O口,且可以灵活地改变显示内容。 以下是一个简单的动态显示数码管的实现示例: 1. 定义数码管的引脚 ```c #define DIG_PORT P2 // 数码管位选端口 #define DIG_COM 0x00 // 数码管位选端口初始值 #define LED_PORT P0 // 数码管段选端口 ``` 2. 定义数码管显示的数字或字符 ```c unsigned char code ledChar[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; ``` 3. 实现数码管动态显示函数 ```c void display(unsigned char i) { unsigned char j, k; for (j = 0; j < 8; j++) { DIG_PORT = DIG_COM | (1 << j); // 选择数码管位(从左到右) for (k = 0; k < 100; k++); // 延时,视情况可调整 LED_PORT = ledChar[i]; // 显示数码管上的数字或字符 } } ``` 4. 调用数码管动态显示函数 ```c int main() { unsigned char i = 0; while (1) { display(i % 10); // 显示数字 i 的个位数 i++; } return 0; } ``` 以上就是一个简单的数码管动态显示的实现示例。需要注意的是,数码管的控制方式和具体实现方法可能因不同的硬件平台和编程语言而有所不同。因此,在具体应用中需要根据实际情况进行适当的调整和修改。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IC 1396

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值