【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数

目录

  • 源码
    • Tube.c
    • Tube.h
    • main.c
  • 效果
    • 8位数码管
      • 正整数
      • 负整数
      • 正小数
      • 负小数
    • 6位数码管
      • 正整数
      • 负整数
      • 正小数
      • 负小数
    • 4位数码管
      • 正整数
      • 负整数
      • 正小数
      • 负小数

普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


源码

移植时主要只修改Tube_Num数量、位选函数Tube_Choose()和单个数码管写入函数Singe_Tube_Write()即可。

数码管基础知识见【51单片机快速入门指南】2.1:数码管显示数字、小数 (科学计数法)
stdint.h内容见【51单片机快速入门指南】一、基础知识和工程创建

Tube.c

#include 
#include "intrins.h"
#include "stdint.h"
#include "Tube.h"

#define Tube_Port P0

#define Tube_Num  8

sbit Tube_A0 = P2^2;
sbit Tube_A1 = P2^3;
sbit Tube_A2 = P2^4;

//位选
void Tube_Choose(uint8_t num)
{
     
	Tube_A0 = (num & 1);
	Tube_A1 = (num & 2) >> 1;
	Tube_A2 = (num & 4) >> 2;
}

//显示的延时 400us @11.0592MHz
void LED_Tube_Delay()
{
     
	unsigned char i;

	_nop_();
	i = 181;
	while (--i);
}

//单个数码管写入数据
void Singe_Tube_Write(uint8_t Data)
{
     
	Tube_Port = Data;
}

code uint8_t Error_Codes[]=
{
     
	Tube_Code_E,
	Tube_Code_r,
	Tube_Code_r,
	Tube_Code_o,
	Tube_Code_r
};

int32_t Pow10(int32_t Pow)
{
     
	int32_t output = 1;
	while (Pow--)
		output *= 10;
	return output;
}

code uint8_t Tube_Codes_0ToF[] =
{
     
	Tube_Code_0,
	Tube_Code_1,
	Tube_Code_2,
	Tube_Code_3,
	Tube_Code_4,
	Tube_Code_5,
	Tube_Code_6,
	Tube_Code_7,
	Tube_Code_8,
	Tube_Code_9,
	Tube_Code_A,
	Tube_Code_b,
	Tube_Code_C,
	Tube_Code_d,
	Tube_Code_E,
	Tube_Code_F
};

//显示整数
void Display_Int(int32_t Num)
{
     
	int8_t i = 0;
	uint8_t DisplayNum = 0;
	char Tube_Double_Buffer[Tube_Num] = {
     0};
	uint8_t Sign_Flag = 0;
	if(Num >= Pow10(Tube_Num) - 1 || Num <= -(Pow10(Tube_Num - 1) - 1))									
	{
     
		for(i = Tube_Num - 1; i >= 0; --i)
		{
     
			Singe_Tube_Write(Tube_Code_NULL);					//消隐
			Tube_Choose(i);
			if(Tube_Num - 1 - i < sizeof(Error_Codes))
				Singe_Tube_Write(Error_Codes[Tube_Num - 1 - i]);			//显示
			else
				Singe_Tube_Write(Tube_Code_NULL);
			LED_Tube_Delay();
		}
		return;
	}
	else
	{
     
		if(Num < 0)
		{
     
			Sign_Flag = 1;
			Num = -Num;
		}
		for(i = 0; i < Tube_Num; ++i)
		{
     
			DisplayNum = Num % 10;
			if(Num == 0 && i != 0)
			{
     
				if(Sign_Flag)
				{
     
					Tube_Double_Buffer[i] = Tube_Code_Negative_Sign;	//负号
					Sign_Flag = 0;
				}
				else
					Tube_Double_Buffer[i] = Tube_Code_NULL;
			}
			else
				Tube_Double_Buffer[i] = Tube_Codes_0ToF[DisplayNum];
			Num /= 10;
		}

		for(i = 0; i < Tube_Num; ++i)
		{
     
			Singe_Tube_Write(Tube_Code_NULL);					//消隐
			Tube_Choose(i);
			Singe_Tube_Write(Tube_Double_Buffer[i]);			//显示
			LED_Tube_Delay();
		}
		return;
	}
}

