2021/11/14定时器的相关问题

1.简单查询实现运用定时器实现小灯闪烁

#include<reg52.h>
void timer0_Init();
sbit LED=P1^0;

void main()
{ 
	timer0_Init();
	while(1)
	{
		if(TF0==1)
		{
			TF0=0;//方便下次再次计时
			TH0=(65536-50000)/256;//重新赋值
	    TL0=(65536-50000)%256;
			LED=~LED;
		}
	}
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0
	TMOD=0x01;
	//2.初值计算
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	//3.溢出标志位设为1开启
	TR0=1;
}

在这里插入图片描述

2.中断功能实现LED闪烁

#include<reg52.h>
sbit LED=P1^0;
void timer0_ISR();
void timer0_Init();
void main()
{
	timer0_Init();
	while(1)
	{
		
	}
}
void timer0_Init()
{
	TMOD=0x01;
	TH0=0x3C;
	TL0=0xB0;
	TF0=0;
	ET0=1;
	EA=1;
	TR0=1;
}
void timer0_ISR() interrupt 1
{
	TR0=0;
	TH0=0x3C;
	TL0=0xB0;
	LED=~LED;
	TR0=1;
}

在这里插入图片描述
拓展:由于定时器只有0-65536的范围,工作时间最大65.36ms那么如果想长时间定时怎么办,那么就需要增加一个变量,类似于时分秒的计数原理,分针转过60,时针才能加1。

#include<reg52.h>
sbit LED=P1^0;
unsigned char timerCnt;
void timer0_ISR();
void timer0_Init();
void main()
{
	timer0_Init();
	while(1)
	{
		
	}
}
void timer0_Init()
{
	TMOD=0x01;
	TH0=0x3C;
	TL0=0xB0;
	TF0=0;
	ET0=1;
	EA=1;
	TR0=1;
}
void timer0_ISR() interrupt 1
{
	TR0=0;
	TH0=0x3C;
	TL0=0xB0;
	timerCnt++;
	if(timerCnt>=10)
	{
		timerCnt=0;
		LED=~LED;
	}
	TR0=1;
}

在这里插入图片描述

3.简单查询法实现流水灯

#include<reg52.h>
#include<intrins.h>
void timer0_Init();
unsigned char timeCnt;
unsigned char temp=0xfe;
void main()
{ 
	timer0_Init();
	while(1)
	{
		if(TF0==1)
		{
			TF0=0;//方便下次再次计时
			TH0=(65536-50000)/256;//重新赋值
	    TL0=(65536-50000)%256;
			//1s=1000ms 
			timeCnt++;
			if(timeCnt>=20)
			{
				timeCnt=0;
        P1=temp;
				temp=_crol_(temp,1);
			}
		}
	}
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD=0x01;
	//2.初值计算
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	//3.溢出标志位设为1开启
	TR0=1;
}

在这里插入图片描述

4.定时器+中断方式实现数码管显示

