一、数码管组成
数码管是由多个发光二极管封装在一起组成8字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极;
数码管常用段数一般为7段,有的另加一个小数点,每一段即是由一个发光二极管组成,一般每一段都需加上限流电阻;
1.1、共阳数码管
共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管。共阳数码管在应用时应将公共极COM接到电源正极,当某一字段发光二极管的阴极为低电平时,相应字段就点亮。当某一字段的阴极为高电平时,相应字段就不亮。
1.2、共阴数码管
共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管。共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮。当某一字段的阳极为低电平时,相应字段就不亮。
二、数码管显示方式
数码管可分为静态显示和动态显示。
静态显示即可普通点亮发光二极管的方式一样,比如共阳数码管,公共极给予固定高电平输出,对应的字段给予低电平,即可一直保持常亮的状态;
其实所谓的动态显示就是静态显示,它是利用人的视觉暂留现象及发光二极管的余辉效应。尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。在设计代码的时候,我们在每一位数码管显示后加上大概2ms的延迟,这样我们在循环扫描数码管的时候就会因为人的视觉效应导致观察的每个数码管都是同时亮的。
三、四位数码管驱动电路
如下图所示是一个简单的四位共阳极数码管驱动电路,一般采用PNP三极管驱动,因为普通的单片机IO口不能承受大的驱动电流,当基极给予低电平时,PNP三极管导通,数码管公共端得到高电平。
四、数码管专用驱动芯片
现在一般采用专用驱动芯片驱动数码管,集成度高,显示稳定,节省单片机IO口和提高驱动电流能力。如TM1640。参考硬件电路如下图:
五、静态显示示例代码
#include "STC8H.h" //头文件
/*数码管控制IO宏定义*/
#define LED_A P77
#define LED_B P26
#define LED_C P46
#define LED_D P01
#define LED_E P02
#define LED_F P27
#define LED_G P45
#define LED_DP P00
#define LED_DIG1 P53
#define LED_DIG2 P52
#define LED_DIG3 P04
#define LED_DIG4 P03
#define LED_DIG5 P20
#define LED_DIG6 P21
#define LED_DIG7 P22
#define LED_DIG8 P23
/*
共阳数码管段码表
这里使用一维数组,
方括号中的数量是其数组所包含元素,但其下标应该从0开始 。
如 a[3] 包含 a[0], a[1], a[2] 三个元素
0, 1, 2分别表示其元素下标
这里用到const关键字,const含义:只要一个变量前用const来修饰,
就意味着该变量里的数据只能被访问,而不能被修改,也就是意味着“只读”
被const修饰后变量存储在单片机内部Flash里
*/
unsigned char const display_ca_table[16] =
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e
}; //0-F
/*
*函数名称:void soft_delay(unsigned int ms)
*描述:软件延时
*输入:ms - 延时时间参数
*输出:无
*返回:无
*/
void soft_delay(unsigned int ms)
{
unsigned int i,j;
for(i = 0;i < ms;i++)
for(j = 0;j < 200;j++);
}
void main(void)
{
unsigned char i;
P0M1 = 0X00; P0M0 = 0X1F; //设置P00/P01/P02/P03/P04为推挽输出口
P2M1 = 0X00; P2M0 = 0XCF; //设置P20/P21/P22/P23/P26/P27为推挽输出口
P4M1 = 0X00; P4M0 = 0X60; //设置P45/P46为推挽输出口
P5M1 = 0X00; P5M0 = 0X0C; //设置P52/P53为推挽输出口
P7M1 = 0X00; P7M0 = 0X80; //设置P77为推挽输出口
while(1)
{
for(i = 0; i < 8;i++)
{
/*
1、>> 右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,
对于无符号数,高位补0
无符号数:7 >> 2
7 转换为二进制:0000 0111,每位向右移动两位变为:00000001,
转换为十六进制数为0x01。
2、& 按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
0 & 0 =0;0 & 1 =0;1 & 0 =0;1 & 1 =1。
*/
LED_A = (display_ca_table[i]>>0) & 0x01;
LED_B = (display_ca_table[i]>>1) & 0x01;
LED_C = (display_ca_table[i]>>2) & 0x01;
LED_D = (display_ca_table[i]>>3) & 0x01;
LED_E = (display_ca_table[i]>>4) & 0x01;
LED_F = (display_ca_table[i]>>5) & 0x01;
LED_G = (display_ca_table[i]>>6) & 0x01;
LED_DP = (display_ca_table[i]>>7) & 0x01;
LED_DIG1 = 1;
LED_DIG2 = 1;
LED_DIG3 = 1;
LED_DIG4 = 0;
LED_DIG5 = 1;
LED_DIG6 = 1;
LED_DIG7 = 1;
LED_DIG8 = 0;
soft_delay(2000);
}
}
}
六、动态显示示例代码
#include "STC8H.h"
#define LED_A P77
#define LED_B P26
#define LED_C P46
#define LED_D P01
#define LED_E P02
#define LED_F P27
#define LED_G P45
#define LED_DP P00
#define LED_DIG1 P53
#define LED_DIG2 P52
#define LED_DIG3 P04
#define LED_DIG4 P03
#define LED_DIG5 P20
#define LED_DIG6 P21
#define LED_DIG7 P22
#define LED_DIG8 P23
unsigned char dynamic_step = 0;
unsigned char const display_ca_table[16] =
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e
}; //0-F
/*
*函数名称:void soft_delay(unsigned int ms)
*描述:软件延时
*输入:ms - 延时时间参数
*输出:无
*返回:无
*/
void soft_delay(unsigned int ms)
{
unsigned int i,j;
for(i = 0;i < ms;i++)
for(j = 0;j < 200;j++);
}
void main(void)
{
unsigned char i = 0;
P0M1 = 0X00; P0M0 = 0X1F; //设置P00/P01/P02/P03/P04为推挽输出口
P2M1 = 0X00; P2M0 = 0XCF; //设置P20/P21/P22/P23/P26/P27为推挽输出口
P4M1 = 0X00; P4M0 = 0X60; //设置P45/P46为推挽输出口
P5M1 = 0X00; P5M0 = 0X0C; //设置P52/P53为推挽输出口
P7M1 = 0X00; P7M0 = 0X80; //设置P77为推挽输出口
while(1) //死循环
{
switch(dynamic_step) //八个数码管轮流切换显示,时间很多,人眼看起来是同步点亮
{
case 0: //第一个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 0;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 1;
break;
case 1: //第二个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 0;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 2;
break;
case 2: //第三个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 0;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 3;
break;
case 3: //第四个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 0;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 4;
break;
case 4: //第五个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 0;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 5;
break;
case 5: //第六个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 0;LED_DIG7 = 1;LED_DIG8 = 1;
dynamic_step = 6;
break;
case 6: //第七个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 0;LED_DIG8 = 1;
dynamic_step = 7;
break;
case 7: //第八个共阳数码管公共端打开,输入+3.3V电压
LED_DIG1 = 1;LED_DIG2 = 1;LED_DIG3 = 1;LED_DIG4 = 1;
LED_DIG5 = 1;LED_DIG6 = 1;LED_DIG7 = 1;LED_DIG8 = 0;
dynamic_step = 0;
break;
}
LED_A = (display_ca_table[i]>>0) & 0x01;
LED_B = (display_ca_table[i]>>1) & 0x01;
LED_C = (display_ca_table[i]>>2) & 0x01;
LED_D = (display_ca_table[i]>>3) & 0x01;
LED_E = (display_ca_table[i]>>4) & 0x01;
LED_F = (display_ca_table[i]>>5) & 0x01;
LED_G = (display_ca_table[i]>>6) & 0x01;
LED_DP = (display_ca_table[i]>>7) & 0x01;
if(++i > 7) i = 0; //i初值为0,每次加一,判断是否大于7,大于7重新赋初值0
soft_delay(2); //延时一小段时间
}
}
七、数码管动态显示视频讲解
STC8H系列单片机入门教程之数码管动态显示