数码管因为发光亮度强,指示作用好,十分适宜于电梯楼层等数值显现使用中。关于一位数码管,能够选用静态显现,但实践使用中都是需求显现多位数值,数码管模块也只能动态显现,因而笔者在这里简略剖析一下数码管动态扫描驱动的完结。
1. 数码管原理概述
数码管由多个发光二极管封装在一同组成“8”字型的器材,引线已在内部衔接完结,只引出它们的各个笔划,公共电极。数码管实践上是由七个发光管组成8字形构成的,加上小数点便是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表明。数码管依据内部接法又可分红共阳极数码管和共阴极数码管。共阳数码管是指将一切发光二极管的阳极接到一同构成公共阳极(COM)的数码管(如下图SM*10501),共阴数码管是指将一切发光二极管的阴极接到一同构成公共阴极(COM)的数码管如下图(SM*20501)。以共阳数码管为例,要想显现数字2,需把A、B、G、E、D段点亮,即公共端接上正电源,ABGED段阴极拉低,其他段拉高即可显现数字2。
2. 硬件规划
笔者此处以四位一体共阳数码管显现为例解说其大约的硬件规划。
微操控器的IO口均不能流过过大的电流,LED点亮时有约10ms的电流,因而数码管的段码输出不要直接接单片机IO口,应先经过一个缓冲器74HC573。单片机IO口只需很小的电流操控74HC573即可直接的操控数码管段的显现,而74HC573输出也能负载约10ms的电流。设置数码管段的驱动电流为ID=15ma,这个电流点亮度好,并且有必定的裕度,即便电源输出电压偏高也不会焚毁LED,限流电阻值R = (VCC- VCE– VOL– VLED) / ID
VCC为5v供电,VCE为三极管C、E间饱满电压,估为0.2v, VOL为74hc573输出低电平时电压,不同灌电流,此值不一样,估为0.2v,详细检查规格书,VLED为红光驱动电压,估为1.7v,依据上式可算出限流电阻为R = 200R。
数码管需接纳逐一扫描信号,扫描到相应数码管时,对应的段码数据有用,即显现这个数码管的数值。笔者选用三线八线译码器74HC138来发生对应的扫描线信号。
当各个段码均点亮时,电流约15max8=90ma流过数码管公共端,74HC138无法直接驱动这个电流,需加三极管驱动,因为74HC138输出低电平有用,此处只要PNP三极管适宜作为驱动。三极管基极电流设为2ma即可让三极管饱满,最大驱动电流远大于90ma。基极偏置电阻阻值
Rb=(VCC- VEB– VOL) / IB
VCC为5v供电,VEB为三极管E、B间的导通电压0.7v,VOL为74hc138输出低电平时电压,可依据规格书估为0.3v,故Rb= 2k即可。
图2-1 四位一体数码管原理图
3. 驱动完结
数码管段码接P0口,位码接P2口第0~2位。关于LED显现器都是有一个改写频率的,相同关于数码码动态扫描也需求一个扫描频率。扫描频率下限为50HZ,低于必定的扫描频率,显现会闪耀。频率过高,则亮度较差且占用cpu资源。一般整个数码管扫描一遍时刻为约10ms较适宜(即扫描频率100HZ),咱们用的是四位数码管,每个数码管点亮时刻为2ms,扫描一遍时刻为8ms。为确保这个改写频率,经过是经过定时器来周期性进行数码管改写。笔者在此以四位一体数码管完结秒表计数显现为例来作代码开发。
数码管动态显现功用完结模块文件DigitalTubeTable.c内容如下:
#include “reg52.h”
#include“DigitalTube.h”
// 数值相对应的段码,共阳极
staTIc unsigned char codeDigitalTubeTable[12]= { // 共阳LED段码表
0xc0, 0xf9, 0xa4, 0xb0, 0x99,0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf
//“0” “1” “2” “3” “4” “5” “6” “7” “8” “9” “不亮” “-”
};
// 每个数码管需一个字节的内存保存对应数码管数据
staTIc unsigned charFrameBuffer[DigitalTubeNumber];
unsigned char*DigitalTube_GetBuffer()
{
return FrameBuffer;
}
void DigitalTube_Scan()
{
staTIc unsigned char Select = 0; // 记载扫描的挑选线
unsigned char Code;
// 从对应挑选线中找到显存数据,并得到相应的段码
Code = DigitalTubeTable[FrameBuffer[Select]];
// 段码实践输出到数码管接口
DigitalTube_Data(Code);
// 位选实践输出到数码管接口
DigitalTube_Select(Select);
Select++; // 进入到下一位选扫描
if (Select 》= DigitalTubeNumber) {
Select = 0; // 一切数码管已扫描,从第一个数码管再次开端扫描
}
}
咱们在数码管模块头文件DigitalTube.h中完结模块的接口拜访宏完结,使之便利移植及修正接口装备。模块头文件一起也引出模块的接口函数,void DigitalTube_Scan(void)为数码管改写函数,需周期性调用改写数码管显现。unsigned char *DigitalTube_GetBuffer(void)用来取得数码管显存,然后更新数码管显存数据。其内容如下:
#ifndef __DigitalTube_H__
#define __DigitalTube_H__
#ifdef __cplusplus
extern “C” {
#endif
// 数码管模块中的个数,最大为8
#define DigitalTubeNumber 4
// 输出数码管位选
#defineDigitalTube_Select(Select) {P2 = (P2&0xf8) + (Select);}
// 输出数码管段码
#define DigitalTube_Data(Dat) {P0 =(Dat);}
// 数码管改写函数,有必要确保以必定周期调用改写
void DigitalTube_Scan(void);
// 取得数码管显存,以作显现的数据更新
unsigned char*DigitalTube_GetBuffer(void);
#ifdef __cplusplus
}
#endif
#endif /*__DigitalTube_H__*/
外部模块经过引进数码管的模块头文件DigitalTube.h来完结调用数码管驱动函数,简略测验调用(秒表数码管显现计数)完结如下:
#include“reg52.h”
#include“DigitalTube.h”
// 以定时器时刻为计时规范,记载时刻距离
staTIc volatile unsignedint SystemTick = 0;
// 定时器2ms中止处理进行数码管改写
void T0_Interrupt()interrupt 1
{
TH0 = (65536-2000) / 256;
TL0 = (65536-2000) % 256;
SystemTick++; // 记载时刻距离
DigitalTube_Scan(); //改写数码管
}
void T0_Init()
{
TMOD = 0x01; // 定时器0工作方式1
// 2ms计时中止(12M)
TH0 = (65536-2000) / 256;
TL0 = (65536-2000) % 256;
ET0 = 1; // 定时器T0中止答应
EA = 1; // 总中止答应
}
void main()
{
unsigned char *pBuffer;
unsigned char i;
// 定时器初始化
T0_Init();
// 取得数码管显存,以作更新数据显现
pBuffer = DigitalTube_GetBuffer();
// 数据管显存初始化显现0
for (i=0; i
pBuffer[i] = 0;
}
// 敞开定时器进行计时以及数码管改写
TR0 = 1;
while(1) {
// SystemTick读数到500时为1s距离到
if (SystemTick 》 500) {
SystemTick =0; // 从头计秒
// 更新数码管秒表计数显存
for (i=0; i
pBuffer[DigitalTubeNumber-1-i]++;
if (pBuffer[DigitalTubeNumber-1-i] 《10) {
break; // 未到10,不必进位更新高位显存,退出
} else {