写法一:

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
void timer0_Init();
unsigned int systemTimer;
unsigned int num=1234;
unsigned char LEDBUF[]={22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
void display_Service()
{
	  LEDBUF[0]=num/1000;
		LEDBUF[1]=num/100%10;
		LEDBUF[2]=num/10%10;
		LEDBUF[3]=num%10;
}

void main()
{ 
	timer0_Init();
	while( systemTimer<50000)
	{
		systemTimer++;
	}
	while(1)
	{
		display_Service();
	}
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	EA=1;
	//3.溢出标志位设为1开启
	TR0=1;
}
void time0_ISR() interrupt 1
{
	TR0=0;
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}

写法二:(软件在定时器内部进行)

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit LED=P1^0;
void timer0_Init();
unsigned int systemTimer=0;
unsigned int systemFlag=1;
unsigned int num=1234;
unsigned char LEDBUF[]={22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
void display_Service()
{
	  LEDBUF[0]=num/1000;
		LEDBUF[1]=num/100%10;
		LEDBUF[2]=num/10%10;
		LEDBUF[3]=num%10;
}

void main()
{ 
	timer0_Init();
	do
	{
		if(systemTimer%50==0)
		{
			LED=~LED;
		}
	}while(systemTimer<5000);
	
	systemFlag=0;
	
	while(1)
	{
		display_Service();
	}
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	EA=1;
	//3.溢出标志位设为1开启
	TR0=1;
}
void time0_ISR() interrupt 1
{
	TR0=0;
	if(systemFlag==1)
	{
		systemTimer++;
	}
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}

在这里插入图片描述

5.综合实践(流水灯,倒计时,数码管显示)

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit LED=P1^0;
void timer0_Init();
void timer1_Init();
unsigned char secCnt;
unsigned char sec=60;
unsigned char timerCnt;
unsigned char temp=0xfe;
unsigned char LEDBUF[]={22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
void display_Service()
{
	  LEDBUF[0]=23;
		LEDBUF[1]=23;
		LEDBUF[2]=sec/10;
		LEDBUF[3]=sec%10;
}

void main()
{ 
	timer0_Init();
	timer1_Init();
	EA=1;
	while(1)
	{
		display_Service();
	}
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	//EA=1;
	//3.溢出标志位设为1开启
	TR0=1;
}
void timer1_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0x0F;
	TMOD |=0x10;
	//2.初值计算
	TH1=0x3C;
	TL1=0xB0;
	TF1=0;
	ET1=1;
	//EA=1;
	//3.溢出标志位设为1开启
	TR1=1;
}
void time0_ISR() interrupt 1
{
	TR0=0;
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}
void time1_ISR() interrupt 3
{
	TR1=0;
	secCnt++;
	timerCnt++;
	if(timerCnt>=20)
	{
		timerCnt=0;
		P1=temp;
		temp=_crol_(temp,1);
	}
	if(secCnt>=20)
	{
		secCnt=0;
		sec--;
		if(sec>60)
		{
			sec=60;
		}
	}
	TH1=0xB0;
	TL1=0x3C;
	TR1=1;
}

在这里插入图片描述

6.外部中断实现数码管的增加和减少

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
void timer0_Init();
void EX0_Init();
void EX1_Init();
unsigned int numCnt=0;
unsigned char LEDBUF[]={0,0,0,0};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
void display_Service()
{
	  LEDBUF[0]=numCnt/1000;
		LEDBUF[1]=numCnt/100%10;
		LEDBUF[2]=numCnt/10%10;
		LEDBUF[3]=numCnt%10;
}

void main()
{ 
	timer0_Init();
	EX0_Init();
	EX1_Init();
	EA=1;//中断总开关
	while(1)
	{
		display_Service();
	}
}
void EX0_Init()
{
	IT0=1;//触发方式 下降沿
	EX0=1;
	
}
void EX1_Init()
{
	IT1=1;//触发方式 下降沿
	EX1=1;
	
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	//EA=1;
	//3.溢出标志位设为1开启
	TR0=1;
}

void time0_ISR() interrupt 1
{
	TR0=0;
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}
void EX0_ISR() interrupt 0
{
	EX0=0;
	numCnt++;
	if(numCnt>9999)
		numCnt=0;
	EX0=1;
	
}
void EX1_ISR() interrupt 2
{
	EX1=0;
	numCnt--;
	if(numCnt>9999)
		numCnt=0;
	EX1=1;
}

改进:实现数码管根据数字开启数码管。

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
void timer0_Init();
void EX0_Init();
void EX1_Init();
unsigned int numCnt=0;
unsigned int temp0;
unsigned int temp1;
unsigned int temp2;
unsigned int temp3;
unsigned char LEDBUF[]={0,0,0,0};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
void display_Service()
{
	  temp0=numCnt/1000;
	  temp1=numCnt/100%10;
	  temp2=numCnt/10%10;
	  temp3=numCnt%10;
	  if(numCnt<1000)
	     LEDBUF[0]=23;
		else
		   LEDBUF[0]=temp0;
		if(numCnt<100)
	     LEDBUF[1]=23;
		else
		   LEDBUF[1]=temp1;
		if(numCnt<10)
	     LEDBUF[2]=23;
		else
		   LEDBUF[2]=temp2;
	  LEDBUF[3]=temp3;
}

void main()
{ 
	timer0_Init();
	EX0_Init();
	EX1_Init();
	EA=1;//中断总开关
	while(1)
	{
		display_Service();
	}
}
void EX0_Init()
{
	IT0=1;//触发方式 下降沿
	EX0=1;
	
}
void EX1_Init()
{
	IT1=1;//触发方式 下降沿
	EX1=1;
	
}
void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	//EA=1;
	//3.溢出标志位设为1开启
	TR0=1;
}

void time0_ISR() interrupt 1
{
	TR0=0;
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}
void EX0_ISR() interrupt 0
{
	EX0=0;
	numCnt++;
	if(numCnt>9999)
		numCnt=0;
	EX0=1;
	
}
void EX1_ISR() interrupt 2
{
	EX1=0;
	numCnt--;
	if(numCnt>9999)
		numCnt=0;
	EX1=1;
}

在这里插入图片描述

7.实验题目如下:

在这里插入图片描述

(主要是1s秒的设置)

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit BUZZER=P1^0;
void timer0_Init();
void timer1_Init();
void EX0_Init();
void EX1_Init();
unsigned int numCnt=0;
unsigned char secCnt=0;
unsigned char sec=0;
unsigned int i=0;
unsigned int temp0;
unsigned int temp1;
unsigned int temp2;
unsigned int temp3;
unsigned char LEDBUF[]={0,0,0,0};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
//段码表
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
//延时函数
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
//显示函数
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
//数码管根据数的情况何时亮何时灭
void display_Service()
{
	  temp0=sec/1000;
	  temp1=sec/100%10;
	  temp2=sec/10%10;
	  temp3=sec%10;
	  if(sec<1000)
	     LEDBUF[0]=23;
		else
		   LEDBUF[0]=temp0;
		if(sec<100)
	     LEDBUF[1]=23;
		else
		   LEDBUF[1]=temp1;
		if(sec<10)
	     LEDBUF[2]=23;
		else
		   LEDBUF[2]=temp2;
	  LEDBUF[3]=temp3;
}


void main()
{ 
	BUZZER=0;
	EX0_Init();
	EX1_Init();
	timer0_Init();
	timer1_Init();
	EA=1;//中断总开关
	while(1)
	{
		display_Service();
	}
}
//外部中断0初始化
void EX0_Init()
{
	IT0=1;//触发方式 下降沿
	EX0=1;
	
}
//外部中断0服务函数
void EX0_ISR() interrupt 0
{
		EX0=0;
//		numCnt++;
//		if(numCnt>60)
//			numCnt=0;
	  TR1=1;
		EX0=1;	
}
//外部中断1初始化
void EX1_Init()
{
	IT1=1;//触发方式 下降沿
	EX1=1;
	
}
//外部中断1服务函数
void EX1_ISR() interrupt 2
{
	EX1=0;
	TR1=0;//用中断服务函数实现TR1的开还是关
	EX1=1;
}

void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//TMODE=0x01;直接写这一句也可以
	//2.初值计算为1000ms=1s
	TH0=0xFC;
	TL0=0x18;
	TF0=0;
	ET0=1;
	//EA=1;
	//3.溢出标志位设为1开启,0关闭
	TR0=1;
}

