zoukankan      html  css  js  c++  java
  • STC89C52控制74HC595,74HC138双色16x16点阵屏循环显示汉字

    简介

    常见的LED点阵除了使用MAX7219, 还有一部分是使用74HC595, 前者能主动刷新, 后者需要上位机主动扫描刷新.

    手里这块是德飞莱的16x16LED点阵模块, 板上印的型号LY-LED16x16B V2.0, 这个型号有两种配置, 单色或者双色. 双色多一个IO口用于控制另一个颜色. 下图是板子背面, 这个是单色的配置, 有几个焊盘是空的, 8x8LED的引脚也有部分是空的.

    运行机制

    LED点阵的显示主要是通过74HC595和74HC138这两个逻辑芯片

    74HC138 译码器/decoder

    74HC138接受3位二进制地址输入(A0, A1, A2), 当使能时提供8个互斥的低有效输出(Y0至Y7). 在这个模块中, 74HC138负责行扫描, 每次扫描其中一行, 行的位置由ABCD这4个脚控制, 对应了两片74HC138, 每片控制8个行, 通过P0.0-P0.3, 可以对指定的行拉低电平.

    通信方式是直接通过IO高低电平控制.

    74HC595 8位移位寄存器输出锁存器

    74HC595是一个串行输入, 并行输出的移位寄存器, 包含一个串行移位输入(Ds), 一个串行移位输出(Q7’), 一个异步的低电平复位; 存储寄存器有一个8位的并行的具备三态的总线输出, 当使能OE时(低电平使能), 存储寄存器的数据输出到总线.

    在这个模块中, 74HC595负责准备当前行上的数据, 这个数据有 16 bit, 对应 2 byte, 对应每个汉字, 有16x16个点, 就是16个 16 bit, 每次扫描时, 配合74HC138将正在扫描的那行的2个字节内容送到总线上去, 同样是两片74HC595, 每片负责8个bit.

    通信方式是SPI, 串行输入-锁存-并行输出的方式

    上位机代码

    STC89C52RC

    连接方式

    R1        => P2.4 红色数据信号
    D         => P0.3
    C         => P0.2
    B         => P0.1
    A         => P0.0 A-D用于控制16行,通过2路 HC138 控制
    LATCH     => P2.6 锁存
    SCK       => P2.5 时钟
    G1        => P0.4 绿色数据信号, 如果使用单红色屏此信号无需连接
    OE        => P2.1 可以用IO引脚PWM控制亮度, 或者使用此引脚控制拖尾现象
    +5V       => 5V
    GND       => GND
    

    代码

    #include<reg52.h>
    
    sbit G1    = P0^4;       //数据引脚,屏上标识G1
    sbit OE    = P2^1;       //使能引脚,屏上标识EN/OE
    sbit R1    = P2^4;       //数据引脚,屏上标识R1
    sbit T_CLK = P2^5;       //时钟引脚,屏上标识CLK
    sbit T_STR = P2^6;       //锁存引脚,屏上标识LATCH
    
    unsigned char pos=0;
    
    unsigned char tab[8];
    unsigned char DIS[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//行数据
    
    /*-----------------------------------------------
                 16x16汉字取模数据
    ------------------------------------------------*/
    unsigned char code hztest[][32]=    //二维数组, 每个汉字32个字节
    {
    /*--  文字:  电  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00,0x01,0x00,0x01,0x00,0x01,0xF8,0x3F,0x08,0x21,0x08,0x21,0x08,0x21,0xF8,0x3F,
    0x08,0x21,0x08,0x21,0x08,0x21,0xF8,0x3F,0x0A,0x21,0x02,0x01,0x02,0x01,0xFE,0x00,
    
    /*--  文字:  子  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00,0x00,0xF8,0x7F,0x10,0x00,0x20,0x00,0x40,0x00,0x80,0x01,0x00,0x01,0xFE,0xFF,
    0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,
    
    /*--  文字:  工  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00,0x00,0x00,0x00,0xFC,0x7F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
    0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFE,0xFF,0x00,0x00,0x00,0x00,
    
    /*--  文字:  程  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00,0x08,0xFC,0x1D,0x04,0xF1,0x04,0x11,0x04,0x11,0xFC,0xFD,0x00,0x10,0x00,0x30,
    0xFE,0x39,0x20,0x54,0x20,0x54,0xFC,0x91,0x20,0x10,0x20,0x10,0xFE,0x13,0x00,0x10,
    
    /*--  文字:  信  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x40,0x08,0x20,0x08,0xFE,0x0B,0x00,0x10,0x00,0x10,0xFC,0x31,0x00,0x30,0x00,0x50,
    0xFC,0x91,0x00,0x10,0x00,0x10,0xFC,0x11,0x04,0x11,0x04,0x11,0xFC,0x11,0x04,0x11,
    
    /*--  文字:  息  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00,0x01,0x00,0x02,0xF0,0x1F,0x10,0x10,0xF0,0x1F,0x10,0x10,0xF0,0x1F,0x10,0x10,
    0xF0,0x1F,0x10,0x10,0x00,0x01,0x84,0x08,0x92,0x48,0x12,0x48,0xF0,0x87,0x00,0x00,
    
    /*--  文字:  科  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x10,0x08,0x10,0x1D,0x90,0xF0,0x90,0x10,0x10,0x10,0x10,0xFD,0x90,0x10,0x90,0x38,
    0x10,0x34,0x1E,0x50,0xF0,0x53,0x10,0x90,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
    
    /*--  文字:  学  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x08,0x22,0x08,0x11,0x10,0x11,0x20,0x00,0xFE,0x7F,0x02,0x40,0x04,0x80,0xE0,0x1F,
    0x40,0x00,0x80,0x01,0xFE,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,
    
    
    };
    
    /*-----------------------------------------------
                 向595写入一个字节, 红色
    ------------------------------------------------*/
    void InputByte(unsigned  char dat)
    {
      unsigned char i;
      for(i = 8; i > 0; i--)
      {
        R1 = !(dat & 0x01);
        T_CLK = 0;
        T_CLK = 1;
        dat = dat >> 1;
      }
    }
    
    /*-----------------------------------------------
                 向595写入一个字节, 绿色
    ------------------------------------------------*/
    void InputByteG(unsigned  char dat)
    {
      unsigned  char i;
      for(i = 8; i > 0; i--)
      {
        G1 = !(dat & 0x01);
        T_CLK = 0;
        T_CLK = 1;
        dat = dat >> 1;
      }
    }
    
    /*-----------------------------------------------
                 向595写入两个字节 双色
    ------------------------------------------------*/
    void Input2Byte(unsigned  char DataR1, unsigned  char DataG1) //写一个字节
    {
      unsigned  char i;
      for(i=8; i>0; i--)
      {
        R1 = !(DataR1&0x01);
        G1 = !(DataG1&0x01);
        T_CLK = 0;
        T_CLK = 1;
        DataR1 = DataR1 >> 1;
        DataG1 = DataG1 >> 1;
      }
    }
    
    /*-----------------------------------------------
                初始化定时器,做为动态扫描
    ------------------------------------------------*/
    void Init_Timer1(void)
    {
      TMOD |= 0x10;                             
      EA=1;                      //总中断使能
      ET1=1;                     //定时中断使能
      TR1=1;                     //打开定时器开关
    }
    
    /*-----------------------------------------------
                          主程序
    ------------------------------------------------*/
    main()
    {
      unsigned int i;
      unsigned char a;
      Init_Timer1(); //初始化定时器
    
      while(1)
      {
        for(i = 0; i < 1000; i++); // 延时
        a++;
        if(a == 8) a = 0; // 汉字循环
        pos = a;
      }
    }
    
    /*-----------------------------------------------
                 定时器执行动态扫描
    ------------------------------------------------*/
    void Timer1_isr(void) interrupt 3
    {
      static unsigned char count, j;
      unsigned char i;
      TH1=0xff;                // 重装初值
      TL1=0;
    
      T_STR=0;    // 锁存释放
      for(j = 0; j < 1; j++) //取当前汉字在i位置的2个字节,数据传输完成后锁存输出
            {
        InputByte(hztest[j+pos][i]);
        InputByte(hztest[j+pos][i+1]);
            }
      OE = 1;    // 关闭屏幕, 如果没有使用该引脚控制则会出现拖影现象
      T_STR=1;   // 锁存有效, 此时一行的数据显示到屏上
    
      P0 = DIS[count] | 0xF0; //低4位对应P0.0-P0.3, 通过HC138 4-16译码器, 循环扫描其他15行
      OE = 0;    // 打开屏幕
      count++;
    
      i += 2;    // 当前汉字下一位置
      if(count == 16) count = 0;
      if(i == 32) i = 0;
    }
    
  • 相关阅读:
    迅为4412开发板实验Menuconfig_Kconfig(上)
    迅为IMX6ULL开发板Linux 4G通信实验
    迅为IMX6ULL开发板Linux RS232/485驱动实验(下)
    迅为4412开发板实验_Makefile编译(下)
    迅为IMX6Q开发板QtE5.7编译(上)
    迅为干货 | iTOP-4418/6818移植mt6620热点
    UDT源码剖析(十一)之SendQueue And RecvQueue
    UDT源码剖析(九)之CCC
    UDT源码剖析(十)之Channel
    UDT源码剖析(八)之Cache
  • 原文地址:https://www.cnblogs.com/milton/p/15201472.html
Copyright © 2011-2022 走看看