• 4个74HC595级联控制16x16点阵横向滚动带仿真(一)


    前言:

      淘宝买了个51开发板学习用,其16*16点阵屏是4个74HC595级联控制,这种方式方便更改行、列刷新模式,但每显示一行或一列时都有32bit数据串行输入再一起并行输出,速度较慢,容易产生闪烁感。而且配套教程太垃圾,。。太多槽点就不吐槽了,全靠自力更生,新手初学,个中辛苦就不谈了。

      教程没有横向滚动的例程,于是自己写了一个,记录一下。也画了个Protues的原理图,供没有这款开发板的朋友研究。

      软件环境:Keil uvsion 4, Protues 7.8

      本例采用列扫描模式,只实现了向左滚动。需要向右滚动的朋友请自行更改或参见

      《4个74HC595级联控制16x16点阵横向滚动带仿真(二)》。


    原理图:

    DSN文件下载地址链接

    代码:

    /**
     **********************************************************
     ******     Copyright(C), 2010-2016, 吐泡泡的虾       ******
     **********************************************************
    
     *@Tittle        :    16x16点阵滚动显示汉字——横向滚动
     *@Version       :    v1.0
     *@Author        :    吐泡泡的虾
     *@Dat           :    2016-08-04 14:23:59
     *@Desctription  :    16x16点阵采用4个74HC595移位寄存器控制,
     *                    4个移位寄存器采用串联方式。
     *                    本例采用列刷新模式。
     *                    取模方式:纵向取模,字节不倒序。
     *                注意:
     *                    由于采用4个595级联方式,输入数据速度太慢,
     *                    导致闪烁感较强。可改用6T或1T模式,改善很多。
     *@History       :
     *
     *
     **********************************************************
     **********************************************************
     */
    
    
    #include <reg52.h>
    #include <intrins.h>
    
    
    #define uchar unsigned char
    #define uint unsigned int
    
    
    sbit DS_595 = P3 ^ 4;        //P3^4: 595的数据输入管脚
    sbit SHCP_595 = P3 ^ 6;        //P3^6: 595的移位寄存器时钟管脚 SCK
    sbit STCP_595 = P3 ^ 5;        //P3^5: 595的输出寄存器时钟管脚 RCK
    // sbit MR_595 = P2 ^ 3;    //P0^3: 595的输出输出寄存器重置管脚 MR
    
    void InputTo595(uchar *displayBuff, uchar len);
    void OutputFrom595();
    void Init_IO();
    void DelayX10us(uchar multi);
    
    //列扫描模式下的列序号,两两一组。如0x80, 0x00为点亮第一列,0x40, 0x00为第二列
    uchar code COL_CODE[] = {
        0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00,
        0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01,
    };
    
    
    //要显示的字符。开头和末尾均留1个空白字符,以显示滚入、滚出效果
    uchar code words[] =
    {
    
        /*--  起始空白,滚入效果,可去掉  --*/
        /*--  宽度x高度=16x16  --*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    
        /*--  文字:  售  --*/
        /*--  Trebuchet MS12;  此字体下对应的点阵为:宽x高=16x16   --*/
        0x04, 0x08, 0x10, 0x3F, 0xEA, 0x2A, 0x2A, 0xAA, 0x7F, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x00, 0x00,
        0x00, 0x00, 0x00, 0xDF, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x9F, 0x80, 0x00, 0x00,
    
        /*--  文字:  后  --*/
        /*--  Trebuchet MS12;  此字体下对应的点阵为:宽x高=16x16   --*/
        0x00, 0x00, 0x00, 0x3F, 0x24, 0x24, 0x24, 0x24, 0x44, 0x44, 0x44, 0xC4, 0x44, 0x04, 0x04, 0x00,
        0x02, 0x04, 0x18, 0xE0, 0x00, 0x7F, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7F, 0x00, 0x00, 0x00,
    
        /*--  文字:  真  --*/
        /*--  Trebuchet MS12;  此字体下对应的点阵为:宽x高=16x16   --*/
        0x00, 0x20, 0x20, 0x2F, 0x2A, 0x2A, 0x2A, 0xFA, 0x2A, 0x2A, 0x2A, 0x2F, 0x20, 0x20, 0x00, 0x00,
        0x08, 0x08, 0x09, 0xFA, 0xAC, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xAC, 0xFA, 0x09, 0x08, 0x08, 0x00,
    
        /*--  文字:  烂  --*/
        /*--  Trebuchet MS12;  此字体下对应的点阵为:宽x高=16x16   --*/
        0x01, 0x0E, 0x00, 0xFF, 0x08, 0x10, 0x04, 0x44, 0x34, 0x04, 0x04, 0x14, 0x64, 0x04, 0x04, 0x00,
        0x01, 0x06, 0x18, 0xE0, 0x10, 0x08, 0x02, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x02, 0x00,
    
        /*--  末尾空白,必须,否则有乱码  --*/
        /*--  宽度x高度=16x16  --*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };
    
    
    
    void main()
    {
        uint i, j = 0, k;
        uchar X10us = 1;
        uchar displayBuff[4];    //显示缓存
    
        Init_IO();
    
        while (1)
        {
            k = 4;    //每屏重复刷新次数,滚动速度调节。
            while (--k)
            {
                //依次显示16列,即显示完一屏
                for (i = 0; i < 16; i++)
                {
                    // //程序测试块,用以确定缓存数组元素对应的行或列
                    // displayBuff[0] = 0x82;        /*0b10000010 上8行,上为高位*/
                    // displayBuff[1] = 0x44;        /*0b01000100 下8行,上为高位*/
                    // displayBuff[2] = ~0x80;        /*0b10000000 左8列,左为高位*/
                    // displayBuff[3] = ~0x03;        /*0b00000011 右8列,左为高位*/
    
                    displayBuff[0] = *(words + (j + i) % 16 + (j + i) / 16 * 32 );    //每一列对应的上8行码值
                    displayBuff[1] = *(words + (j + i) % 16 + (j + i) / 16 * 32 + 16);    //每一列对应的下8行码值
    
                    displayBuff[2] = ~ COL_CODE[2 * i];    //左8列码值,左为高位
                    displayBuff[3] = ~ COL_CODE[2 * i + 1];    //右8列码值,左为高位
    
                    InputTo595(displayBuff, 4);
                    _nop_();
                    OutputFrom595();
                    // DelayX10us(X10us);//当前列显示时间延时,会引起闪烁感
                }
            }
    
            //达到边界后j清0,以便循环显示
            //必须用works总字符数-1,不减1的话displayBuff[0]和[1]就出边界了
            if (++j == (sizeof(words) / sizeof(words[0]) / 32 - 1) * 16)
                j = 0;
    
        }
    }
    
    /**
     * 将displayBuff数组输入级联的595芯片,最后一个元素先输入,从低位到高位顺序输入
     * @param displayBuff 输入数组地址
     * @param len      要输入的数组元素个数,从数组第一个元素开始计
     */
    void InputTo595(uchar *displayBuff, uchar len)
    {
        uchar i, j;
    
        for (j = len; j > 0; j--)
        {
            for (i = 0; i < 8; i++)
            {
                DS_595 = displayBuff[j - 1] & 0x01 ;    //先输入最低位
                displayBuff[j - 1] >>= 1;
    
                SHCP_595 = 0;
                _nop_();
                SHCP_595 = 1;    //上升沿,输入到移位寄存器
            }
    
        }
    }
    
    void OutputFrom595()    //595输出
    {
        STCP_595 = 0;
        _nop_();
        STCP_595 = 1;
        STCP_595 = 0;
    }
    
    void Init_IO()
    {
        P3 = 0x0;
    }
    
    //延时10us的倍数,误差5us
    void DelayX10us(uchar multi)
    {
        do
        {
            _nop_(); _nop_(); _nop_(); _nop_();
            _nop_(); _nop_(); _nop_(); _nop_();
        } while (--multi);
    }
    View Code

     欢迎关注本人的个人博客YoungCoding.top

  • 相关阅读:
    Unreal Engine 4官网教程
    快速上手制作暗黑类游戏动作打击感的一些要点
    充分利用 UE4 中的噪声
    综合帖:多角度闲聊游戏打击感
    鹅厂内部分享:七步教你从无到有做数值
    二叉树、二叉搜索树、平衡二叉树、B树、B+树的精确定义和区别探究
    MySQL的InnoDB索引原理详解
    分布式核心
    Mysql 原理以及常见mysql 索引等
    redis核心原理
  • 原文地址:https://www.cnblogs.com/ToddleLobster/p/5737455.html
Copyright © 2020-2023  润新知