【蓝桥杯—单片机】定时器/计数器的原理和应用| 备赛 | 笔记

前言

学习资料参考

基本应用
https://www.bilibili.com/video/BV1Bt41187hw?p=9&vd_source=e2191f89c557f5ac44bb6c7aa3967c7c
进阶应用

LED基本控制可以参考以下笔记
https://blog.csdn.net/zicheng_G/article/details/142025188?fromshare=blogdetail&sharetype=blogdetail&sharerId=142025188&sharerefer=PC&sharesource=zicheng_G&sharefrom=from_link
数码管的基本控制可以参考以下笔记
https://blog.csdn.net/zicheng_G/article/details/142304378?fromshare=blogdetail&sharetype=blogdetail&sharerId=142304378&sharerefer=PC&sharesource=zicheng_G&sharefrom=from_link

本节训练重点

  1. 定时器实现秒闪功能:利用51单片机的定时/计数器T0的模式1实现间隔定时,每隔1秒L1指示灯闪烁一下,也就是点亮0.5秒,熄灭0.5秒;每隔10秒L8指示灯闪烁一下,即点亮5秒,熄灭5秒。
  2. 定时器实现秒表功能:利用定时器T0、数码管模块和2个独立按键,设计一个秒表,具有清零、暂停、启动功能。

定时器/计数器

原理

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

计数器的技术脉冲有两个来源:

  1. 系统时钟振荡器输出的12分频
  2. T0或T1引脚输入的外部脉冲信号

计数器每接收到一个脉冲是计数脉冲,计数器加1,当计数器记满时溢出,计数归零,计数器向内核发出中断请求,进入中断函数。

关于定时器的相关知识,可以参考我的51单片机的笔记中9的内容,链接如下:
https://blog.csdn.net/zicheng_G/article/details/140287386?fromshare=blogdetail&sharetype=blogdetail&sharerId=140287386&sharerefer=PC&sharesource=zicheng_G&sharefrom=from_link

编程思路

定时器实现秒闪功能

/*函数声明区域*/
#include <REGX52.H>

/*变量声明区域*/
sbit HC89C53_C = P2^7;
sbit HC89C53_B = P2^6;
sbit HC89C53_A = P2^5;
sbit L1 = P0^0;
sbit L8 = P0^7;
unsigned char CountShort;  //定时器短定时专用
unsigned char CountLong;   //定时器长定时专用

/*三八译码器选中Y4*/
void HC89C53()
{
	HC89C53_C = 1;
	HC89C53_B = 0;
	HC89C53_A = 0;
}


/*定时器初始化函数*/
void Timer0Init(void)		//50毫秒@12.000MHz
{
	/*TMOD=0x01,选中定时器1,置为计时器模式*/
	TMOD &= 0xF0;		//把TMOD的低四位清零,高四位保持不变
	TMOD |= 0x01;		//把TMOD最低位置1,高四位保持不变
	
	/*设置定时初值,50毫秒*/
	TL0 = (65535 - 50000) / 256;		
	TH0 = (65535 - 50000) % 256;		
	
	ET0=1;    //中断允许控制寄存器闭合
	EA=1;     //CPU开放中断
	TR0 = 1;		//定时器0开始计时
}

/*主函数*/
void main()
{
	Timer0Init();
	while(1)
	{
		
	}
}

/*定时器中断函数*/
void ServiceTimer0() interrupt 1
{
	/*重新配置定时值,50毫秒*/
	TL0 = (65535 - 50000) / 256;		
	TH0 = (65535 - 50000) % 256;
	
	CountShort++;
	CountLong++;
	
	/*每隔500毫秒L1指示灯闪烁一下*/
	if(CountShort == 10)
	{
		HC89C53();
		L1 = ~L1;
		CountShort = 0;
	}
	
	/*每隔10秒L8指示灯闪烁一下*/
	if(CountLong == 100)
	{
		HC89C53();
		L8 = ~L8;
		CountLong = 0;
	}
}

