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

废话

  续上篇

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

  将横向滚动的程序分享给QQ群里后,群内的晚秋兄弟提出了另一种思路——采用行扫描、移位方式做滚动,于是熬夜将其实现了一下。仿真程序还是跟前篇一样,不再赘述。


效果预览

  


代码

/**
 **********************************************************
 ******       Copyright(C), 2010-2016,吐泡泡的虾           ******
 **********************************************************

 *@Tittle                :    16x16点阵滚动显示汉字——横向滚动 移位方式
 *@Version        :    v1.0
 *@Author        :    吐泡泡的虾
 *@Dat            :    2016-08-05 01:11:28
 *@Desctription    :    16x16点阵采用4个74HC595移位寄存器控制,
 *                    4个移位寄存器采用串联方式。
 *                    本例采用行刷新模式。
 *                    取模方式:横向取模,字节不倒序。
 *                    适用于普中开发板。
 *                    为尽量减少RAM占用,未用buff[32]缓存满屏
 *                    显存的方式来存储要显示的文字码值,而采用
 *                    3个基准指针和3个缓存字节循环赋值的方式
 *                注意:
 *                    由于采用4个595级联方式,输入数据速度太慢,
 *                    导致闪烁感较强。可改用6T模式,改善很多。
 *
 *                     更改k值可以更改滚动速度。
 *                     更改延时也可以更改滚动速度,但注意可能引
 *                     起闪烁。
 *@History        :
     #v1.0    [Press F5 to insert time]
         1. some comment

 **********************************************************
 **********************************************************
 */

#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 DelayX10us(uchar multi);

