Skip to content

数码管动态扫描

作者:张庆奎

1.数码管介绍

  1. 数码管,其内部含有8个LED,其实是由LED组装而成的。

    8SGOXTXS1V1M{BCU7%{0Z1V_tmb

  2. 从图可以看出来,数码管共有 a、b、c、d、e、f、g、dp 这么 8 个段,而实际上,这 8 个段每一段都是一个 LED 小灯,所以一个数码管就是由 8个 LED 小灯组成的。注意 dp 这个段,它是表示一个小数点!

  3. 数码管分为共阴共阳两种(对于我们使用的STC89C52RC是共阴的)。image-20230614145437270

    1. 共阴数码管就是8只LED灯的阴极是连在一起的,阴极是公共端,由阳极来控制单个小灯的亮灭。

    2. 同理,共阳数码管就是连在一起。

  4. 显示端:a, b, c, d, f, g, dp,这几个端口负责点亮数码管上相应的LED灯,比如a端口控制A这个lLED灯。

  5. 公共端(com):用于选择数码管。

  6. 举例说明:我们现在要使一个数码管显示数字”0“,那么”0“就是点亮A, B, C, D, E, F,对于共阴数码管,它的

​ 相应的端口信号为:

数字dpgfedcba二进制表示十六进制表示
000111111001111110x3f

2.STC89C52RC原理图

本单片机共有六个数码管,共阴

image-20230614145453963

image-20230614145622609

P2口的第六位DULA用于数码管的段锁存器,P2口的第七位WELA用于数码管的位锁存器,所以我们在点亮数码管的过程中要用到这两个锁存器。

image-20230614145636173

由原理图可知显示端的信号,D0-D7分别对应a-h,在位选信号中(即选在哪一个数码管)D0对应WE1即当D0为低电平时第一个数码管亮,后面的D1...同理。

3. 数码管的动态扫描原理

  1. 由于开发板上所有的数码管都是由共用端和显示端连通的,显示端由某一个寄存器控制。
  2. 假设我们让第一个数码管显示1,之后我们还想让第二个数码管显示2,但是当第二个数码管显示2的时候,第一个数码管也会变成2,因为每个数码管的显示端都是由同一个寄存器控制的。
  3. 因此我们可以这样考虑,一次只点亮一个数码管,显示对应的值,点亮之后写一个延迟函数,这个延迟函数在1~2ms之间(1ms即可)。(延迟函数时间太长,就会变成静态效果,延迟函数时间太短,又会由于运行过快,没有稳定点亮就去执行下一语句而产生鬼影。)
  4. 由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
  5. 延迟时间必须相同,并且这些延迟时间不能过长,过长的话人眼会识别出来(过长的话人眼只认为第一个数码管点亮)。

4.实战:在数码管上同时显示012345

c
//overwhelm.h头文件

#define __OVERWHELM_H__
#ifdef CCNUIOT_51
#define uint_16 unsigned int
#define uint_8 unsigned char
#define int_16 int
#define int_8 char
#include <REG52.H>
#include "bsy_tube.h"
#include "bsp_delay.h"
#endif /*CCNUIOT_51*/
#endif /*__OVERWHELM_H__*/
c
//bsp_delay.h
#ifndef __BSP_DELAY_H__ 
#define __BSP_DELAY_H__
#include "overwhelm.h"

void Delay(uint_16 i);

#endif
c
//bsp_delay.c
#include "bsp_delay.h"
//延时函数delay 
void Delay(unsigned int i)
{
	unsigned int m,n;
	
	for(m=i;m>0;m--)
		for(n=90;n>0;n--);
}
c
//bsp_tube.h
//bsp_tube.h
#ifndef __BSP_TUBE_H__
#define __BSP_TUBE_H__
#include "overwhelm.h"
void Static_Display(uint_8 num, uint_8 i);//静态点亮数码管
void Dynamic_Display(); 
#endif
c
//bsp_tube.c
#include "bsy_tube.h"
#include "bsp_delay.h"

sbit dula=P2^6;		//段选信号的锁存器控制
sbit wela=P2^7;		//位选信号的锁存器控制 

uint_8 code wei[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf};
					//数码管各位的码表
uint_8 code duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d};
					//0-5的码表

void Static_Display(uint_8 i, uint_8 num)//num是要显示的数字0-5,i是第几个数码管 
{										//静态点亮数码管 
	P0 = wei[i];
	wela = 1;
	wela = 0;	
	
	P0 = duan[num];
	dula = 1;
	dula = 0;
} 

void Dynamic_Display()//动态点亮数码管
{
	 Static_Display(0, 0);
	 Delay(2);
	 
	 Static_Display(1, 1);
	 Delay(2);
	 
	 Static_Display(2, 2);
	 Delay(2);
	 
	 Static_Display(3, 3);
	 Delay(2);
	 
	 Static_Display(4, 4);
	 Delay(2);
	 
	 Static_Display(5, 5);
	 Delay(2);
}
c
//main.c
#include "overwhelm.h"//注意要包含这个头文件 

void main(void)
{
	while(1)
	{
		Dynamic_Display();//调用动态扫描数码管函数 
	}
}

在数字显示时,需要将不同的数字对应的段选信号和位选信号输出到数码管上,才能正确地显示出数字。而dula和wela这两个引脚则是控制这些信号传递的关键。

在实现数码管显示时,通常需要使用锁存器来保证数据稳定地传递到数码管上,避免闪烁和干扰。每当一个数字需要输出时,会先将该数字对应的位码和段码存储到锁存器中,然后通过控制dula和wela这两个引脚,将锁存器中的数据依次输出到数码管上。

5.思考:

  1. 如何在数码管上显示数字流0-F。
  2. 如何在数码管上显示一个时间,比如23.23.23分别对应时分秒,然后时间依次增加。

Released under the MIT License.