//显示小数
void Display_Double(double Num)
{
     
	int8_t i = 0;
	int8_t j = 0;
	uint8_t DisplayNum = 0;
	int32_t Int; 
	int8_t Int_Flag;
	double Double;
	char Tube_Double_Buffer[Tube_Num] = {
     0};
	if(Num >= Pow10(Tube_Num) - 1 || Num <= -(Pow10(Tube_Num - 1) - 1))									
	{
     
		for(i = Tube_Num - 1; i >= 0; --i)
		{
     
			Singe_Tube_Write(Tube_Code_NULL);					//消隐
			Tube_Choose(i);
			if(Tube_Num - 1 - i < sizeof(Error_Codes))
				Singe_Tube_Write(Error_Codes[Tube_Num - 1 - i]);			//显示
			else
				Singe_Tube_Write(Tube_Code_NULL);
			LED_Tube_Delay();
		}
		return;
	}
	else
	{
     
		if(Num < 0)
		{
     
			Tube_Double_Buffer[Tube_Num - 1] = Tube_Code_Negative_Sign;	//负号
			Num = -Num;
		}
		Int = (int32_t)Num;
		Double = Num - Int;
		for (j = 0; Int >= Pow10(j); ++j);
		for(i = Tube_Num - 1 - (Tube_Double_Buffer[Tube_Num - 1] == Tube_Code_Negative_Sign), Int_Flag = 1; i >= 0; --i)
		{
     	
			if(Int_Flag)
				if(Int)
					for(; j; --j, --i)
					{
     
						Tube_Double_Buffer[i] = Tube_Codes_0ToF[Int / Pow10(j - 1)];
						Int %= Pow10(j - 1);
						if (j == 1)
						{
     
							--j;
							Tube_Double_Buffer[i--] |= Tube_Code_Dot;
							Int_Flag = 0;
							break;
						}
					}
				else
				{
     
					Tube_Double_Buffer[i--] = Tube_Codes_0ToF[0] | Tube_Code_Dot;
					Int_Flag = 0;
				}
			Double *= 10;
			Tube_Double_Buffer[i] = (uint8_t)(Double + (i == 0) * 0.5);		//末位四舍五入
			Double -= (int)Tube_Double_Buffer[i];
			Tube_Double_Buffer[i] = Tube_Codes_0ToF[Tube_Double_Buffer[i]];
		}
		for(i = 0; i < Tube_Num; ++i)
		{
     
			Singe_Tube_Write(Tube_Code_NULL);					//消隐
			Tube_Choose(i);
			Singe_Tube_Write(Tube_Double_Buffer[i]);			//显示
			LED_Tube_Delay();
		}
		return;
	}
}

//显示数字
void Display_Num(double Num)
{
     
	if(Num == (int32_t)Num)
		Display_Int((int32_t)Num);
	else
		Display_Double(Num);
	return;
}

Tube.h

#ifndef TUBE_H_
#define TUBE_H_

#define Tube_Code_NULL 0x00

#define Tube_Code_0 0x3f
#define Tube_Code_1 0x06
#define Tube_Code_2 0x5b
#define Tube_Code_3 0x4f
#define Tube_Code_4 0x66
#define Tube_Code_5 0x6d
#define Tube_Code_6 0x7d
#define Tube_Code_7 0x07
#define Tube_Code_8 0x7f
#define Tube_Code_9 0x6f

#define Tube_Code_A 0x77
#define Tube_Code_b 0x7c
#define Tube_Code_C 0x39
#define Tube_Code_c 0x58
#define Tube_Code_d 0x5e
#define Tube_Code_E 0x79
#define Tube_Code_F 0x71
#define Tube_Code_G 0x3d
#define Tube_Code_H 0x76
#define Tube_Code_I 0x30
#define Tube_Code_i 0x10
#define Tube_Code_J 0x0e
#define Tube_Code_K	0x7a
#define Tube_Code_L 0x38
#define Tube_Code_M 0x55
#define Tube_Code_n	0x54
#define Tube_Code_o 0x5c
#define Tube_Code_P 0x73
#define Tube_Code_q 0x67
#define Tube_Code_r 0x50
#define Tube_Code_S 0x64
#define Tube_Code_t 0x78
#define Tube_Code_U	0x3e
#define Tube_Code_u 0x1c
#define Tube_Code_v 0x62
#define Tube_Code_W 0x6a
#define Tube_Code_X 0x36
#define Tube_Code_y 0x6e
#define Tube_Code_Z 0x49

