电子产品世界 » 论坛首页 » 高校社团 » 坤创E-Geek/天科大新电社 » 07. 单片机定时计数器的使用

共11条 1/2 1 2 跳转至

07. 单片机定时计数器的使用

工程师
2019-01-25 21:45:33    评分

很开心,大家能够继续跟上进度,进行单片机定时计数器的学习。单片机的定时计数器,是学习单片机一个非常重要的点,正确的使用定时计数器,能够减轻单片机CPU的负担,可以增强程序的实时性。例如我们之前所用的ms级别的延时函数,是通过两个for循环的嵌套,使程序不断的在原地进行“等待”,这样一来,单片机的CPU就会在延时的同时,被100%占用,导致当延时函数执行时,单片机无法做其他的任何事情。显然,这对单片机CPU的资源是一个极大的浪费,特别是程序中有较长的延时需求时,更是如此。而定时计数器的出现,则能够很好的解决了这一问题。

当然,从蓝桥杯竞赛的角度来说,定时计数器的使用也是一个较重要的编程技能,聪明的使用定时计数器,能够让你的程序更加灵活,也更容易设计、编写和维护

本节针对定时计数器,设计了两个练习题,题目要求如下:

题1、在数码管上显示字符8,利用定时器定时每1秒左移动一位

题2、数码管初始显示0,利用定时器定时每1秒数值加1

下面仍照惯例给出两个题目的代码,并在文末给出所有代码压缩包的下载链接,请大家自行下载哈~当然,本系列中所有的代码,均在相对应的开发板上验证通过,大家可以放心下载~

-----------------------蓝桥板代码---------------------

蓝桥板题1代码:

/*********************************************************************
1、在数码管上显示字符8,利用定时器定时每1秒左移动一位
**********************************************************************/
#include<stc15f2k60s2.h>
#include<intrins.h>

#define  uchar unsigned char
#define  uint  unsigned int 
	
uchar code smgwei[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80,0x01};
uint tt;
uchar a=8;
void init();  //蓝桥杯板初始化程序
void keyScan();//键盘扫描
void delayms(uint z);//ms级延时函数
void timer0Init(void);		//5毫秒@11.0592MHz
void display(uchar j ); //数码管显示函数

/**********************主函数********************************/
/*void main()
{
	init();
	timer0Init();
	while(1)
	{   
		EA=1;     //开总中断
		ET0=1;	  //开定时计数器中断
		if(tt>=200)
		{
			tt=0;a--;
			if(a==0)a=8; 
		}
		display(a);
	}
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=845;y>0;y--);
}

void init()
{
   P2=0xa0; 
	 P0=0x00;   //关闭继电器蜂鸣器
	 P2=0x80;
	 P0=0xff;  //关闭led灯
	 P2=0xc0;
	 P0=0xff; //选择所有数码管
	 P2=0xff;
	 P0=0xff; //关闭所有数码管
}

void timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void timer0()interrupt 1
{
   tt++;
}

void display(uchar j )
{
  P2=0xc0;
	P0=smgwei[j];  //位选
	P2=0xff;
	P0=0x80;      //段选
	delayms(5);
}

蓝桥板题2代码:

/***************************************************************
2、数码管初始显示0,利用定时器定时每1秒数值加1
****************************************************************/
#include<stc15f2k60s2.h>
#include"intrins.h"

#define uchar unsigned char
#define uint  unsigned int 
	
uchar code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar yi,er,san,si,wu,liu,qi,ba;
uint num;
uchar tt;
void  init();//蓝桥杯板初始化程序
void  delayms(uint z);//ms级延时函数
void  timer0Init(void);		//5毫秒@11.0592MHz
void  displayOne(uchar yi,uchar er);//第一 二个数码管显示函数
void  displayTwo(uchar san,uchar si);//第三 四个数码管显示函数
void  displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数
void  displayFour(uchar qi,uchar ba);//第七 八个数码管显示函数

/****************************主函数**********************************/
void main()
{
	init();
	timer0Init();		//5毫秒@11.0592MHz
	while(1)
	{
		yi=11; er=11;san=11;si=11;wu=11;liu=num/100; qi=num/10%10;ba=num%10;
		
    if(tt>=200){tt=0;num=num+1;}
		else if(num>999){num=0;}
		displayOne(yi,er);
		displayTwo(san,si);
		displayThree(wu,liu);
		displayFour(qi,ba);
	}
}

void timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}

void  timer0()interrupt 1
{
  tt++;
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=845;y>0;y--);
}
	
void init()
{
   P2=0xa0; 
	 P0=0x00;   //关闭继电器蜂鸣器
	 P2=0x80;
	 P0=0xff;  //关闭led灯
	 P2=0xc0;
	 P0=0xff; //选择所有数码管
	 P2=0xff;
	 P0=0xff; //关闭所有数码管
}

