前言:
淘寶買了個51開發板學習用,其16*16點陣屏是4個74HC595級聯控制,這種方式方便更改行、列刷新模式,但每顯示一行或一列時都有32bit數據串行輸入再一起並行輸出,速度較慢,容易產生閃爍感。而且配套教程太垃圾,。。太多槽點就不吐槽了,全靠自力更生,新手初學,個中辛苦就不談了。
教程沒有橫向滾動的例程,於是自己寫了一個,記錄一下。也畫了個Protues的原理圖,供沒有這款開發板的朋友研究。
軟件環境:Keil uvsion 4, Protues 7.8
本例采用列掃描模式,只實現了向左滾動。需要向右滾動的朋友請自行更改或參見
《4個74HC595級聯控制16x16點陣橫向滾動帶仿真(二)》。
原理圖:
代碼:

/** ********************************************************** ****** 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); }
歡迎關注本人的個人博客YoungCoding.top