本博文程序实现的功能是蓝桥杯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;
}
}