【蓝桥杯练习-定时器】

定时器练习

内容来自B站小蜜蜂老师

51单片机有两个定时/计数器T0和T1,为16位加法计数器,由低8位TLx和高8位THx两个寄存器组成,最大计数值为65535个计数脉冲。
该加1计数器的计数脉冲来源有2个:
<1> 系统时钟振荡器输出的12分频。
<2> T0或T1引脚输入的外部脉冲信号。
每接收到一个计数脉冲,计数器就会加1,当计数值累计至全为1时(8位255,13位8191,16位65535),再输入一个计数脉冲,计数器便会溢出回零,并且计数器的溢出是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) / 256;
TL0 = 0xef; 或者 TL0 = (65535 - 10000) % 256;

定时/计数器相关的寄存器
TMOD 、TCON 、IE

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Practise

在这里插入图片描述

#include "reg52.h"

//定义两个led灯
sbit L1 = P0^1;
sbit L8 = P0^7;
//--------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
 	switch(n)
	{
		case 4: P2 = P2 | 0x1f; P2 = 0x80; break;
		case 5: P2 = P2 | 0x1f; P2 = 0xa0; break;
		case 6: P2 = P2 | 0x1f; P2 = 0xc0; break;
		case 7: P2 = P2 | 0x1f; P2 = 0xe0; break; 
	}
}
//--------------------------------------------------------------------
void Init_Timer0(void)
{
 	TMOD = 0x01;  //定时0 方式二16位
	TH0 = (65535-50000)/256; //高八位
	TL0 = (65535-50000)%256; //低八位
	ET0 = 1; //定时器0中断使能
	TR0 = 1;//启动定时
	EA = 1; //总中断
}
//----------------------------------------------------------------------

void main(void)
{
	Init_Timer0();
	Init_74HC138(4);	//选通Y4控制led
	while(1)
	{

	}
}


//--------------------------定时器0中断服务函数-------------------------
void Server_Timer0() interrupt 	1
{
	unsigned char t;
	//该方式没有自动重装载 需要手动重新配置
 	TH0 = (65535-50000)/256; //高八位
	TL0 = (65535-50000)%256; //低八位
	t++;
	if(t % 10 == 0) //0.5s
	{
	 		L1 = ~L1; //0.5s闪烁
	}
	if(t % 100 == 0)
	{
	  L8 = ~L8;		  //5s闪烁
		t = 0;		 //清零重新计数
	}
}
//---------------------------------------------------------------------

Practise 2 定时器进阶
在这里插入图片描述

#include "reg52.h"


/********************************************
Date:2022-1-11
Author:小殷同学
Learn From:B 站小蜜蜂老师
*********************************************/

unsigned char min = 0,s =  0, ms = 0; //定义三个变量分别记录分 秒 毫秒 的时间
sbit S4 = P3^3;		  //重启和暂停
sbit S5 = P3^2;		 //清零

//共阳数目管段码
unsigned char month = 0;	 //定义一个变量让其变化显示
//0-f  0xbf代表 -
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
															   0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf};

//-----------------------------简单延时-----------------------------
void Delay(unsigned int t)
{
	while(t--);
}
//-------------------------------------------------------------------


//--------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
 	switch(n)
	{
		case 4: P2 = P2 | 0x1f; P2 = 0x80; break;
		case 5: P2 = P2 | 0x1f; P2 = 0xa0; break;
		case 6: P2 = P2 | 0x1f; P2 = 0xc0; break;
		case 7: P2 = P2 | 0x1f; P2 = 0xe0; break; 
	}
}
//--------------------------------------------------------------------

//-----------------------------系统初始化-----------------------------
void InitSystem(void)
{
 	 Init_74HC138(5);			//Y5选通
	 P0 = 0x00; //关闭继电器和蜂鸣器
	 Init_74HC138(4);		 //Y4
	 P0 = 0xff; //关闭LED

}
//----------------------------------------------------------------------


//-------------------------------数码管按位选择------------------------
//pos ->数码管的位置  dat->数码管数据

void SMG_DisplayBit(unsigned char pos ,unsigned char dat)
{
		Init_74HC138(6);		 //Y6 ->数码管位选控制
		P0 = 0x01 << pos;
		Init_74HC138(7);		 //Y7 ->数码管段码控制
		P0 = dat;
}
//---------------------------------------------------------------------


//------------------------------数码管数据显示-------------------------
void SMG_DisplayData(void)
{
	 SMG_DisplayBit(0,SMG_Duan[min/10]); //分的十位
	 Delay(200);
	 SMG_DisplayBit(1,SMG_Duan[min%10]); //分的个位
	 Delay(200);
	 SMG_DisplayBit(2,SMG_Duan[16]); //-
	 Delay(200);
	 SMG_DisplayBit(3,SMG_Duan[s/10]); //秒的十位
	 Delay(200);
	 SMG_DisplayBit(4,SMG_Duan[s%10]); //秒的十位
	 Delay(200);
	 SMG_DisplayBit(5,SMG_Duan[16]); //-
	 Delay(200);
	 SMG_DisplayBit(6,SMG_Duan[ms/10]); //毫秒的十位
	 Delay(200);
	 SMG_DisplayBit(7,SMG_Duan[ms%10]); //毫秒的十位
	 Delay(200);

}


//---------------------------------------------------------------------

//------------------------------按键功能函数---------------------------
//S4 ->重启和暂停  S5 ->清零
//这里要注意的是在我们等待按键松开的时候数码管也要继续显示 所以在下面编写中将数码管显示放到等待按键松开中
void Key_Tackle(void)
{
 	if(S4 == 0)
	{
		Delay(20);
		if(S4 == 0)
		{
		 	TR0 = ~TR0;
			while(S4 == 0)
			{
			 	SMG_DisplayData();
			}
		}
	
	}

	if(S5 == 0)
	{
		Delay(20);
		if(S5 == 0)
		{
			min = 0;
			s   = 0;
			ms  = 0;
			while(S5 == 0)
			{
			 	 SMG_DisplayData();
			}
		}
	
	} 

}

//---------------------------------------------------------------------

//-------------------------------定时器0初始化-------------------------
void Init_Timer0(void)
{
 	TMOD = 0x01;  //定时0 方式二16位
	TH0 = (65535-50000)/256; //高八位
	TL0 = (65535-50000)%256; //低八位
	ET0 = 1; //定时器0中断使能
	TR0 = 1;//启动定时
	EA = 1; //总中断
}
//----------------------------------------------------------------------


//----------------------------------主函数-------------------------------
void main(void)
{
	Init_Timer0();
	InitSystem();
	while(1)
	{
		 SMG_DisplayData();
		 Key_Tackle();
		
	}
}


//--------------------------定时器0中断服务函数-------------------------
void Server_Timer0() interrupt 	1
{
	
	//该方式没有自动重装载 需要手动重新配置
 	TH0 = (65535-50000)/256; //高八位
	TL0 = (65535-50000)%256; //低八位
	ms++;
	if(ms == 10)  //10ms -> 1s
	{
		ms = 0;//清零
		s++;
		if(s == 60) //60s ->1min
		{
		 	s =  0; //清零
			min++;
			if(min == 60)
			{
				min = 0; //清零
			}
		}
	}
	
}
//---------------------------------------------------------------------

总结

此次定时器的练习还是比较综合的,将前面所学的数码管显示、按键处理、定时器中断等等都结合了起来。老师说的很对,对单个功能函数的编写很简单,关键是我们如何将其整合起来去处理功能逻辑最优化的去实现我们想要的功能这才是最重要的。
加油 ^^

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小殷学长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值