void  displayOne(uchar yi,uchar er)
{
   P2=0xc0;
	 P0=0x01;     //选通第一个数码管
	 P2=0xff;
	 P0=smgtab[yi];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x02;    //选通第二个数码管
	 P2=0xff;
	 P0=smgtab[er];//位选
	 delayms(1);
}

void  displayTwo(uchar san,uchar si)
{
   P2=0xc0;
	 P0=0x04;     //选通第三个数码管
	 P2=0xff;
	 P0=smgtab[san];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x08;    //选通第四个数码管
	 P2=0xff;
	 P0=smgtab[si];//位选
	 delayms(1);
}

void  displayThree(uchar wu,uchar liu)
{
   P2=0xc0;
	 P0=0x10;   //选通第五个数码管
   P2=0xff;
	 P0=smgtab[wu];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x20;  //选通第六个数码管
	 P2=0xff;
	 P0=smgtab[liu];//位选
	 delayms(1);
}

void  displayFour(uchar qi,uchar ba)
{
   P2=0xc0;
	 P0=0x40;  //选通第七个数码管
	 P2=0xff;
	 P0=smgtab[qi];//位选
	 delayms(1);
	
	 P2=0xc0;
	 P0=0x80;  //选通第八个数码管
	 P2=0xff;
	 P0=smgtab[ba];//位选
	 delayms(1);
}

-----------------------小红板代码----------------------

小红板题1代码:

/**************************************************
1、在数码管上显示字符8,利用定时器定时每1秒左移动一位
**************************************************/
#include"reg52.h"
#define uchar unsigned char
#define uint  unsigned int 

sbit	P_HC595_SER   = P2^7;	//pin 14	SER		data input
sbit	P_HC595_RCLK  = P2^5;	//pin 12	RCLk	store (latch) clock
sbit	P_HC595_SRCLK = P2^6;	//pin 11	SRCLK	Shift data clock

uchar  code smgwei[]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F,0XFE}; 
uchar i=8;
uint tt;
void smg_Init(); //数码管初始化程序
void delayms(uint z);//ms级延时函数
void display(uchar j);//数码管显示函数
void timer0Init(void);//50毫秒@11.0592MHz
void Send_595(unsigned char dat);

/**************主函数************************/
/*void main()
{
	smg_Init();
	timer0Init();
	while(1)
	{
		EA=1;
		ET0=1;	 
		if(tt>=20)
		{
			tt=0;i--;
			if(i==0)i=8; 
		}
		display(i);
	}
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

void SMG_Init()
{
	Send_595(0x00);  //同时选择8个数码管
	Send_595(0x00);	 //让8个数码管同时显示消隐字符
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选	
}

void Send_595(unsigned char dat)	//发送一个字节
{		
	unsigned char	i;
	for(i=0; i<8; i++)
	{
		if(dat & 0x80)	    //判断dat的最高位是否为1
			P_HC595_SER = 1;  //最高位如果为1,则令P2.7 = 1
		else			
			P_HC595_SER = 0;  //最高位如果为0,则令P2.7 = 0
		
		P_HC595_SRCLK = 0;
		P_HC595_SRCLK = 1;
		P_HC595_SRCLK = 0;  //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端
		dat = dat << 1;     //将dat左移一位,取次高位
	}
}
void timer0Init(void)		//50毫秒@11.0592MHz
{
    TR0 = 1;//启动T0
    TMOD = 0x01;//T0为定时器,工作模式1 16位计数器
    TH0 = 0x4b;
    TL0 = 0xfc;//0x4bfc	定时50ms		
}

void timer0()interrupt 1
{
   tt++;
}
void display(uchar j )
{
    Send_595( smgwei[j]); 
    Send_595(0x7f);
    P_HC595_RCLK = 0;
    P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
    delayms(5);
}

小红板题2代码:

/********************************************
2、数码管初始显示0,利用定时器定时每1秒数值加1。
********************************************/
#include"reg52.h"
#define uchar unsigned char
#define uint  unsigned int 

sbit	P_HC595_SER   = P2^7;	//pin 14	SER		data input
sbit	P_HC595_RCLK  = P2^5;	//pin 12	RCLk	store (latch) clock
sbit	P_HC595_SRCLK = P2^6;	//pin 11	SRCLK	Shift data clock

sbit  s5=P3^0;
sbit  s10=P3^1;
sbit  s15=P3^2;
sbit  s20=P3^3;