定时器实现秒表功能

  1. 显示格式为:分 - 秒 - 50ms记一次
  2. 独立按键S4控制暂停和启动,S5控制清零,按键按下有效。
/*函数声明区域*/
#include <REGX52.H>

/*变量声明区域*/
sbit HC138_C = P2^7;
sbit HC138_B = P2^6;
sbit HC138_A = P2^5;

sbit S4=P3^3;//定义独立按键
sbit S5=P3^2;

unsigned char min,s,x5ms;//定义变量记录分、秒、0.05毫秒
unsigned char code lib_Bit_Number[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//数码管显示的数字和分隔符

/*三八译码器选中函数*/
void HC138(unsigned char Y)
{
	switch(Y)
	{
		case 6:
		{
			HC138_C = 1;
	    HC138_B = 1;
    	HC138_A = 0;
			break;
		}
		case 7:
		{
			HC138_C = 1;
	    HC138_B = 1;
    	HC138_A = 1;
			break;
		}
	}
	
}

/*单个数码管的静态显示函数*/
void NiTu_Sig(unsigned char Seg,value)
{	
	/*数码管位选*/
	HC138(6);     
	P0=(0x01<<Seg);
	
	/*数码管段选*/
	HC138(7);      
	P0=lib_Bit_Number[value];
}

/*数码管用的延时延时函数*/
void DelayNi(unsigned char t)
{
	while(t--);
}

/*数码管的动态显示*/
void NiTu_Show()
{
	/*第三部分的显示*/
	NiTu_Sig(7,x5ms%10);
	DelayNi(500);
	NiTu_Sig(6,x5ms/10);
	DelayNi(500);
	
	/*第二部分的显示*/
	NiTu_Sig(4,s%10);
	DelayNi(500);
	NiTu_Sig(3,s/10);
	DelayNi(500);
	
	/*第一部分的显示*/
	NiTu_Sig(1,min%10);
	DelayNi(500);
	NiTu_Sig(0,min/10);
	DelayNi(500);
	
	/*分隔符的显示*/
	NiTu_Sig(5,10);
	DelayNi(500);
	NiTu_Sig(2,10);
	DelayNi(500);
}

/*按键去抖函数*/
void DelayKey(unsigned char t)
{
	while(t--);
}

/*独立按键扫描函数*/
void Key_Scan()
{
	/*S4按下,计时暂停或启动*/
	if(S4==0)
	{
		DelayKey(100);
		if(S4==0)
		{
			TR0= ~TR0;
			while(S4==0);
		}
	}
	
	/*S5按下,数码管清零*/
	if(S5==0)
	{
		DelayKey(100);
		if(S5==0)
		{
			x5ms=0;
			s=0;
			min=0;
			while(S5==0);
		}
	}
}

/*定时器初始化函数*/
void Timer0Init(void)		//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	
	TL0 = 0xB0;		//设置定时初值
	TH0 = 0x3C;		//设置定时初值
	
	ET0 = 1;		
	EA=1;
	TR0 = 1;		//定时器0开始计时
}


/*主函数*/
void main()
{
	Timer0Init();
	while(1)
	{
		NiTu_Show();
		Key_Scan();
	}
}

/*定时器中断函数*/
void ServiceTimer0() interrupt 1
{
	/*重新配置定时值,50毫秒*/
	TL0 = 0xB0;		
	TH0 = 0x3C;
	
	x5ms++;//数码管第三部分加一
	if(x5ms==20)//当计时时间到达100毫秒时
	{
		s++; //每隔100ms,秒数加一
		x5ms=0;//第三部分重新开始计时
		if(s==60)
		{
			min++;//每隔60s,分钟加一
			s=0;//秒数部分重新开始计时
			
			/*当分钟计到100时,计时重新开始*/
			if(min==100)
			{
				x5ms=0;
				s=0;
				min=0;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值