#define Tube_Code_Dot 0x80
#define Tube_Code_Negative_Sign 0x40

void Display_Int(int32_t Num);
void Display_Double(double Num);
void Display_Num(double Num);

#endif

main.c

#include 
#include "intrins.h"
#include "stdint.h"
#include "Tube.h"

void main(void)
{
     	
	while(1)
	{
     
		Display_Num(-235);
	}		
}

效果

8位数码管

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第1张图片
【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第2张图片

#define Tube_Port P0

#define Tube_Num  8

sbit Tube_A0 = P2^2;
sbit Tube_A1 = P2^3;
sbit Tube_A2 = P2^4;

//位选
void Tube_Choose(uint8_t num)
{
     
	Tube_A0 = (num & 1);
	Tube_A1 = (num & 2) >> 1;
	Tube_A2 = (num & 4) >> 2;
}

//显示的延时 400us @11.0592MHz
void LED_Tube_Delay()
{
     
	unsigned char i;

	_nop_();
	i = 181;
	while (--i);
}

//单个数码管写入数据
void Singe_Tube_Write(uint8_t Data)
{
     
	Tube_Port = Data;
}

正整数

while(1)
{
     
	Display_Num(23333);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第3张图片

负整数

while(1)
{
     
	Display_Num(-123456);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第4张图片

正小数

while(1)
{
     
	Display_Num(1.23456);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第5张图片

负小数

while(1)
{
     
	Display_Num(-45.678987);
}		

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第6张图片

6位数码管

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第7张图片
【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第8张图片

#define Tube_Port P0

#define Tube_Num  6

sbit SEG_DLE = P2^6;
sbit SEG_WLE = P2^7;

//位选
void Tube_Choose(uint8_t num)
{
     
	SEG_DLE = 0;
	SEG_WLE = 1;
	Tube_Port = ~(0x20 >> num);
	SEG_WLE = 0;
}

//显示的延时 400us @11.0592MHz
void LED_Tube_Delay()
{
     
	unsigned char i;

	_nop_();
	i = 181;
	while (--i);
}

void Singe_Tube_Write(uint8_t Data)
{
     
	SEG_DLE = 1;
	SEG_WLE = 0;
	Tube_Port = Data;
	SEG_DLE = 0;
}

正整数

while(1)
{
     
	Display_Num(23333);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第9张图片

负整数

while(1)
{
     
	Display_Num(-12);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第10张图片

正小数

while(1)
{
     
	Display_Num(1.23456);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第11张图片

负小数

while(1)
{
     
	Display_Num(-45.678987);
}		

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第12张图片

4位数码管

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第13张图片

#define Tube_Port P0

#define Tube_Num  4

sbit Tube_Y0 = P1^0;
sbit Tube_Y1 = P1^1;
sbit Tube_Y2 = P1^2;
sbit Tube_Y3 = P1^3;

//位选
void Tube_Choose(uint8_t num)
{
     
	switch(num)
	{
     
		case 0:
			Tube_Y0 = 1;
			Tube_Y1 = 0;
			Tube_Y2 = 0;
			Tube_Y3 = 0;
			break;
		case 1:
			Tube_Y0 = 0;
			Tube_Y1 = 1;
			Tube_Y2 = 0;
			Tube_Y3 = 0;
			break;
		case 2:
			Tube_Y0 = 0;
			Tube_Y1 = 0;
			Tube_Y2 = 1;
			Tube_Y3 = 0;
			break;
		case 3:
			Tube_Y0 = 0;
			Tube_Y1 = 0;
			Tube_Y2 = 0;
			Tube_Y3 = 1;
			break;
	}
}

//显示的延时 1ms @12MHz
void LED_Tube_Delay()
{
     
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
     
		while (--j);
	} while (--i);
}

void Singe_Tube_Write(uint8_t Data)
{
     
	Tube_Port = Data;
}

正整数

while(1)
{
     
	Display_Num(233);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第14张图片

负整数

while(1)
{
     
	Display_Num(-12);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第15张图片

正小数

while(1)
{
     
	Display_Num(1.23456);
}

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第16张图片

负小数

while(1)
{
     
	Display_Num(-45.678987);
}		

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数_第17张图片

你可能感兴趣的:(51单片机,电赛,51单片机,嵌入式硬件,单片机,数码管,keil)