zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/ToddleLobster/p/5737455.html
Copyright © 2011-2022 走看看