单片机交流
直播中

张杰

7年用户 1231经验值
私信 关注
[问答]

如何利用74HC245来实现数码管的亮灭?

如何利用51单片机点亮LED灯?
如何利用74HC245来实现数码管的亮灭?

回帖(1)

李可熠

2021-11-3 10:15:17
以下是我所用单片机的原理图





这块51单片机一共有4个I/O口(意思为input/output),也代表着如果我们后续都要用到这四个的话那么功能会比较单一,所以单片机上会有很多模块,如74HC245可以用来控制数码管,减轻单片机核心上的负担。





这是LED模块,VCC代表高电位+5V,所以说想让这LED发光,就要在另一端接低电位0V。
在图中我们可以看到可以把LED右端的接口与核心上的P2端相接,一一对应。

LED的点亮与流水灯
1.先来说一下如何点亮LED灯


#include "reg52.h"//调用52单片机的头文件,写51也可以//
***it LED=P2^0;//***it 是用来确定地址,这里是把LED定义为P2的0号接口//
void main()
{
        LED=0;//代表着P2口出低电位使发光二极管前后产生电位差而发光//
}


所以以此类推我们可以使开发板上的多个发光二极管点亮,但是如果一个一个接口定义过去会比较麻烦,所以我们可以对整个P2口进行操作。


#include "reg52.h"
#define LED P2
void main()
{
        LED=0;
}       


这样就能实现LED灯全部点亮。
那么我们要如何使LED灯实现流水灯的样子呢?


流水灯实现
首先我们要知道8个LED灯每一个灯都代表二进制位上的一位,也就是说8个灯在一开始都为1111 1111(顺序从LED1到8),这样两边高电位所以不会亮,我们把他写为十六进制数为0xff(0x是为了告诉电脑这是16进制)
所以我们想要把灯点亮,就可以把各个位置变为0出低电位,这样就可以实现点亮LED灯。
那么我们要怎么样才能使LED灯逐个点亮呢?
我们可以用到C语言中的"<<“与”>>"来实现位的左移右移。也就是说我们可以这样写


#include "reg52.h"
#define LED P2
#define ui unsigned int
#define uc unsigned char




void delayms(ui del) //延时语句,延时时长为(del*10)ms       
{
        ui i,j;
        for(i=0; i         for(j=0; j<1827; j++)  ;
}
       
void main(){
        int i;
       
        while(1){
        for(i=1;i<8;i++){
        LED=(0xff<         delayms(15);//此处延时是为了展现视觉效果,不延时会太快人眼看不出流水效果
                }
        }       
}


但这样的流水灯又有点单调了,我们还可以实现使流水灯从左到右再从右到左,只需要在while里在写一个右移即可,代码如下:


#include "reg52.h"
#define LED P2
#define ui unsigned int
#define uc unsigned char




void delayms(ui del)        
{
        ui i,j;
        for(i=0; i         for(j=0; j<1827; j++)  ;
}
       
void main(){
        int i;
       
        while(1){


        for(i=1;i<8;i++){
        LED=(0xff<         delayms(15);
        }
        LED=0x00;//让所有灯熄灭准备待会反着来亮
        delayms(10);//这就是待会……
         for(i=1;i<8;i++){
        LED=(0xff>>i);//右移!
        delayms(15);
        }       
}
}


数码管的显示

原理图展示






这是一个八位数码管原理图,我们可以看到这个动态数码管可以靠74HC245来实现亮灭。
这里先介绍一下什么叫位选和段选:
位选是控制每一位数码管的控制信号线。
段选是控制一位数码管上8个发光管(段)的亮灭控制信号线。
位选决定着一位数码管是否显示内容。
段选决定着每一个段(发光管)的亮灭。一位数码管就相当于8个LED灯,数码管分为共阴极和共阳极型,共阴极型的,段选为1时段点亮;共阳极型的,段选为0时点亮。
下图左为共阴,左(2)图共阳。






而右图abcdefg对应各个发光管的引脚依次顺序展现为二进制数,a对应20,b对应21 ,以此类推出完整的二进制数再转换为16进制数。另外图中dp为小数点。以下为最简单的让数码管显示一个’0’的代码:


#include
void main()
{
        P0=0X3F;//显示字符‘0’
}


但我们想要实现让数码管多个显示数字该怎么办?为了方便我先定义一个共阴数码管的数组其中包含了0~9数字的十六位进制码。


uc code gmoon[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uc code gsun[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};


这样就方便我们来采集所需要的数字。
让多个数码管显示称为动态显示,其实就是多个数码管,不断交替显示,通过极短的延时利用人的视觉暂停作用,使人看到多个数码管同时显示的效果。在这之中我要先来说一下位选和段选。



首先看到这个74HC245的说明:





其中L代表LOW低电位,H代表HIGH高电位,D就是输入,而Q则是输出,X代表任意一个电位,Q0表示保持原先状态。从中我们可以看到,保存原先状态就是能把之前输入的保存下来也就是说【锁存】。只要先将段选打开(段选=1)来输入所要数字的十六进制,再关闭段选(段选=0)就能够使其锁存住。
我的这块开发板上使用的是74HC138来控制位选也就是接在P22 P23 P24口上




这里在放一张这个芯片的真值表:





A0 A1 A2接口分别对应上述P22 P23 P24,在这之中的第四行开始我们就能得出一个规律,L看做0 H看做1的话,那么A0 A1 A2所一一对应的二进制,整合起来的值就是右边Y哪一个口出低电位的位置。
通过以上所述就可以来进行动态显示,代码如下:

#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
***it LSA = P2^2;
***it LSB = P2^3;
***it LSC = P2^4;
u8 code smgduan[16]= {0x3f, 0x06, 0x5b, 0x4f,
                    0x66, 0x6d, 0x7d, 0x07,
                                        0x7f, 0x6f, 0x77, 0x7c,
                                        0x39, 0x5e, 0x79, 0x71}; //0~F数码
void delay(u16 i) //延时函数
{
    while(i--);
}
       
void DigDisplay() //数码管显示函数
{
        u8 i;
        for(i=0;i<8;i++)
        {
          switch(i)
          {
                case 0:
                          LSC = 0;LSB = 0;LSA = 0;break; //显示第1个数码管
                case 1:
                          LSC = 0;LSB = 0;LSA = 1;break; //显示第2个数码管
                case 2:
                         LSC = 0;LSB = 1;LSA = 0;break; //显示第3个数码管
                case 3:
                        LSC = 0;LSB = 1;LSA = 1;break; //显示第4个数码管
                case 4:
                        LSC = 1;LSB = 0;LSA = 0;break; //显示第5个数码管
                case 5:
                          LSC = 1;LSB = 0;LSA = 1;break; //显示第6个数码管
                case 6:
                          LSC = 1;LSB = 1;LSA = 0;break; //显示第7个数码管
                case 7:
                         LSC = 1;LSB = 1;LSA = 1;break; //显示第8个数码管
          }
          P0 = smgduan[i+1];//显示1~8的数值
          delay(100); //延时,造成视觉暂留现象
          P0 = 0x00; //数码管消隐
        }
}       

void main()
{
   while(1)
   {
   DigDisplay();
   }
}
这样就能实现八位数码管显示1~8。
还有更多效果实现,让管子出现各种样式!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分