单片机学习小组
直播中

符筹荣

8年用户 1059经验值
私信 关注

如何用595芯片来驱动LED点阵呢

LED点阵的原理是什么?
如何用595芯片来驱动LED点阵呢?



回帖(1)

刘艳

2022-1-21 13:54:49
LED点阵

点阵原理





  • 我的开发板是 16*16 红绿 双色的LED点阵,但我只用到了红色的,所以我们暂且只看黑色LED,其实只要让LED导通,我们就可以点亮任意一个LED小灯
       
        如要点亮 左上角第一个LED ,只要让 22 置 1 ,23 置 0 就可以让它导通,就亮了
       

  • 如果要让整个点阵按自己的想法显示,比如显示数字汉字啥的,可以用类似于数码管的 动态扫描 想法,我的理解是给 一个 段选 码表,给 一个 位选 码表,让 逐行扫描,配合列看看该行有没有要显示的LED,不好理解等下看程序

点亮一个




  • 下面我们先来点亮第一个LED看看效果

程序


#include


#define LedH P0                //用P0口控制行
#define LedL P1      //用P1口控制列


void main()
{
        while(1)
        {
                LedH=0x01;    //只让第一个LED导通
                LedL=0xfe;
        }
}

显示图形




  • 显示图形可以自己去计算每个点,但是效率太低,这里我们可以用到 取字模软件





  • 就像这样,它会直接把你点亮的地方的段码给你,这样我们就可以直接用了
  • 还有这个软件的一个参数设置,根据不同的编程,参数设置也是不同的


程序


#include


#define LedH P0
#define LedL P1


unsigned char code wei[8]=
{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char code duan[8]=
{0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C};


void main()
{
        unsigned char i;
        while(1)
        {
                for(i=0;i<8;i++)
                {
                        LedL=0xff;                        //消影
                        LedH=duan;               
                        LedL=~wei;                       
                }
        }
}


  • 不知道为什么,我用IO来传输数据时,它显示的有点暗,而用 95芯片 传输时,则不会这样,不知道是不是IO口的驱动能力不足导致的,所以下面我就用 595芯片 来驱动LED点阵

  
HC595芯片


  • 在显示上,为了更节省IO口,更简便,我们可以用 595芯片 ,也可用 138芯片 之类的,而我则用了两个 595芯片,一个用来控制 给它 段选 ,一个来控制 给它 位选 ,这样就节省了两个IO口,同时为了防止产生上面显示太暗的这个弊端

用法


  • 下面我直接给出 595芯片驱动程序吧,要说原理我也不太清楚,要用的直接在这个上面改就行了

#include "STC89C5xRC.H"                         
#include "intrins.h"
#define uchar unsigned char //对数据类型进行声明定义
***it SRCLK = P3^6;        //定义IO口,看开发板的原理图
***it RCLK1 = P3^5;        
***it SER = P3^4;
void HC595(uchar dat1)                        //595芯片驱动程序,,这是传一个,要穿两个可以加一个dat2
{
                uchar a;
                SRCLK = 1;
                RCLK1 = 1;
                for(a=0;a<8;a++)       //发送8位数
                {
                        SER=dat1>>7;       //从最高位开始发送
                        dat1<<=1;
                        SRCLK=0;                                //发送时序
                        _nop_();
                        _nop_();
                        SRCLK=1;
                }
                RCLK1=0;                               
                _nop_();
                _nop_();
                RCLK1=1;
}       

  • 二维数组
    数据类型 数组名[数组长度1][数组长度2];
  • 数组元素的数量可以小于数组元素个数,没有赋值的会自动给0,当数组元素的数量等于数组个数的时候,如下

unsigned char a[2][3] =
{
   {1,2,3}, {4,5,6}
};
或者是
unsigned char a[2][3] =
{1,2,3,4,5,6};


  • 当数组元素的数量小于数组个数的时候,如下所示:

  unsigned char a[2][3] =
{
   {1,2}, {3,4}
};
等价于
unsigned char a[2][3] =
{1,2,0,3,4,0};
反过来
unsigned char a[2][3] =
{1,2,3,4};
等价于
unsigned char a[2][3] =
{
   {1,2,3}, {4,0,0}
};
  
最终程序

#include
#include "intrins.h"
#define uchar unsigned char




uchar code imagewei[8]=
{
        0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
};


uchar code imageduan[11][8]=
{
        {0x00,0x00,0x44,0x92,0x92,0x92,0x6C,0x00}, //3
        {0x00,0x00,0xE4,0xA2,0xA2,0xA2,0x9C,0x00}, //2
        {0x00,0x00,0x88,0x84,0xFE,0x80,0x80,0x00}, //1
        {0x00,0xC3,0xC3,0xFF,0xFF,0xC3,0xC3,0x00}, //i
        {0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C}, //心
        {0x00,0x7F,0xFF,0xC0,0xC0,0xFF,0x7F,0x00}, //u


        {0x00,0x18,0x3C,0x78,0x78,0x3C,0x18,0x00},  //小心
        {0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C},  //中心
        {0x3E,0x7F,0xFF,0xFE,0xFE,0xFF,0x7F,0x3E},        //大               
//        {0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C},  //中心
        {0x00,0x18,0x3C,0x78,0x78,0x3C,0x18,0x00},  //缩小       
        {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},  //全灭
       
};


***it SRCLK = P3^6;
***it RCLK1 = P3^5;
***it SER = P3^4;


void HC595(uchar dat1,uchar dat2)                        //595芯片驱动程序,直接拿上面的来用,修改一下
{
        uchar a;
        SRCLK = 1;
        RCLK1 = 1;
        for(a=0;a<8;a++)
        {
                SER=dat1>>7;
                dat1<<=1;
                SRCLK=0;                               
                _nop_();
                _nop_();
                SRCLK=1;
        }
        for(a=0;a<8;a++)                //传输的第二个数据
        {
                SER=dat2>>7;
                dat2<<=1;
                SRCLK=0;                               
                _nop_();
                _nop_();
                SRCLK=1;
        }
        RCLK1=0;                               
        _nop_();
        _nop_();
        RCLK1=1;
}       


void main()   
{
        int k,x,y;
        uchar j;
        uchar i;
        y=0;
        while(1)
        {
                if(j<6)
                        {x=200;}                        //让前面321倒计时切换慢点
                else
                        {x=60;}                        //让后面心跳快点
                for(k=0;k                 {
                        for(i=0;i<8;i++)                                        //扫描
                        {
                                HC595(~imagewei,imageduan[j]);       
                        }               
                }
                j++;
                if(j==11)                //单独循环7次后面的心跳
                {       
                        j=7;
                        y++;
                }
                if(y==7)                        //单独循环完后重新开始
                {
                        j=0;
                        y=0;
                }
        }
}
最终效果展示

啦~最终效果就完成啦
是不是看起来还可以,工科直男也有浪漫的好吧,我们不需要什么玫瑰花,不需要什么礼物,我们玩的高科技,玩的是技术,不开玩笑了,收工~


  • 我本来想的在加一个定时器中断蜂鸣器来模拟心跳的声音的,但是这个不知道怎么上传视频,就懒得弄了
举报

更多回帖

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