//行扫描模式下的行序号,两两一组。如0x80, 0x00为点亮第一行,0x40, 0x00为第二行
uchar code ROW_NUM[] = {
    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,

//=======================================文字内容替换区============================================
    /*--  文字:  ☆  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x04, 0x40, 0xFC, 0x7E, 0x40, 0x04,
    0x30, 0x18, 0x08, 0x20, 0x08, 0x20, 0x11, 0x90, 0x16, 0x50, 0x18, 0x30, 0x20, 0x08, 0x00, 0x00,

    /*--  文字:  左  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFF, 0xFE, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00,
    0x0F, 0xF8, 0x10, 0x80, 0x10, 0x80, 0x20, 0x80, 0x40, 0x80, 0x80, 0x80, 0x3F, 0xFE, 0x00, 0x00,

    /*--  文字:  右  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFF, 0xFE, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
    0x1F, 0xF8, 0x28, 0x08, 0x48, 0x08, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0F, 0xF8, 0x08, 0x08,

    /*--  文字:  滚  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00, 0x80, 0x20, 0x40, 0x17, 0xFC, 0x11, 0x10, 0x82, 0x48, 0x44, 0x84, 0x41, 0x20, 0x13, 0xF0,
    0x10, 0x10, 0x20, 0x88, 0xE1, 0x50, 0x23, 0x20, 0x25, 0x10, 0x29, 0x48, 0x21, 0x86, 0x01, 0x00,

    /*--  文字:  动  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x00, 0x40, 0x00, 0x40, 0x7C, 0x40, 0x00, 0x40, 0x01, 0xFC, 0x00, 0x44, 0xFE, 0x44, 0x20, 0x44,
    0x20, 0x44, 0x20, 0x84, 0x48, 0x84, 0x44, 0x84, 0xFD, 0x04, 0x45, 0x04, 0x02, 0x28, 0x04, 0x10,

    /*--  文字:  ★  --*/
    /*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
    0x01, 0x00, 0x01, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0xC0, 0xFF, 0xFE, 0x7F, 0xFC,
    0x3F, 0xF8, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xF0, 0x1E, 0xF0, 0x18, 0x30, 0x20, 0x08, 0x00, 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, rollSpeed;
    bit mode = 0;
    uchar num = 0;
    //显示缓存,用来存储输入到4个595中的数据。
    //displayBuff[0]:0# 595,控制上8行,上为高位
    //displayBuff[1]:1# 595,控制下8行,上为高位
    //displayBuff[2]:2# 595,控制左8列,左为高位
    //displayBuff[3]:3# 595,控制右8列,左为高位
    uchar displayBuff[4];

    bit moveLeft = 1;    //移动方向,1——左移,0——右移

    uchar* basePtr[3];    //每8次移位之前的第一行的3个半边字符(即正在显示的左半、正在显示的右半、即将显示的另一半)的基准指针,其他行码值在此基础上偏移
    uchar temp[3];        //用来存储三个半边字符的某一行的码值
    uchar cache[2];        //中间变量,可不要
    uchar wordsCount = sizeof(words) / sizeof(words[0]) / 32;    //汉字总数

    while (1)
    {
        //获取每8次移位前的第一行的基准指针地址
        if (mode == 0)    //模式0,左右半屏显示同一个字,basePtr[2]指向下一个即将显示的字的左半(左滚时)或右半(右滚时)的首行
        {
            basePtr[0] = words + (num)  * 32 + (moveLeft ? 0 : 1);
            basePtr[1] = words + (num)  * 32 +  (moveLeft ? 1 : 0);
            basePtr[2] = words + (num + 1) % wordsCount * 32 + (moveLeft ? 0 : 1);    //取余是为了显示到最后一个字时,temp[2]等于首字的左半
        }
        else//模式1,(左滚时)左半屏显示上一个字的右半,右半屏显示下一个字的左半
            //(右滚时)右半屏显示上一个字的左半,左半屏显示下一个字的右半
            //basePtr[1][2]指向下一个即将显示的两个半边字符码地址的首行
        {
            basePtr[0] = words + (num)  * 32 +  (moveLeft ? 1 : 0);
            basePtr[1] = words + (num + 1) % wordsCount * 32 + (moveLeft ? 0 : 1);    //取余是显示最后一个字右半时,temp[1]等于首字的左半
            basePtr[2] = words + (num + 1) % wordsCount * 32 +  (moveLeft ? 1 : 0); //取余是显示最后一个字右半时,temp[1]等于首字的右半
        }

        for (j = 0; j < 8; j++)
        {
            rollSpeed = 1;    //滚动速度调节
            while (rollSpeed--)
            {
                //依次显示16列,即显示完一屏
                for (i = 0; i < 16; i++)
                {
                    //移位操作涉及的3个半边字符,往移动方向最先移除屏幕的定义为序号[0]
                    //根据ptr计算,可得左移时,temp[0][1][2]分别对应前左<-前右<-后左或前右<-后左-<后右
                    //右移时,temp[2][1][0]分别对应后右->前左->前右或后左->后右->前左
                    temp[0] = *(basePtr[0] + 2 * i);
                    temp[1] = *(basePtr[1] + 2 * i);
                    temp[2] = *(basePtr[2] + 2 * i);

                    if (moveLeft)//左移
                    {
                        cache[0] = temp[0] << j | temp[1] >> (8 - j);
                        cache[1] = temp[1] << j | temp[2] >> (8 - j);
                    }
                    else
                    {
                        cache[0] = temp[1] >> j | temp[2] << (8 - j);
                        cache[1] = temp[0] >> j | temp[1] << (8 - j);
                    }

                    displayBuff[0] =  ROW_NUM[2 * i];        //上8行码值,上为高位
                    displayBuff[1] =  ROW_NUM[2 * i + 1];    //下8行码值,上为高位
                    displayBuff[2] = ~cache[0];                //每一行对应的左8列码值,左为高位
                    displayBuff[3] = ~cache[1];                //每一行对应的右8列码值,左为高位

                    InputTo595(displayBuff, 4);
                    _nop_();
                    OutputFrom595();
                    DelayX10us(5);//显示时间延时,太长会引起闪烁感
                }
            }
        }

        mode = ~mode;    //移位8次后模式反转,下一半汉字第一行码值的地址即将存到基准指针

        if (mode == 0) num++; //mode再次为0时,即屏幕已显示到下一个字
        if (num == wordsCount)
        {
            num = 0;
            moveLeft = ~moveLeft;    //反向滚动
        }
    }

}

/**
 * 将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;
}

//延时10us的倍数,误差5us
void DelayX10us(uchar multi)
{
    do
    {
        _nop_(); _nop_(); _nop_(); _nop_();
        _nop_(); _nop_(); _nop_(); _nop_();
    } while (--multi);
}
        

时间: 2024-11-03 20:49:45

4个74HC595级联控制16x16点阵横向滚动带仿真(二)的相关文章

4个74HC595级联控制16x16点阵横向滚动

废话: 淘宝买的51开发板16*16点阵屏是4个74HC595级联控制,这样方便更改行.列刷新模式,但速度较慢,容易产生闪烁感.而且配套教程太垃圾,..太多槽点就不吐槽了,全靠自力更生,新手初学,个中辛苦就不谈了. 教程没有横向滚动的例程,于是自己写了一个,记录一下.也画了个Protues的原理图,供没有这款开发板的朋友研究. 原理图: DSN文件下载地址链接: http://pan.baidu.com/s/1qYzTOHQ 密码: j4yh 代码: /** ******************

李洪强实现横向滚动的View&lt;二&gt;

上一节中我们已经实现了一个带有图片,标题和价格label 的UIView 这节我们用这个view实现一个横向滚动的UIcollectionView 实现的效果如下:  01 - 创建CFTyreScrollViewCell,继承自UICollectionViewCell

ListView的下拉刷新上拉加载以及带列的横向滚动

相信有很人做的项目估计都用的到这个.就是ListView的下拉刷新上拉加载还有就是列的横向滚动; PS:横向滚动带表头与固定列(相信蛮多人都有这样的需求吧?就是在ListView上支持很多列,然而设备屏幕宽度有限) PS:这是我个人在网上找的两个示例demo结合而成的一个示例demo,还可以继续拓展,后续有时间就会更新,大家互相学习 ListView下拉刷新上拉加载示例demo原文出处: http://blog.csdn.net/limb99/article/details/18901513 L

JS浏览器滚轮事件实现横向滚动照片展

if(window.attachEvent){ ///*IE8注册事件*/ this.oc.attachEvent('onmousewheel',function(e) { //函数体 }); } else if(window.addEventListener) ///*Firefox注册事件*/ { this.oc.addEventListener('DOMMouseScroll', function(e) { //函数体 }, false); } this.oc.onmousewheel =

微信小程序-scroll-view横向滚动和上拉加载

今天介绍微信小程序中scroll-view实现横向滚动和上拉加载的实现及需要注意的地方. 先看最终效果. 横向滚动 1.设置滚动项display:inline-block; 2.设置滚动视图容器white-space: nowrap; 3.滚动项不要用float 为什么会有以上三点要求呢? 其实横向滚动官方文档中是没有做太多说明的,只说明需要定义scroll-view滚动方向scroll-x=true允许横向滚动,但是我在实践的时候我发现,你要横向滚动,首先你得是一排吧.所以才发现需要定义滚动项

Android TextView 横向滚动(跑马灯效果)

Android TextView 中当文字比较多时希望它横向滚动显示,下面是一种亲测可行的方法. 效果图: 1.自定义TextView,重写isFocused()方法返回true,让自定义TextView一直处于获取焦点状态. package com.example.shen.marqueedemo; import android.content.Context; import android.util.AttributeSet; import android.widget.TextView;

jQuery实现文字横向滚动效果

HTML代码: <div id="aaa" style="width:100px; position:relative; white-space:nowrap; overflow:hidden; height:20px;"> <div id="noticeList" style="position:absolute; top:0; height:20px;"> <span>jQuery文字横

解决iScroll横向滚动区域无法拉动页面的问题

近期项目中使用iScroll遇到一个问题,在设定wrapper为横向滚动时,如果你手指放在该区域,将无法拉动页面,也就是说该区域取消了默认事件.这个体验是实在是无法接受,特别是页面中有多个横向滚动区域时,很容易触碰到这种区域,这时用户将觉得页面很卡. Google搜了一下,看来很多人都为这个问题而烦恼.有高人给出了解决方案,在 这里 可以找到. 代码如下: myScroll = new iScroll('scrollpanel', { // other options go here... vS

web开发 小方法1-禁止横向滚动

最近学了学做了个公司的网站  总结了一些小方法 比如取消横向滚动条并禁止的横向滚动 这样就可以吧超出的切掉让网页更和谐 在body 标签 body{ text-align: center; overflow:scroll; overflow-x:hidden} 加入该代码就行  overflow属性详情可以去 w3cSchool 或者菜鸟教程