学习数码管的动态显示[译码器实现位选|基于普中 HC6800]

  开发板买来半个月,有空就会玩儿玩儿,不过我玩儿的都还是比较初级的东西,所以感觉也没什么可写的,今天就把搞定数码管动态显示的东西记一下吧。

  常见的数码管(7-segment display)封装形式有一位数字的,也有多位数字的。在只有一位数字的数码管上显示一个数字(或者在多位封装的数码管上显示若干个一样的数字)叫做静态显示,静态显示不是说显示的数字不可变,而是意味着在显示这个数字期间,数码管的状态不变,是静态的。数码管的动态显示用于多位数码管,拿 4 位数码管来举例,4 位数码管的所有段(segment)引脚是公用的,然后由 4 个位选引脚来决定哪个数字位有效。比如说我们想显示在这个 4 位数码管上显示 0123,那么实际上要做的事情其实是:

  1. 用位选选中 4 位数码管中的第一个数字位
  2. 给数码管送 0 这个数字的字模
  3. 关闭数码管的显示
  4. 用位选选中 4 位数码管中的第二个数字位
  5. 给数码管送 1 这个数字的字模
  6. ……以此类推……

从上面过程可以看出来,就算我们想显示的是一串恒定的数字 0123,但对于 4 位数码管来说,这个过程是一个动态的逐位显示的过程,所以叫动态显示。

环境准备

以下描述都以我手上的普中 HC6800 为准:

  1. 用跳线帽连接 J15 和 J16
  2. 用排线连接 JP10(P0)和 J12
  3. J21 接 VCC

原理

这里我们用 74HC138 这个译码器(Decoder)来实现 2 个 4 位数码管的位选:
Pin configuration of 74HC138
74HC138 的真值表如下:
Truth table of 74HC138
74HC138 有 3 个输入(接 P2.2、P2.3、P2.4),8 个输出,从真值表上可以看出,74HC138 的作用就相当于把一个 3 位二进制数的输入转换成某个输出脚上的低电平。2 个 4 位数码管,做位选刚好够用:)

HC6800 用的 2 个 4 位数码管是共阴极数码管,用 74HC573 锁存器(Latch)来驱动:
Pin configuration of 74HC573
74HC573 有 8 个输入,8 个输出:
Truth table of 74HC573
由于 J21 接了 VCC(LE 高电平),-OE 接了 GND,所以 74HC573 工作在 transparent mode,Dn 如果是低电平,对应的 Qn 也是低电平;如果 Dn 是高电平,对应的 Qn 也是高电平。74HC573 的作用应该是提供点亮数码管所需的电流(这里暂时存疑)。J12 和 JP10 连接以后,P0 就是 74HC573 的输入。

代码

SSD.h

  1. #ifndef __SEVEN_SEGMENT_DISPLAY__20101030__
  2.  #define __SEVEN_SEGMENT_DISPLAY__20101030__
  3.  
  4.  unsigned char
  5.  GetSSDCode(
  6.      unsigned char n,
  7.      bit bWithDP// Decimal Point
  8.      bit bCC );    // Common Cathode(-) or Common Anode(+)
  9.  
  10.  unsigned char
  11.  GetEmptySSDCode( bit bCC )// Common Cathode(-) or Common Anode(+)
  12.  
  13.  #endif  // __SEVEN_SEGMENT_DISPLAY__20101030__

SSD.c

  1. /*
  2.     A
  3.   +---+
  4.  F|   |B
  5.   +-G-+
  6.  E|   |C
  7.   +---+  oDP
  8.     D
  9.  
  10.   7 6 5 4 3 2 1 0
  11.  DP G F E D C B A
  12.   8 4 2 1,8 4 2 1
  13.  */
  14.  unsigned char code SSDCodes[] =
  15.  {
  16.      0x3F// 0 = ABCDEF
  17.      0x06// 1 = BC
  18.      0x5B// 2 = ABGED
  19.      0x4F// 3 = ABCDG
  20.      0x66// 4 = BCFG
  21.      0x6D// 5 = ACDFG
  22.      0x7D// 6 = ACDEFG
  23.      0x07// 7 = ABC
  24.      0x7F// 8 = ABCDEFG
  25.      0x6F// 9 = ABCDFG
  26.      0x77// A = ABCEFG
  27.      0x7C// b = CDEFG
  28.      0x39// C = ADEF
  29.      0x5E// d = BCDEG
  30.      0x79// E = ADEFG
  31.      0x71// F = AEFG
  32.  };
  33.  
  34.  unsigned char
  35.  GetSSDCode(
  36.      unsigned char n,
  37.      bit bWithDP// Decimal Point
  38.      bit bCC )     // Common Cathode(-) or Common Anode(+)
  39.  {
  40.      unsigned char SSDCode;
  41.      if( n >= 0 && n < sizeof( SSDCodes ) / sizeof( SSDCodes[0] ) )
  42.          SSDCode = SSDCodes[n];
  43.  
  44.      if( bWithDP )
  45.          SSDCode |= 0x80;
  46.  
  47.      return( bCC ? SSDCode : ~SSDCode );
  48.  }
  49.  
  50.  unsigned char
  51.  GetEmptySSDCode( bit bCC )  // Common Cathode(-) or Common Anode(+)
  52.  {
  53.      return( bCC ? 0 : 0xFF );
  54.  }

main.c

  1. #include <reg52.h>
  2.  #include "SSD.h"
  3.  
  4.  sbit DecoderA = P2^2;
  5.  sbit DecoderB = P2^3;
  6.  sbit DecoderC = P2^4;
  7.  
  8.  void Display( unsigned char pos, unsigned char n )
  9.  {
  10.      switch( pos )
  11.      {
  12.          case 0: DecoderC = 0; DecoderB = 0; DecoderA = 0; break;
  13.          case 1: DecoderC = 0; DecoderB = 0; DecoderA = 1; break;
  14.          case 2: DecoderC = 0; DecoderB = 1; DecoderA = 0; break;
  15.          case 3: DecoderC = 0; DecoderB = 1; DecoderA = 1; break;
  16.          case 4: DecoderC = 1; DecoderB = 0; DecoderA = 0; break;
  17.          case 5: DecoderC = 1; DecoderB = 0; DecoderA = 1; break;
  18.          case 6: DecoderC = 1; DecoderB = 1; DecoderA = 0; break;
  19.          case 7: DecoderC = 1; DecoderB = 1; DecoderA = 1; break;
  20.      }
  21.      P0 = GetSSDCode( n, 0, 1 );
  22.  }
  23.  
  24.  void main()
  25.  {
  26.      unsigned char i = 0;
  27.      do
  28.      {
  29.          for( i = 0; i < 8; ++i )
  30.          {
  31.              Display( i, i );
  32.              P0 = GetEmptySSDCode( 1 );
  33.          }
  34.      }
  35.      while( 1 );   
  36.  }

程序烧进 89C52 以后会看到 2 个 4 位数码管上显示 0 到 7 这 8 个数字。

Leave a Reply