蓝桥杯单片机开发板-定时器中断实现数码管0-99+摇摆灯(详解)

本博文程序实现的功能是蓝桥杯51单片机通过定时器功能来实现数码管的计数与8个LED小灯的交替闪烁。
首先是程序初始化函数:

void init(void)
{
	Timer0Init();//初始化定时器
	HC138(4);P0=0Xff;
	HC138(5);P0=0X00;
	HC138(6);P0=0Xff;
	HC138(7);P0=0Xff;	
}

上一段程序中涉及到的通过74HC138来进行74HC573片选的函数如下所示:

void HC138(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;
	}
}

定时器定时1毫秒的初始化函数如下所示:

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

每当定时1毫秒时,系统的程序运行就会进入到中断服务子程序中,中断服务子程序如下所示:

//中断函数,每次定时器溢出进入中断,执行中断函数
void time0() interrupt 1
{
//5ms一次,200就为1s
	t++;
	if(t == 200)
	{
		t=0;
		time++;
		value=~value;
		HC138(4);
		P0=~value;		
	}
}

每进入一次中断服务子程序,中断次数计数变量t就加一,当加到200时,就意味着1秒钟的定时时间已到。然后此时秒数时间加1,通过P0口控制摇摆灯的闪烁。
系统的主程序如下:

void main(void)
{
	init();//初始化开发板
	while(1)
	{
	//每次循环数码管进行显示,time值在定时器中断减减
		SMG[0]=time/10;
		SMG[1]=time%10;
		SMG_output();
	}
}

单片机上电后首先进行系统的初始化,然后进入while()循环中,将time/10得到的数字设定为中间变量数组的首个数据值,将time%10得到的数字设定为中间变量数组的第二个数据值。比如此时time 的数值是18,即已经过了18秒,那么SMG[0],的数值为8,SMG[1]的数值为1;
紧接着我们看一下SMG_output();函数的具体介绍:

//数码管显示函数
void SMG_output(void)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		//数码管位选,从左向右依次进行位选
		HC138(6);P0=(0x01<<i);
		//数码管段选,当从第三个数码管开始时
		//tab[10]没有对应的段选值,则不显示对应的值,即数码管熄灭
		HC138(7);P0=tab[SMG[i]];
		//延时1毫秒,100赫兹无闪烁
		Delay1ms();
	}
	HC138(6);P0=0Xff;
	HC138(7);P0=0Xff;	
}

根据C语言数组的有关知识,我们可以知道tab[SMG[0]]的含义与tab[8]的含义相同,此时即代表将tab[]数组中的第9个数据传递给P0口,根据共阳数码管的断码值表我们可以看到tab[]的第九个数据代表的数字是8,那么tab[SMG[1]]的含义也可以理解啦~
本博文的全部程序如下所示:

#include "reg52.h"
#include "intrins.h"


#define uchar unsigned char
#define uint unsigned int
	

void SMG_output(void);
void init(void);
void Delay1ms(void);
void Timer0Init(void);
void HC138(unsigned char channel);

//tab[]的含义是定义蓝桥杯单片机开发板共阳极数码管的断码值
unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
//SMG[8]的含义是给数码管显示值一个储存的中间变量,设置为10可以熄灭对应的数码管
//从左向右依次对应开发板上从左向右焊接的数码管
unsigned char SMG[8]={10,10,10,10,10,10,10,10};
//定义显示的时间初始数值
unsigned char time=0;
unsigned char value=0x55;
uint t=0;
sfr AUXR=0X8E; //NOTES:sbit是位操作,用于将某个sfr中具体位赋值给一个变量

void main(void)
{
	init();//初始化开发板
	while(1)
	{
	//每次循环数码管进行显示,time值在定时器中断减减
		SMG[0]=time/10;
		SMG[1]=time%10;
		SMG_output();
	}
}
//中断函数,每次定时器溢出进入中断,执行中断函数
void time0() interrupt 1
{
//5ms一次,200就为1s
	t++;
	if(t == 200)
	{
		t=0;
		time++;
		value=~value;
		HC138(4);
		P0=~value;		
	}
}

//数码管显示函数
void SMG_output(void)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		//数码管位选,从左向右依次进行位选
		HC138(6);P0=(0x01<<i);
		//数码管段选,当从第三个数码管开始时
		//tab[10]没有对应的段选值,则不显示对应的值,即数码管熄灭
		HC138(7);P0=tab[SMG[i]];
		//延时1毫秒,100赫兹无闪烁
		Delay1ms();
	}
	HC138(6);P0=0Xff;
	HC138(7);P0=0Xff;	
}
//定时器初始化函数
void Timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA=1;//打开总中断,打开定时器0中断
	ET0=1;
}
//开发板初始化函数,关闭LED,蜂鸣器,继电器和数码管
void init(void)
{
	Timer0Init();//初始化定时器
	HC138(4);P0=0Xff;
	HC138(5);P0=0X00;
	HC138(6);P0=0Xff;
	HC138(7);P0=0Xff;	
}

void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}


void HC138(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;
	}
}

你可能感兴趣的:(单片机,蓝桥杯,单片机,蓝桥杯,嵌入式硬件)