# 单片机数码管显示时间

## 利用单片机的数码管模拟时钟的显示时间

2016-09-16 20:49:55 baidu_35534327 阅读数 6804
• ###### 静态和动态控制数码管-第1季第7部分

本课程是《朱有鹏老师单片机完全学习系列课程》第1季第7个课程，全面讲解了静态数码管、无38译码器式动态数码管、有38译码器式动态数码管等各种数码管驱动方式，学完本课程将会对数码管的驱动方式彻底熟悉和掌握。

9课时 210分钟 3017人学习 朱有鹏
免费试看

```#include <reg52.h>

#define SEGPORT P0
sbit seg_select = P2^1;
sbit bit_select = P2^0;

unsigned char duanma[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char weima[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char TempData[8];

unsigned char shi = 20, fen = 54, miao = 55;

void display()
{
static unsigned char i = 0;
SEGPORT = 0x0;
seg_select = 1;
seg_select = 0;

SEGPORT = 0xff;
bit_select = 1;
bit_select = 0;

SEGPORT = TempData[i];
seg_select = 1;
seg_select = 0;

SEGPORT = weima[i];
bit_select = 1;
bit_select = 0;

i++;

if(8 == i)
{
i = 0;
}
}

void time0_init(void)
{
EA = 1;                              //打开总中断
TMOD |= 0x01;                        //设置定时器工作方式
TH0 = (65536 - 20000) / 256;
TL0 = (65536 - 20000) % 256;        //设置定时器初值
ET0 = 1;                           //打开定时器中断
TR0 = 1;

}

void timer0_isr() interrupt 1
{
static unsigned char i = 0;
TH0 = (65536 - 20000) / 256;
TL0 = (65536 - 20000) % 256;    //设置定时器初值，
i++;

if(50 == i)
{
i = 0;
miao++;
if(60 == miao)
{

miao = 0;
fen++;

if(60 == fen)
{
fen = 0;
shi++;

if(24 == shi)
{
shi = 0;

}
}
}
}

TempData[0] = duanma[shi / 10];
TempData[1] = duanma[shi % 10];
TempData[2] = 0x40;
TempData[3] = duanma[fen / 10];
TempData[4] = duanma[fen % 10];
TempData[5] = 0x40;
TempData[6] = duanma[miao / 10];
TempData[7] = duanma[miao % 10];
}

void time1_init(void)
{
EA = 1;
TMOD |= 0x10;
TH1 = (65536 - 20000) / 256;
TL1 = (65536 - 20000) % 256;
ET1 = 1;
TR1 = 1;

}

void time1_isr() interrupt 3
{
TH1 = (65536 - 1000) / 256;
TL1 = (65536 - 1000) % 256;
display();

}

void main()
{
time0_init();
time1_init();
while(1)
{

}

}
```

## 51单片机数码管详解

2015-11-18 11:15:51 u013151320 阅读数 6432
• ###### 静态和动态控制数码管-第1季第7部分

本课程是《朱有鹏老师单片机完全学习系列课程》第1季第7个课程，全面讲解了静态数码管、无38译码器式动态数码管、有38译码器式动态数码管等各种数码管驱动方式，学完本课程将会对数码管的驱动方式彻底熟悉和掌握。

9课时 210分钟 3017人学习 朱有鹏
免费试看

## 一.数码管基础知识

LED数码管是由多个发光二极管封装在一起组成“8”字型的器件，引线已在内部连接完成，只需引出它们的各个笔划，公共电极。LED数码管常用的段数一般为7段，有的另加一个小数点 。LED数码管根据LED的接法不同，分为共阳和共阴两类 。
1.共阳极数码管

2.共阴极数码管

## 二.静态数码管（以共阳极为例）

1.原理分析
LED 发光二极管的正极共同接在VCC上，这里以单片机P1口为例，当P1口对应引脚为0（即低电平）时数码管的该段发光二极管亮。

2.共阳极数码管段选编码

3.例程