void time0_ISR() interrupt 1
{
	TR0=0;//关闭
	//过1s显示一次
	Display();//展示函数
	TH0=0xFC;//重新赋值
	TL0=0x18;//重新赋值
	TR0=1;//开启
}

void timer1_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0x0F;
	TMOD |=0x10;
	//TMODE=0x10;
	//2.初值计算50ms
	TH1=0x3C;
	TL1=0xB0;
	TF1=0;
	ET1=1;
	//EA=1;不设置总开关在main函数里面打开总开关
	//3.溢出标志位设为0开启
	//TR1=0;//关闭,交给中断开启
	//这里不设TR1交给中断来控制开还是关
}
void time1_ISR() interrupt 3
{
	//TR1=0;
	secCnt++;
	if(secCnt>=50)//这个时间设置表示已经到1s了
	{
	  secCnt=0;
		sec++;//要显示的数字
		if(sec>60)
		{
		  BUZZER=1;
			DelayXms(500);
			BUZZER=0;
			sec=0;
		}	
  }
	TL1=0xB0;//重新计时
	TH1=0x3C;//重新计时
	//TR1=1;
}


在这里插入图片描述

8.简单测量频率

这里采用简单的测量法,取1s进行脉冲个数的显示,(频率=1s的脉冲数量)这里有一个关键是如何显示脉冲数,就是把TH1和TL1加起来,但是由于都是八位寄存器,所以不能直接加,可以TH1256表示腾出了8位给TL1,TH1256+TL1就是整体的脉冲个数(注意简单测量法有一个正负1的误差)

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
void timer0_Init();
void timer1_Init();
unsigned int dataNum;
unsigned int timerCnt;
unsigned char LEDBUF[]={0,0,0,0};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
//段码表
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

//显示函数
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	//2.送位选
	//3.延时1ms<10ms
	//4.消隐
	switch(i)
	{
		case 0:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  i++;
		  break;
			
		case 1:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  i++;
		  break;
			
		case 2:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  i++;
		  break;
			
		case 3:
			GPIO_DIG=0xff;
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  i=0;
		  break;	
		default:break;
	}
}
//数码管根据数的情况何时亮何时灭
void display_Service()
{
	  LEDBUF[0]=dataNum/1000;
		LEDBUF[1]=dataNum/100%10;
		LEDBUF[2]=dataNum/10%10;
		LEDBUF[3]=dataNum%10;
}


