STC15单片机动态数码管实现原理详解

目录

点亮一位数码管

动态数码管

100s倒计时

动态数码管封装代码



点亮一位数码管

段选:选中哪一位数码管

位选:选中的数码管要显示的内容

这是我对段选位选的理解,就是选中某个位置,赋值字形码,显示想要的图形

如果只想让第一个数码管显示,就只需要让com1 = 1即可,其他comx都=0

如果想让8个数码管都亮,就让com1~com8都赋值1,此时对数码管赋值,8个数码管都会显示一致的内容

如果想让不同数码管显示不同的内容且互不干扰,就需要不断的段选、位选,段选、位选,段选、位选。

先打开段选的锁存器(U8),用来选择哪个数码管亮,U8的Y6C = 1来控制

往前推导就是Y6 = 0;WR = 0(跳线帽链接)

Y6又由138译码器控制

P27 = 1; P26 = 1; P25 = 0;        //段选

 选中第一个数码管 P00 = 1;

P27 = 1; P26 = 1; P25 = 1;        //位选

 第一个LED显示个0  P0 = 0xC0;

代码如下:

#include <STC15F2K60S2.H>
#include "smg.h"

void main()
{
	P2 = 0xA0;	P0 = 0x00;	//初始化,关闭蜂鸣器继电器
//	P2 = 0x80;	P0 = 0xFF;	//Y4=0;选中LED,使其灭
	
	//数码管段选
	P27 = 1; P26 = 1; P25 = 0;	//Y6=0;Y6C=1; 使能锁存器U8
	P00 = 1; 					//选中第一个数码管
	//数码管位选
	P27 = 1; P26 = 1; P25 = 1;	//Y7=0;Y7C=1; 使能锁存器U7
	P0 = 0xC0;					//显示0
	
	while(1)
	{	}
}

如果想让第5个数码管也显示相同的内容,就在段选的第二行代码,将P04也选中

#include <STC15F2K60S2.H>
#include "smg.h"

void main()
{
	P2 = 0xA0;	P0 = 0x00;	//初始化,关闭蜂鸣器继电器
//	P2 = 0x80;	P0 = 0xFF;	//Y4=0;选中LED,使其灭
	
	//数码管段选
	P27 = 1; P26 = 1; P25 = 0;	//Y6=0;Y6C=1; 使能锁存器U8
	P00 = 1; P04 = 1;			//选中第一个数码管
	//数码管位选
	P27 = 1; P26 = 1; P25 = 1;	//Y7=0;Y7C=1; 使能锁存器U7
	P0 = 0xC0;					//显示0
	
	while(1)
	{	}
}

动态数码管

动态数码管的工作原理及使用

动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一个数码管有效。这样一来,就没有必要每一位数码管分配一个锁存器,从而大大简化硬件电路。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码挂送出字形码和相应的位选,利用发光二极管的余晖和人眼视觉暂留作用,使人肉眼感觉各位数码管同时都在显示。动态显示的两幅比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的电阻。

明白了一位数码管是怎么显示的,就可以操作8个数码管了

下面是一次操作8个数码管动态显示的代码

第一个数码管显示1,第二个数码管显示2……第八个数码管显示8

#include "smg.h"
#include "intrins.h"


void Delay_ms(int xms)		//15单片机延时函数@11.0592MHz
{
	unsigned char i, j;		
	while(xms--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}	
}

/*共阳极码表 ABCDEF都是大写*/
unsigned char wei[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x80, 0xC6, 0xC0, 0x86, 0x8E, 0xBF, 0xFF};
					   //0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F     -    灭

	
void SMG_Diaplay(void)
{
	//第1个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x01;	//选中第1个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[1];
	Delay_ms(1);
	
	//第2个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x02;	//选中第2个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[2];
	Delay_ms(1);
	
	//第3个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x04;	//选中第3个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[3];
	Delay_ms(1);
	
	//第4个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x08;	//选中第4个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[4];
	Delay_ms(1);
	
	//第5个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x10;	//选中第5个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[5];
	Delay_ms(1);
	
	//第6个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x20;	//选中第6个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[6];
	Delay_ms(1);
	
	//第7个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x40;	//选中第7个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[7];
	Delay_ms(1);
	
	//第8个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x80;	//选中第8个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[8];
	Delay_ms(1);
}