``````#include <reg51.h>
unsigned char code num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void delay_ms(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{
unsigned int i;
while(1)
{
for(i=0;i<16;i++)
{
P0=num[i];
delay_ms(300);
P0=0xff;
delay_ms(100);
}
}
}``````

## 三.动态数码管（以共阴极为例）

1.原理分析

2.数码管动态扫描的一般步骤
(1).给对应的IO口赋位选编码选择让哪一位亮。
(2).给选中的数码管赋段选编码，使其显示对应的数字或字母。
(3).适当延时使其显示稳定（特别注意延时不宜过长）
(4).消隐，即消除上一次IO输出段码对本次段码的影响。

3.共阴极数码管编码
(1).位选编码

(2).段选编码

*位选和段选的编码还与电路设计有关，具体情况请根据电路图接线具体分析

4 .例程

``````#include<reg51.h>
unsigned char code wei[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选控制   查表的方法控制
unsigned char code duan[17] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码

void delay_ms(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}

void main(void)
{
unsigned char i;
for(i=0;i<8;i++)
{
P0=wei[i];    //位选，选择让哪一位亮
P1=duan[i];   //段选，让数码管显示什么
delay_ms(2);  //延时使显示充分
P1=0x00;         //消隐
}
}``````

## 基于51单片机的电子时钟（数码管显示）

2018-05-20 08:30:59 qq_40598185 阅读数 49616
• ###### 静态和动态控制数码管-第1季第7部分

本课程是《朱有鹏老师单片机完全学习系列课程》第1季第7个课程，全面讲解了静态数码管、无38译码器式动态数码管、有38译码器式动态数码管等各种数码管驱动方式，学完本课程将会对数码管的驱动方式彻底熟悉和掌握。

9课时 210分钟 3017人学习 朱有鹏
免费试看

此次对于数码管进行一个简单的应用，同时可以设计一个电子小时钟，增加趣味性。

从图中，我们可以看到，第一个74HC573是来控制8个数码管的位选的，就是说我要选种哪个数码管，这里的WE是低电平有效，比如说我想选中最后一个数码管，那么这里我就要将0x7f送到相应的I/O口。第二个74HC573是来控制数码管显示什么的这里0~9的16进制码如下：

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f；

wirte_address(unsigned char);

write_date(unsigned int);

write_address(0x7f);

write_date(0x7f);

然后我们就要多个位置显示，这里我们硬件的P0口接的是数码管，同时我们要引进相应的延时函数delay（unsigned int）;

当我们能显示时，就需要了解定时器，让它来计时，然后将数值取出，进行显示。这里我们的晶振是12MHz，所以一个机械周期时1/12MHz=1us,为了使计时较为精确，我们这里选择定时器0的模式2,8位重装定时器，并且我们100us进入一次中断，定时器的初始化就该如下：

TMOD=0x02;

TH0=256-100;

TL0=256-100;

EA=1;

ET0=1;

TR0=1;

这样我们再定义一个n用来计数进入中断的次数，当n的10000时，就表示1s到了，所以我们需要对相应的变量进行处理。

那么我们需要对数据进行处理，比如，所得的秒的值，其十位=秒/10，其个位就等于秒%10，其它以此类推。

```#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};	 //数码管位选数据
sbit dula=P2^6;//段选信号,写数码管数据
sbit wela=P2^7;//位选信号,选择数码管

uint miao=0;		//秒
uint fen=0;			//分
uint shi=0;		    //时
uint n=0;			//计数
uint date[6]={0,0,0,0,0,0};	  //定义一个有6个地址的数组，分别存时，分，秒的个位和十位。
void delay(uint z)			 //延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=50;y>0;y--);
}

void write_address(uchar address)		 //写地址函数，选择数码管
{
wela=1;
P0=address;
wela=0;
}

void write_date(uint n)				     //写数据函数，送入段选信号
{
dula=1;
P0=table[n];
dula=0;
}										//显示函数
void display()
{
write_date(date[0]);
P0=0xff;
write_address(0x7f);
delay(1);

write_date(date[1]);
P0=0xff;
write_address(0xbf);
delay(1);

write_date(date[2]);
P0=0xff;
write_address(0xef);
delay(1);

write_date(date[3]);
P0=0xff;
write_address(0xf7);
delay(1);

write_date(date[4]);
P0=0xff;
write_address(0xfd);
delay(1);

write_date(date[5]);
P0=0xff;
write_address(0xfe);
delay(1);

}
void time_init()						   //定时器初始化函数
{
TMOD=0x02;							  //选择方式2
TH0=156;							  //重装初值为156
TL0=156;							  //运行值为156
EA=1;								  //开总中断
ET0=1;								  //开定时器0中断
TR0=1;								  //开定时器0
}

void main()
{
dula=0;								   //先关闭位选，段选信号。
wela=0;
time_init();
while(1)
{
display();
}

}

void timer() interrupt 1					  //定时器0中断
{
n++;
if(n==10000)								 //当n=10000时，表示1s到了
{
n=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
}
}
date[0]=miao%10;
date[1]=miao/10;
date[2]=fen%10;
date[3]=fen/10;
date[4]=shi%10;
date[5]=shi/10;

}

}```

## 单片机数码管时钟显示

2013-09-07 22:56:02 qqzwp 阅读数 1116
• ###### 静态和动态控制数码管-第1季第7部分

本课程是《朱有鹏老师单片机完全学习系列课程》第1季第7个课程，全面讲解了静态数码管、无38译码器式动态数码管、有38译码器式动态数码管等各种数码管驱动方式，学完本课程将会对数码管的驱动方式彻底熟悉和掌握。

9课时 210分钟 3017人学习 朱有鹏
免费试看

```/*--------------------------------------------------------------------------------------------------
* Project: IIC.c
* Name: zwp
* Date: 2013.8
*--------------------------------------------------------------------------------------------------*/

#include <reg52.h>

bit write = 0;				// Ð´24C02µÄ±êÖ¾
sbit sda = P2^0;
sbit scl = P2^1;
sbit dula = P2^6;			// U1Ëø´æÆ÷¶ÎÊý¾Ý
sbit wela = P2^7;			// U2Ëø´æÆ÷Î»Êý¾Ý

unsigned char sec, min, hou, tcnt;

unsigned char code Table[] =
{
0X3F, 0X06, 0X5B, 0X4F,
0X66, 0X6D, 0X7D, 0X07,
0X7F, 0X6F, 0X77, 0X7C,
0X39, 0X5E, 0X79, 0X71
};

/*
** Î¢Ãë¼¶ÑÓÊ±
*/
void Delay(void)
{
;;
}

/*
** ÑÓÊ±1ºÁÃë
*/
void Delay1ms(unsigned int xms)
{
unsigned int index, indeu;

for(index = xms; index > 0; -- index)
for(indeu = 110; indeu > 0; -- indeu);

}

/*
** ³õÊ¼»¯º¯Êý
*/
void Initialize(unsigned char s, unsigned char f, unsigned char m)
{
sda = 1;
Delay();
scl = 1;
Delay();

/* µ÷ÕûÊ±¼ä */

hou = s;
min = f;
sec = m;

}

/*
** ÐÅºÅ¿ªÊ¼
*/
void Start(void)
{
sda = 1;
Delay();
scl = 1;			// scl ¸ßµçÆ½ÆÚ¼ä
Delay();
sda = 0;			// sda Ò»¸öÏÂ½µÑØÆô¶¯ÐÅºÅ
Delay();
}

/*
** Í£Ö¹ÐÅºÅ
*/
void Stop(void)
{
sda = 0;
Delay();
scl = 1;				// SCL ¸ßµçÆ½ÆÚ¼ä
Delay();
sda = 1;				// sda Ò»¸öÉÏÉýÑØÍ£Ö¹ÐÅºÅ
Delay();
}

/*
** Ó¦´ðÐÅºÅ
*/
void Response(void)
{
unsigned char index = 0;

scl = 1;				// SCL Îª¸ßµçÆ½ÆÚ¼ä
Delay();
while((sda == 1)&&(index < 255)) // sda ±»´ÓÉè±¸À­ÎªµÍµçÆ½±íÊ¾Ó¦´ð
index++;

scl = 0;				// »Ö¸´µÍµçÆ½×´Ì¬
Delay();
}

/*
** Ð´×Ö½Ú
*/
void Write_byte(unsigned char xms)
{
unsigned char index, temp;

temp = xms;
for(index = 0; index < xms; ++ index)
{
temp <<= 1; 		// Ñ­»·ÒÆÎ»
scl   = 0;
Delay();
sda = CY;			// ×î¸ßÎ»½«ÒÆÈëPSWµÄCY¼Ä´æÆ÷ÖÐ£¬È»ºó½«CY¸³Öµ¸øSDA
Delay();			// ½ø¶øÔÚsclµÄ¿ØÖÆÏÂ·¢ËÍ³öÈ¥
scl = 1;
Delay();
}

scl = 0;
Delay();
sda = 1;
Delay();
}

/*
** ¶ÁÒ»¸ö×Ö½Ú
*/
unsigned char Read_byte(void)
{
unsigned char index, kent;

scl = 0;
Delay();
sda = 1;

for(index = 0; index < 8; index ++)
{
scl = 1;
Delay();
kent = (kent<<1)|sda;	// ÒÀ´Î°Ñ8¸ö¶ÀÁ¢µÄÎ»·ÅÈëÒ»¸ö×Ö½ÚÖÐÀ´Íê³É½ÓÊÕ
scl = 0;
Delay();
}
Delay();

return kent;
}

/*
** Ö¸¶¨µØÖ·Ð´Êý¾Ý
*/
void Write_add(unsigned char address, unsigned char adata)
{
Start();				// ÐÅºÅ¿ªÊ¼

Write_byte(0XA0);
Response();			// Ó¦´ð

Write_byte(address);   // Ð´µØÖ·
Response();			// Ó¦´ð
Write_byte(adata);		// Ð´Êý¾Ý
Response();

Stop();
}

/*
** Ö¸¶¨µØÖ·¶ÁÊý¾Ý
*/
unsigned char Read_add(unsigned char address)
{
unsigned char adata;

Start();				// ÐÅºÅ¿ªÊ¼

Write_byte(0XA0);
Response();			// Ó¦´ð

Write_byte(address);	// Ð´µØÖ·
Response();

Start();				// ÐÅºÅ¿ªÊ¼
Write_byte(0XA1);

Response();
adata = Read_byte();	// ¶ÁÊý¾Ý

Stop();				// Í£Ö¹ÐÅºÅ

return adata;
}

/*
** ÔÚÊýÂë¹ÜÉÏÏÔÊ¾Êý¾Ý Ê±ÏÔÊ¾
*/
void Display_hou(unsigned char bai, unsigned char shi)
{
dula = 0;
P0	  = Table[bai];		// ·¢ËÍ¶ÎÑ¡Êý¾Ý ÏÔÊ¾µÄÊý×Ö
dula = 1;
dula = 0;

wela = 0;
P0 = 0X7E;				// ·¢ËÍÎ»Ñ¡Êý¾Ý ÏÔÊ¾ÊýÂë¹ÜÎ»ÖÃ
wela = 1;
wela = 0;

Delay1ms(2);

dula = 0;
P0   = Table[shi];
dula = 1;
dula = 0;

wela = 0;
P0  = 0X7D;
wela = 1;
wela = 0;

Delay1ms(2);

}

/*
** ÔÚÊýÂë¹ÜÉÏÏÔÊ¾Êý¾Ý ·ÖÏÔÊ¾
*/

void Display_min(unsigned char bai, unsigned char shi)
{
dula = 0;
P0	  = Table[bai];		// ·¢ËÍ¶ÎÑ¡Êý¾Ý ÏÔÊ¾µÄÊý×Ö
dula = 1;
dula = 0;

wela = 0;
P0 = 0XFB;				// ·¢ËÍÎ»Ñ¡Êý¾Ý ÏÔÊ¾ÊýÂë¹ÜÎ»ÖÃ
wela = 1;
wela = 0;

Delay1ms(2);

dula = 0;
P0   = Table[shi];
dula = 1;
dula = 0;

wela = 0;
P0  = 0XF7;
wela = 1;
wela = 0;

Delay1ms(2);

}

/*
** ÔÚÊýÂë¹ÜÉÏÏÔÊ¾Êý¾Ý ÃëÏÔÊ¾
*/
void Display_sec(unsigned char bai, unsigned char shi)
{

dula = 0;
P0  = Table[bai];		// ·¢ËÍ¶ÎÊý¾Ý ÏÔÊ¾µÄÊý×Ö
dula = 1;
dula = 0;

wela = 0;
P0   = 0xEF;			// Î»Ñ¡Êý¾Ý ÊýÂë¹ÜÎ»ÖÃ
wela = 1;
wela = 0;

Delay1ms(2);

dula = 0;
P0  = Table[shi];		// ÏÔÊ¾¶ËÊý¾Ý
dula = 1;
dula = 0;

wela = 0;
P0 = 0XDF;				// ÏÔÊ¾Î»Ñ¡Êý¾Ý
wela = 1;
wela = 0;

Delay1ms(2);

}

/*
** Ö÷º¯Êý
*/
void main(void)
{
Initialize(20, 11, 59);			// ³õÊ¼»¯

sec = Read_add(2);
if(sec > 100)			// ·ÀÖ¹Ê×´Î¶Á³ö´íÎóÊý¾Ý
sec = 0;

TMOD = 0X01;			// ¶¨Ê±Æ÷¹¤×÷ÔÚ·½Ê½0
ET0  = 1;				// ¿ª¶¨Ê±Æ÷0ÖÐ¶Ï
EA   = 1;				// ¿ª×ÜÖÐ¶Ï

TH0 = (65536 - 50000) / 256;	// ÖÐ¶Ï¼ä¸ôÎ»0.05Ãë
TL0 = (65536 - 50000) % 256;
TR0 = 1;				// ¿ª¶¨Ê±Æ÷0

while(1)
{
Display_sec(sec / 10, sec % 10);

Display_min(min / 10, min % 10);

Display_hou(hou / 10, hou % 10);

if(write == 1)		// ¼ÆÊ±Æ÷ÒÑ¾­¼ÆÊ±1Ãë
{
write = 0;
Write_add(2, sec);	// ÔÚ24c02µÄµØÖ·2ÖÐÐ´ÈëÊý¾Ýsec
}
}
}

/*
** ÖÐ¶Ï0´¦Àí³ÌÐò
*/
void Timer() interrupt 1
{
TH0 = (65536 - 50000) / 256;	// ÖÐ¶Ï¼ä¸ôÎ»0.05Ãë
TL0 = (65536 - 50000) % 256;

tcnt++;		// Ã¿¹ý50msµÝÔö

if(tcnt == 20) // Ê±¼äÎª1Ãë
{
tcnt = 0;
sec++;
write = 1;				//1ÃëÐ´Ò»´Î24C02

if(sec == 60)	 // ¶¨Ê±60ÃëÔÙ´ÓÁã¿ªÊ¼¼ÆÊ±
{
sec = 0;
min++;		  // Ôö¼Ó1·ÖÖÓ

if(min == 60) 	// ¶¨Ê±µ½60·ÖÖÓÊ±ÔÙ´ÓÁã¿ªÊ¼¼ÆÊ±
{
min = 0;
hou++;		// Ôö¼ÓÒ»¸öÐ¡Ê±

if(hou == 24) // ¶¨Ê±µ½24Ð¡Ê±Ê±ÔÙ´ÓÁã¿ªÊ¼¼ÆÊ±
hou = 0;
}

}
}
}

```

## C51单片机数码管动态显示

2018-08-27 21:49:25 zlllg 阅读数 11380
• ###### 静态和动态控制数码管-第1季第7部分

本课程是《朱有鹏老师单片机完全学习系列课程》第1季第7个课程，全面讲解了静态数码管、无38译码器式动态数码管、有38译码器式动态数码管等各种数码管驱动方式，学完本课程将会对数码管的驱动方式彻底熟悉和掌握。

9课时 210分钟 3017人学习 朱有鹏
免费试看

C51单片机由于运行速度很慢，在高刷新频率下，单片机的资源耗费很厉害，这样单片机就不可以再进行大量的计算工作，实际上，单片机在刷新时，只需要周期性的改变GPIO口的状态就可以了，剩下的时间其实都是在空转的状态下，我们能不能将这个空转的状态拿来用呢？当然是可以的啦，这里，我们利用单片机的定时器周期地产能中断，在中断内进行数码管的刷新工作，就可以将等待中断的这个CPU时间拿来做别的事情了。

``````#include "shumaguan.h"
#include "timer.h"

sbit sw_jdq=P1^0;//定义一位继电器操作
void main(void)
{
int cnt=0;//设定初值
timer_init();//初始化定时器
while(1)
{
value_now = cnt;//送初值到显示缓存
delay(50);
cnt++;
sw_jdq=~sw_jdq;//切换继电器状态
if(cnt>9999)//数值超出界线，回归最小
cnt=-999;
}
}``````

``````#include "shumaguan.h"

#define DType	1			//define the Digital LED type, 1: VCC in common, 0: GND in common
#if DType==1
/*--------------------------------------------------------
Set the digital LED display code
From left to right for
0,1,2,3,4,5,6,7,8,9,a.b,c,d,e,f,dp,-，
--------------------------------------------------------*/
uchar code DS_BUF[]={0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90 , 0x88 ,
0x83 , 0xc6 , 0xa1 , 0x86 , 0x8e , 0x7f , 0xbf , 0xff };
#else
uchar code DS_BUF[]={0x3f , 0x06 , 0x5b , 0x4f , 0x66 , 0x6b , 0x7d , 0x07 , 0x7f , 0x6f , 0x77 ,
0x7c , 0x39 , 0x5e , 0x79 , 0x71 , 0x80 , 0x40 , 0x00 };
#endif
uchar xdata buf_sm[4];            //set display buffer

uchar frash_cnt=0;//刷新计数器
uchar wei_buf=0x10;//位输出计数器

/*--------------------------
Compute the number from Value
value: something to display, range from -999 to 9999, suport float
--------------------------*/
void calc_sm(float value)
{
uint tmp=0;
if(value>=0)//输入值为正数，不显示负号
{
if(value>9999)//输入值大于9999，显示----
{
buf_sm[0]=17;
buf_sm[1]=17;
buf_sm[2]=17;
buf_sm[3]=17;
}
else if(value>=1000)//输入值大于999，只显示整数
{
tmp=value;
buf_sm[0]=tmp/1000;
buf_sm[1]=tmp%1000/100;
buf_sm[2]=tmp%100/10;
buf_sm[3]=tmp%10;
}
else if(value>=100)//显示一位小数
{
tmp=value*10;
buf_sm[0]=tmp/1000;
buf_sm[1]=tmp%1000/100;
buf_sm[2]=(tmp%100/10)+20;
buf_sm[3]=tmp%10;
}
else if(value>=10)//显示两位小数
{
tmp=value*100;
buf_sm[0]=tmp/1000;
buf_sm[1]=(tmp%1000/100)+20;
buf_sm[2]=tmp%100/10;
buf_sm[3]=tmp%10;
}
else//显示三位小数
{
tmp=value*1000;
buf_sm[0]=(tmp/1000)+20;
buf_sm[1]=tmp%1000/100;
buf_sm[2]=tmp%100/10;
buf_sm[3]=tmp%10;
}
}
else//输入值小于0，显示负号，其余同上
{
if((value<0)&&(value>-10))
{
tmp=value*100;
tmp=abs(tmp);
buf_sm[0]=17;
buf_sm[1]=(tmp/100)+20;
buf_sm[2]=tmp%100/10;
buf_sm[3]=tmp%10;
}
else if((value<=-10)&&(value>-100))
{
tmp=value*10;
tmp=abs(tmp);
buf_sm[0]=17;
buf_sm[1]=(tmp/100);
buf_sm[2]=tmp%100/10+20;
buf_sm[3]=tmp%10;
}
else if((value<=-100)&&(value>-1000))
{
tmp=value;
tmp=abs(tmp);
buf_sm[0]=17;
buf_sm[1]=(tmp/100);
buf_sm[2]=tmp%100/10;
buf_sm[3]=tmp%10;
}

}

}
/*

*/
void display()
{
if(frash_cnt<=3)
{
wei |=0xf0;//数码管的消隐

if(buf_sm[3-frash_cnt]>=20)
{
duan = (DS_BUF[(buf_sm[3-frash_cnt])-20]&0x7f);//显示小数点
}
else
duan = DS_BUF[buf_sm[3-frash_cnt]];//不显示小数点

wei = ~wei_buf;
wei_buf <<=1;//显示位左移一位
frash_cnt++;
}
else
{
wei |=0xf0;//数码管的消隐
frash_cnt=0;
wei_buf=0x10;//显示位回到最右边
}
}
/*

*/
void delay(uint i)
{
uchar j;
for(;i>0;i--)
for(j=0;j<120;j++);

}
``````

``````#ifndef _shumaguan_h_
#define _shumaguan_h_
#include "math.h"
#include "reg52.h"
#define duan P0
#define wei P2

#define uchar unsigned char
#define uint unsigned int

extern uchar frash_cnt;
extern uchar wei_buf;

void calc_sm(float value);
void display();
void delay(uint i);

#endif
``````

``````#include "reg52.h"
#include "timer.h"
#include "shumaguan.h"

float xdata value=0 , value_now = 0;

void timer_init()
{
TMOD = 0x02;                    //set timer0 as mode1 (16-bit)
TL0 = T1MS;                     //initial timer0 low byte
TH0 = T1MS;                //initial timer0 high byte
TR0 = 1;                        //timer0 start running
ET0 = 1;                        //enable timer0 interrupt
EA = 1;                         //open global interrupt switch
}

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 using 1
{
if(value!=value_now)//检测显示值与当前值是否匹配
{
value=value_now;//刷新显示值
calc_sm(value_now);//重新计算显示值的输出缓冲区
}
display();//刷新数码管显示

}
``````

``````#ifndef _timer_h_
#define _timer_h_
#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int

//-----------------------------------------------

/* define constants */
//#define FOSC 11059200L
#define FOSC 12000000L

#define T1MS 0   //1ms timer calculation method in 12T mode

//-----------------------------------------------

extern float xdata value , value_now;

void timer_init();

#endif
``````