Brimon-zZY

适用于两片74HC573级联的8位数码管(用74HC595驱动的数码管底层驱动请移步:595

头文件:

#include<reg52.h>

引脚定义(用于清翔51单片机):
sbit WE = P2^7;
sbit DU = P2^6;

定义部分(定义在全局):
unsigned int code smg_duan[12] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40,0x00};
unsigned int code smg_wei[9] = {0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};

函数部分:(这个是有BUG的)
void delay()   //延时500μS
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=227;a>0;a--);
}
void smg(unsigned long a)
{
    unsigned int arc[9];
    unsigned int i;
    arc[8] = smg_duan[a % 10];
    arc[7] = smg_duan[(a / 10) % 10];
    arc[6] = smg_duan[(a / 100) % 10];
    arc[5] = smg_duan[(a / 1000) % 10];
    arc[4] = smg_duan[(a / 10000) % 10];
    arc[3] = smg_duan[(a / 100000) % 10];
    arc[2] = smg_duan[(a / 1000000) % 10];
    arc[1] = smg_duan[(a / 10000000) % 10];
    while(1)
    {
        for(i = 1; i <= 8; i ++)
        {
            P0 = 0xFF;
            WE = 1;
            P0 = smg_wei[i];
            WE = 0;
            DU = 1;
            P0 = arc[i];
            DU = 0;
            delay();
        }
    }
}

 

调用方式:


void main()
{
    smg(32168465);   //最高8位
    while(1);
}

 

但是上面那个是有bug的,现在我还不会调orz  (2020 11 3)

 更新(2020/12/27):

上面的代码在定时器中断下产生bug的原因:

由于定时器中断设置的是5ms扫描一次。所以每一次进入中断都不能执行完一次动态扫描(一次完整的动态扫描时间超过5ms),所以会出现bug。

最简单的方案就是只进行1次静态扫描,下一次进入中断在进行下一位静态扫描。

所以就需要生命static uint型变量。

不过不通过定时器中断实现动态扫描的话还是需要进行上面的循环的。

 

 

下面这个是没有bug的中断调用的方法:

 

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit DU = P2^6;
sbit WE = P2^7;
uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
uchar code SMGwei[] = {0xfe, 0xfd, 0xfb};

void display(uchar i)
{
    static uchar wei;         
    P0 = 0XFF;
    WE = 1;
    P0 = SMGwei[wei];
    WE = 0;
    switch(wei)
    {
        case 0: DU = 1; P0 = SMGduan[i / 100]; DU = 0; break;
        case 1: DU = 1; P0 = SMGduan[i % 100 / 10]; DU = 0; break;    
        case 2: DU = 1; P0 = SMGduan[i % 10]; DU = 0; break;        
    }
    wei++;
    if(wei == 3)
        wei = 0;
}

//定时器0初始化
void timer0Init()
{
    EA = 1;    //打开总中断
    ET0 = 1;//打开定时器0中断
    TR0 = 1;     //启动定时器0
    TMOD |= 0X01; //定时器工作模式1,16位定时模式
    TH0 = 0xED;
    TL0 = 0xFF; //定时5ms
}

void mian()
{
    timer0Init();
    
}

//定时器0中断函数
void timer0() interrupt 1
{
    TH0 = 0xED;
    TL0 = 0xFF; //定时5ms
    display(num); //数码管显示函数    
}

 

上面的代码只是3位数码管的显示,如果需要8位数码管还需要加上4个case以及将定时器中断的时间调小。

 

 

下面是另两种实现方式(8位数码管):一定不能在中断下调用,否则会出现bug

unsigned int code table[25] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5E,0x79,0x71,0x76,0x38,0x37,0x3E,0x40,0x00};  //0x40是负号  用10来标记
unsigned int code duan[10] = {0,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};

 

void digitaltube(unsigned int du,unsigned int num)
{
	if(num == 10)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[20];
		DU = 0; 
	}
	if(num == 0)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[0];
		DU = 0;
	}
	if(num == 1)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[1];
		DU = 0;
	}
	if(num == 2)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[2];
		DU = 0;
	}
	if(num == 3)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[3];
		DU = 0;
	}
	if(num == 4)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[4];
		DU = 0;
	}
	if(num == 5)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[5];
		DU = 0;
	}
	if(num ==6)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[6];
		DU = 0;
	}
	if(num == 7)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[7];
		DU = 0;
	}
	if(num == 8)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[8];
		DU = 0;
	}
	if(num == 9)
	{
		P0 = 0xFF;
		WE = 1;
		P0 = duan[du];
		WE = 0;
		
		DU = 1;
		P0 = table[9];
		DU = 0;
	}
}	

void display(unsigned long a)
{
	a8 = a % 10;
	a7 = (a / 10) % 10;
	a6 = (a / 100) % 10;
	a5 = (a / 1000) % 10;
	a4 = (a / 10000) % 10;
	a3 = (a / 100000) % 10;
	a2 = (a / 1000000) % 10;
	a1 = (a / 10000000) % 10;
	digitaltube(1,a1); delay();
	digitaltube(2,a2); delay();
	digitaltube(3,a3); delay();
	digitaltube(4,a4); delay();
	digitaltube(5,a5); delay();
	digitaltube(6,a6); delay();
	digitaltube(7,a7); delay();
	digitaltube(8,a8); delay();
}

 

或者:

#include<reg52.h>

sbit WE = P2^7;
sbit DU = P2^6;

unsigned int code smg_duan[12] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40,0x00};
unsigned int code smg_wei[9] = {0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
void delay()   //延时500μS
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=227;a>0;a--);
}
void smg(unsigned long a)
{
    unsigned int arc[9];
    unsigned int i;
    arc[8] = smg_duan[a % 10];
    arc[7] = smg_duan[(a / 10) % 10];
    arc[6] = smg_duan[(a / 100) % 10];
    arc[5] = smg_duan[(a / 1000) % 10];
    arc[4] = smg_duan[(a / 10000) % 10];
    arc[3] = smg_duan[(a / 100000) % 10];
    arc[2] = smg_duan[(a / 1000000) % 10];
    arc[1] = smg_duan[(a / 10000000) % 10];
    while(1)
    {
        for(i = 1; i <= 8; i ++)
        {
            P0 = 0xFF;
            WE = 1;
            P0 = smg_wei[i];
            WE = 0;
            DU = 1;
            P0 = arc[i];
            DU = 0;
            delay();
        }
    }
}

void main()
{
    smg(32168465);
    while(1);
}
不在中断情况下调用的8位数码管显示

 

分类:

技术点:

相关文章: