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);
}
        
View Code

 

 歡迎關注本人的個人博客YoungCoding.top


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM