设计目标
当count=100,sec++=60 min++=60 hour++ 当hour=24全部为零。利按钮用键盘扫描函数和显示函数调用刷新。K1按第一下开始再按一下暂停 ,按钮K1利用定时器函数的(TR0=0)和(TR0=1)的功能。 K2的功能清零让hour、min、sec、count=0 。调时K3 让hour个位的+1。调分K4让min的个位+1。
LED数码管的结构
在单片机应用系统中, LED 数码管是单片机人机对话的一种重要输出设备,经常用来显示单片机应用系统的工作状态、运算结果等信息。
单个 LED 数码管的外形和外部引脚如图所示。 LED 数码管由8个发光二极管(以下简称段)构成,通过不同的发光段组合可显示数字0~9、字符 A ~ F 、 H 、 L 、 P 、 R 、 U 、 Y 、符号"-"及小数点"."等信息。
LED数码管的字型编号
LED数码管有共阳和共阴。共阳是指将所有发光二极管的阳极接到一起形成公共阳极(COM)。共阴是指将所有发光二极管的阴极接到一起形成公共阴极(COM)。共阳的LED数码管在应用时应将公共极COM接到+5V;共阴的LED数码管在应用时应将公共极COM接到地线GND上。
共阳是当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴是当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。
LED数码管动态显示
动态显示的概念和显示接口
动态扫描显示,即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。具体过程是:当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以只要将需要显示的数码管的位选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。但51单片机的LED数码管的链接有些不同。
所以51单片机的8个位选端为0xFF,0xFB,0xF7,0xF3,0xEF,0xEB,0xE7,0xE3。
时钟代码
代码由延时函数、定时器函数、数码管显示结果函数、按键扫描函数、主函数组成。
主函数
主函数对函数进行调用。
void main(void)
{
Time0_Init();
while(1)
{
Key_Scan();
SEG_Display();
Star_stop();
Cleal();
Adjust();
}
}
子函数1
LED数码管的显示结果的函数。
void SEG_Display()
{
uint i;
Dis_Buf[7]=count%10;
Dis_Buf[6]=count/10;
Dis_Buf[5]=sec%10;
Dis_Buf[4]=sec/10;
Dis_Buf[3]=min%10;
Dis_Buf[2]=min/10;
Dis_Buf[1]=hour%10;
Dis_Buf[0]=hour/10;
for(i=0;i<8;i++)
{
if(i==1||i==3||i==5)//i=0小数点亮
P0=SEG_Code[Dis_Buf[i]]| 0x80;
else
P0=SEG_Code[Dis_Buf[i]];
P2=SEG_Bit[i];
delay_xms(3);
P0=0x00;
}
}
子函数2
利用定时器函数让当count=100,sec++=60 min++=60 hour++ 当hour=24全部为零。
void Time0_Init()
{
TMOD=0x01; //设置P0工作方式:方式0000 0001
TH0 =(65536-50000)/256; //给T0赋初值,技术长度是8;2^8=256
TL0 =(65536-50000)%256;
EA =1; //开启总中断
ET0 =1; //开启T0中断
TR0 =1; //启动T0定时器
}
void Timer0_ISR() interrupt 1
{
TH0 =(65536-50000)/256; //重新给T0赋初值
TL0 =(65536-50000)%256;
count++;
if(count==100)
{
count=0;
sec++;
if(sec==60)
{
sec=0;
min++;
}
if(min==60)
{
min=0;
hour++;
}
if(hour==24)
{
hour=0;
}
}
}
子函数3
按键扫描函数
void Key_Scan() //声明按键扫描函数
{
if(K1==0)
{
delay_xms(10);
if(K1==0)
{
KeyFlag=1;//识别按下
}
}
else
{
KeyFlag=0;
}
}
子函数4
K1按第一下开始再按一下暂停 ,按钮K1利用定时器函数的(TR0=0)和(TR0=1)的功能。
void Star_stop()
{
if(K1==0)
{
delay_xms(10);
while(K1==0)
{
a++;
if(a>=2) a=0;
while(K1==0);
switch(a)
{
case (0) : TR0=1;break;
case (1) : TR0=0;break;
}
}
}
}
子函数5
按K2清零
void Cleal()
{
if(Key_Cleal == 0)
{
delay_xms(10);
while(Key_Cleal == 0);
hour=0;min=0;sec=0;count = 0;
}
}
子函数6
调时K3 让hour个位的+1。调分K4让min的个位+1。
void Adjust()
{
if(K3==0)
{
delay_xms(10);
hour++;
while(K3==0)
if(hour>=24)
hour=0;
}
if(K4==0)
{
delay_xms(10);
while(K4==0)
min++;
if(min>=60)
min=0;
}
}
子函数7
延时函数
void delay_xms(uint xms)
{
uint i;
while(xms--)
{
for(i=0;i<234;i++);
}
}
源代码
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar SEG_Code[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x80};
uchar SEG_Bit[8]={0xFF,0xFB,0xF7,0xF3,0xEF,0xEB,0xE7,0xE3};
uchar Dis_Buf[]={0,0,0,0,0,0,0,0};
uchar KeyFlag,a;//声明按键的标志位,为1时按下,为0时没按下
sbit K1=P3^1;sbit Key_Cleal = P3^0;sbit K3=P3^2;sbit K4=P3^3;
uint hour; min; sec; count=10;// count=0.01s=10ms
//当count=100,sec++——60 min++——60 hour++ 当hour=24全部为零
//(n=1)开始和(n=2)暂停利用键盘扫描函数 (if) K1当等于0(TR0=0)和1(TR0=1)的功能
//清零 K2 hour.min.sac.count=0
//调时 K3 个位的hour+1 显示函数调用刷新
// 分 K4 min
void Key_Scan();
void Star_stop();
void Cleal();
void Adjust();
void SEG_Display();
void delay_xms(uint xms);
void Time0_Init();
void main(void)
{
Time0_Init();
while(1)
{
Key_Scan();
SEG_Display();
Star_stop();
Cleal();
Adjust();
}
}
void Time0_Init()
{
TMOD=0x01; //设置P0工作方式:方式0000 0001
TH0 =(65536-50000)/256; //给T0赋初值,技术长度是8;2^8=256
TL0 =(65536-50000)%256;
EA =1; //开启总中断
ET0 =1; //开启T0中断
TR0 =1; //启动T0定时器
}
void Timer0_ISR() interrupt 1
{
TH0 =(65536-50000)/256; //重新给T0赋初值
TL0 =(65536-50000)%256;
count++;
if(count==100)
{
count=0;
sec++;
if(sec==60)
{
sec=0;
min++;
}
if(min==60)
{
min=0;
hour++;
}
if(hour==24)
{
hour=0;
}
}
}
void Key_Scan() //声明按键扫描函数
{
if(K1==0)
{
delay_xms(10);
if(K1==0)
{
KeyFlag=1;//识别按下
}
}
else
{
KeyFlag=0;
}
}
void Star_stop()
{
if(K1==0)
{
delay_xms(10);
while(K1==0)
{
a++;
if(a>=2) a=0;
while(K1==0);
switch(a)
{
case (0) : TR0=1;break;
case (1) : TR0=0;break;
}
}
}
}
void Cleal()
{
if(Key_Cleal == 0)
{
delay_xms(10);
while(Key_Cleal == 0);
hour=0;min=0;sec=0;count = 0;
}
}
void Adjust()
{
if(K3==0)
{
delay_xms(10);
hour++;
while(K3==0)
if(hour>=24)
hour=0;
}
if(K4==0)
{
delay_xms(10);
while(K4==0)
min++;
if(min>=60)
min=0;
}
}
void SEG_Display()
{
uint i;
Dis_Buf[7]=count%10;
Dis_Buf[6]=count/10;
Dis_Buf[5]=sec%10;
Dis_Buf[4]=sec/10;
Dis_Buf[3]=min%10;
Dis_Buf[2]=min/10;
Dis_Buf[1]=hour%10;
Dis_Buf[0]=hour/10;
for(i=0;i<8;i++)
{
if(i==1||i==3||i==5)//i=0小数点亮
P0=SEG_Code[Dis_Buf[i]]| 0x80;
else
P0=SEG_Code[Dis_Buf[i]];
P2=SEG_Bit[i];
delay_xms(3);
P0=0x00;
}
}
void delay_xms(uint xms)
{
uint i;
while(xms--)
{
for(i=0;i<234;i++);
}
}