在while(1)里调用SMG_Diaplay即可

偷偷懒,用stc给的延时1ms代码,延时1ms的目的是消影,即将本次的段选位选上一次的段选位选分隔开,互不影响,否则数码管会重影看不清,莎普爱思也没用

函数中有_nop_();    需要调用#include "intrins.h"头文件


100s倒计时

后三位数码管依次显示百十个位上的数字

我的思路是定义一个时间变量Time,初始化=100

在1s中断的程序里让Time–,这样就实现了100s倒计时

如何让这每一位都显示在数码管上呢?

我采用数位分离的方法,即将一个数的百位、十位、个位都分离出来,分别显示

三位数数位分离方法

bai = Time/100

shi = Time/10%10

ge = Time%10

 

 数码管部分代码

#include "smg.h"
#include "intrins.h"


void Delay_ms(int xms)		//15单片机延时函数@11.0592MHz
{
	unsigned char i, j;		
	while(xms--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}	
}

/*共阳极码表 ABCDEF都是大写*/
unsigned char wei[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x80, 0xC6, 0xC0, 0x86, 0x8E, 0xBF, 0xFF};
					   //0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F     -    灭

		
void DJS_Show(unsigned char bai, unsigned char shi, unsigned char ge)
{
	//第6个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x20;	//选中第6个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[bai];	//显示百位
	Delay_ms(1);
	
	//第7个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x40;	//选中第7个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[shi];	//显示十位
	Delay_ms(1);
	
	//第8个数码管
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	P0 = 0x80;	//选中第8个数码管
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0 = wei[ge];	//显示个位
	Delay_ms(1);
}	
#ifndef __SMG_H__
#define __SMG_H__

#include <STC15F2K60S2.H>

extern unsigned char wei[];

void SMG_Diaplay(void);
void DJS_Show(unsigned char bai, unsigned char shi, unsigned char ge);

#endif

主程序代码

#include <STC15F2K60S2.H>
#include "smg.h"
#include "Timer0.h"

unsigned char Time = 100;

void main()
{
	P2 = 0xA0;	P0 = 0x00;	//初始化,关闭蜂鸣器继电器
	P2 = 0x80;	P0 = 0xFF;	//Y4=0;选中LED,使其灭
	Timer0_Init();	
	
	while(1)
	{
		DJS_Show(Time/100, Time/10%10, Time%10);
	}
}

void Timer0_Rountine(void) interrupt 1
{	//5ms定时
	static unsigned int Count0;

	Count0++;
	if(Count0 >= 200)	//1s
	{
		Time--;
		Count0 = 0;	//软件复位
	}
}

这个100s是不精确的,因为控制数码管程序里时钟有1ms延时


动态数码管封装代码

改用一位一位单独控制的数码管,操作方便 

和51单片机数码管程序差不多

void Delay_ms(int xms)		//15单片机延时函数@11.0592MHz
{
	unsigned char i, j;		
	while(xms--)
	{
		_nop_();		_nop_();		_nop_();
		i = 11;		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}	
}

/*共阳极码表 ABCDEF都是大写*/
unsigned char NixieTable[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x80, 0xC6, 0xC0, 0x86, 0x8E, 0xBF, 0xFF};
					   //0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F     -    灭

void Nixie(unsigned char location, unsigned char number)
{
	P2 = 0xC0;	//Y6=0;Y6C=1; 使能锁存器U8     P27 = 1; P26 = 1; P25 = 0;
	switch(location)//选中LED位置,位选
	{
		case 1:P0 = 0x01;break;
		case 2:P0 = 0x02;break;
		case 3:P0 = 0x04;break;
		case 4:P0 = 0x08;break;
		case 5:P0 = 0x10;break;
		case 6:P0 = 0x20;break;
		case 7:P0 = 0x40;break;
		case 8:P0 = 0x80;break;
	}
	P2 = 0xFF;	//Y7=0;Y7C=1; 使能锁存器U7     P27 = 1; P26 = 1; P25 = 1;
	P0=NixieTable[number];//数字
	Delay_ms(1);
	P0=0xFF;//消影清零,否则重影
}

物联沃分享整理
物联沃-IOTWORD物联网 » STC15单片机动态数码管实现原理详解

发表评论