void main()
{ 
	timer0_Init();
	timer1_Init();
	EA=1;//中断总开关
	while(1)
	{
		display_Service();
	}
}

void timer0_Init()
{
	//1.首先选择模式,是定时还是计数,计数为1,定时为0,Gate=0,工作方式为1
	TMOD&=0xF0;
	TMOD |=0x01;
	//TMODE=0x01;直接写这一句也可以
	//2.初值计算
	TH0=0xFC;
	TL0=0x18;
	TF0=0;//清除TF0标志
	ET0=1;//定时器0的中断开关
	//EA=1;
	//3.溢出标志位设为1开启,0关闭
	TR0=1;//定时器0开始计时
}

void time0_ISR() interrupt 1
{
	TR0=0;
	timerCnt++;
	if(timerCnt>=1000)//1s时间到
	{
		TR1=0;
		timerCnt=0;
		dataNum=TH1*256+TL1;
		TH1=TL1=0;
		TR1=1;
	}
	Display();
	TH0=0xFC;
	TL0=0x18;
	TR0=1;
}

void timer1_Init()
{

	TMOD&=0x0F;//设置计数器模式 为GATE C/T M1 M0 0 1 0 1
	TMOD |=0x50;
	//2.初值计算
	TH1=0;//设置定时初值
	TL1=0;//设置定时初值
	TF1=0;//清除TF1标志
	ET1=1;//定时器1的中断开关
	//EA=1;
	//3.溢出标志位设为0开启
	TR1=1;//定时器1开始计数
}

在这里插入图片描述

9.定时计数器实现PWM

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

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数

sbit PWM=P1^0;
unsigned char PWM_Cnt;
unsigned char PWM_Duty=0;
void timer0_Init();
void EX0_Init();

void main()
{ 
	timer0_Init();
	EX0_Init();
	EA=1;
	while(1)
	{
		
	}
}

void EX0_Init()
{
	IT0=1;//下降沿触发
	EX0=1;
}

void EX0_ISR() interrupt 0
{
	static unsigned char PWM_KEY;
	PWM_KEY++;
	switch(PWM_KEY)
	{
		case 1:PWM_Duty=25;break;
		case 2:PWM_Duty=50;break;
		case 3:PWM_Duty=75;break;
		case 4:PWM_Duty=80;break;
		case 5:PWM_Duty=100;break;
		case 6:PWM_Duty=0;PWM_KEY=0;break;
		default:break;
	}
}
void timer0_Init()
{
	TMOD=0x01;
	TL0=0x9c;
	TH0=0xff;
	TF0=0;
	ET0=1;
	//EA=1;
	TR0=1;
}

void time0_ISR() interrupt 1
{
	TR0=0;
	PWM_Cnt++;
	if(PWM_Cnt>=100)
	{
		PWM_Cnt=0;
	}
	if(PWM_Cnt<PWM_Duty)
	{
		PWM=1;
	}
	else
	{
		PWM=0;
	}
	TL0=0x9c;
	TH0=0xff;
	TR0=1;
}

在这里插入图片描述

10.实现门铃叮咚(有问题待改进)

#include<reg52.h>
#include<intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit DoorBell=P3^7;
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
unsigned int timerCnt;
unsigned char uc500Hz=0;
unsigned char uc700Hz=0;
unsigned char flag=0;
void timer0_Init();
unsigned char Key_Scan();
void KeyService();
//延时函数
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
		for(j=124;j>0;j--);
}
//主函数
void main()
{ 
	timer0_Init();
	while(1)
	{
		KeyService();
	}
}

//键盘扫描函数
unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}
//键盘服务函数
void KeyService()
{
	switch(Key_Scan())
	{
		case 1:TR0=~TR0;break;
		case 2:break;
		case 3:break;
		case 4:break;
		default:break;
	}
}
//定时中断初始化
void timer0_Init()
{
	TMOD =0x01;
	TL0=0x06;
	TH0=0xff;
	TF0=0;
	ET0=1;
	EA=1;
	//TR0=1;
}
//定时中断服务函数
void time0_ISR() interrupt 1
{
	timerCnt++;
	if(timerCnt>=2000)
	{
		timerCnt=0;
		flag=~flag;
	}
	if(!flag)
	{
		uc700Hz++;
		if(uc700Hz>=3)
		{
			uc700Hz=0;
			DoorBell=~DoorBell;
		}
	}
	if(flag)
	{
		uc500Hz++;
		if(uc500Hz>=4)
		{
			uc500Hz=0;
			DoorBell=~DoorBell;
		}
	}
	TL0=0x06;
	TH0=0xff;
}

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值