uchar  code smgtab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};	
uint tt;
uint num;
uchar yi,er,san,si,wu,liu,qi,ba;
void  smg_Init();//数码管初始化程序
void  delayms(uint z);//ms级延时函数
void  timer0Init(void);		//50毫秒@11.0592MHz
void  Send_595(unsigned char dat);
void  displayOne(uchar yi,uchar er);//第一 二个数码管显示函数
void  displayTwo(uchar san,uchar si);//第三 四个数码管显示函数
void  displayThree(uchar wu,uchar liu);//第五 六个数码管显示函数
void  displayFour(uchar qi,uchar ba); //第七 八个数码管显示函数

/*******************主函数************************************/
void main()
{
	smg_Init();
	timer0Init();		//50毫秒@11.0592MHz
	while(1)
	{
		yi=11;er=11;san=11;si=11;wu=11;liu=num/100;qi=num/10%10;ba=num%10;
		EA=1;
		ET0=1;
		if(tt>=20){tt=0;num=num+1;}
		else if(num>999){num=0;}      //uint形最大计数值为65536
		displayOne(yi,er);
		displayTwo(san,si);
		displayThree(wu,liu);
		displayFour(qi,ba);
	}
}

void delayms(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}


void timer0Init(void)		//50毫秒@11.0592MHz
{
	TR0 = 1;//启动T0
	TMOD = 0x01;//T0为定时器,工作模式1 16位计数器
	TH0 = 0x4b;
	TL0 = 0xfc;//0x4bfc	定时50ms	
}

void timer0()interrupt 1
{
	tt++;	
}

void smg_Init()
{
	Send_595(0x00);  //同时选择8个数码管
	Send_595(0x00);	 //让8个数码管同时显示消隐字符
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选	
}


void Send_595(unsigned char dat)	//发送一个字节
{		
	unsigned char	i;
	for(i=0; i<8; i++)
	{
		if(dat & 0x80)	    //判断dat的最高位是否为1
			P_HC595_SER = 1;  //最高位如果为1,则令P2.7 = 1
		else			
			P_HC595_SER = 0;  //最高位如果为0,则令P2.7 = 0
		
		P_HC595_SRCLK = 0;
		P_HC595_SRCLK = 1;
		P_HC595_SRCLK = 0;  //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端
		dat = dat << 1;     //将dat左移一位,取次高位
	}
}

void  displayOne(uchar yi,uchar er)
{
	Send_595(0xfe);     //选通第一个数码管
	Send_595(smgtab[yi]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);

	Send_595(0xfd);     //选通第二个数码管
	Send_595(smgtab[er]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);
}

void  displayTwo(uchar san,uchar si)
{
	Send_595(0xfb);    //选通第三个数码管
	Send_595(smgtab[san]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);

	Send_595(0xf7);   //选通第四个数码管
	Send_595(smgtab[si]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);
}

void  displayThree(uchar wu,uchar liu)
{
	Send_595(0xef);   //选通第五个数码管
	Send_595(smgtab[wu]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);

	Send_595(0xdf);  //选通第六个数码管
	Send_595(smgtab[liu]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);
}

void  displayFour(uchar qi,uchar ba)
{
	Send_595(0xbf);   //选通第七个数码管
	Send_595(smgtab[qi]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);

	Send_595(0x7f);   //选通第八个数码管
	Send_595(smgtab[ba]);//段选
	P_HC595_RCLK = 0;
	P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选
	delayms(1);
}

----------------所有代码打包下载链接------------------

07单片机定时计数器的使用_全部代码打包.zip

 

大家可以继续提前接着往下进行 08DS18B20温度传感器进行数据采集和使用的题目练习~如对代码有任何问题,请在下方回帖留言呀。

曾子在文末曰:“每篇文章末尾都有鸡汤,好烦啊。今天就什么都不曰了,正儿八经一回吧,明天再接着曰。”





关键词: 定时     计数器     使用     定时器    

菜鸟
2019-01-25 22:11:34    评分
2楼

感谢分享,51的资源缺陷往往考验着使用者,有的时候不得不考虑CPU运算时间的问题啊,力挺楼主!


菜鸟
2019-01-26 09:43:10    评分
3楼

代码的注释真的很详细,写的真是负责任,支持楼主!!!!!


菜鸟
2019-01-26 15:17:50    评分
4楼

赞一个·


菜鸟
2019-01-26 18:27:13    评分
5楼
感谢楼主分享

菜鸟
2019-01-27 18:45:19    评分
6楼
哇,膜拜楼主,解答了我好久的困惑,手动比心,哈哈哈

菜鸟
2019-01-27 18:52:52    评分
7楼

对于备战的我来说太需要了,感谢老师


菜鸟
2019-01-31 14:04:45    评分
8楼

定时器也是蓝桥杯比赛中的必考点   也是非常重要的


专家
2019-02-13 08:31:42    评分
9楼

学习单片机定时计数器l啦!


菜鸟
2019-02-27 18:04:02    评分
10楼
void timer0Init(void);这里括号里的void是什么意思?

共11条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]