51单片机数码管显示时钟

设计目标

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

  • 32
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
这里提供一份51单片机数码管显示小数的代码,仅供参考: ``` #include <reg51.h> // 数码管位选控制器 sbit LED_COM1 = P2^4; sbit LED_COM2 = P2^5; sbit LED_COM3 = P2^6; sbit LED_COM4 = P2^7; // 数码管段选控制器 sbit LED_A = P0^0; sbit LED_B = P0^1; sbit LED_C = P0^2; sbit LED_D = P0^3; sbit LED_E = P0^4; sbit LED_F = P0^5; sbit LED_G = P0^6; sbit LED_DP = P0^7; // 数码管显示的数值和小数点位置 unsigned char num = 123; // 设置显示的数值 unsigned char point = 2; // 设置小数点位置,例如显示1.23,则point=2 // 数码管显示函数 void LED_Display(unsigned char num, unsigned char point) { unsigned char temp = 0; // 临时变量,用于存储需要显示的数码管数值 // 将需要显示的数值转换为数码管对应的值 switch(num) { case 0: temp = 0xFC; break; case 1: temp = 0x60; break; case 2: temp = 0xDA; break; case 3: temp = 0xF2; break; case 4: temp = 0x66; break; case 5: temp = 0xB6; break; case 6: temp = 0xBE; break; case 7: temp = 0xE0; break; case 8: temp = 0xFE; break; case 9: temp = 0xF6; break; default: temp = 0x00; break; } // 判断小数点位置,为0则不显示,为1则显示第一位小数点,为2则显示第二位小数点 if(point == 1) { temp &= ~(1 << 7); // 将第一位小数点位置0,即显示小数点 } else if(point == 2) { temp &= ~(1 << 3); // 将第二位小数点位置0,即显示小数点 } // 数码管位选控制 LED_COM1 = 1; LED_COM2 = 1; LED_COM3 = 1; LED_COM4 = 1; // 数码管段选控制 P0 = temp; // 先将需要显示的数值输出到P0口 LED_DP = 1; // 先将小数点位置1,防止误显示 switch(point) // 根据小数点位置控制小数点显示 { case 1: LED_DP = 0; LED_COM1 = 0; break; case 2: LED_DP = 0; LED_COM2 = 0; break; case 3: LED_DP = 0; LED_COM3 = 0; break; case 4: LED_DP = 0; LED_COM4 = 0; break; default: LED_DP = 1; break; } } // 主函数 void main() { while(1) { // 显示数值和小数点位置 LED_Display(num, point); } } ``` 这是一个基础的数码管显示程序,根据需要可以进行修改。其中,LED_Display函数用于控制数码管的位选和段选,将需要显示的数值和小数点位置转换为对应的数码管值,并输出到P0口控制数码管段选。程序中使用了switch语句来实现数值的转换和小数点位置的控制,也可以使用其他方法来实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HWQ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值