51单片机数码管显示时钟

本文详细描述了一种基于51单片机的时间计时器设计,使用定时器功能配合LED数码管实现动态显示小时、分钟和秒数,同时涉及按键控制暂停、清零和调整时间的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

设计目标

LED数码管的结构

LED数码管的字型编号

LED数码管动态显示

动态显示的概念和显示接口

时钟代码

源代码


设计目标

  当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++);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HWQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值