前言:
淘宝买了个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 #include #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); }
上一篇:4个74HC595级联控制16x16点阵横向滚动带仿真(二)
下一篇:8051内核的使用
推荐阅读最新更新时间:2024-11-07 12:31
设计资源 培训 开发板 精华推荐
- LT1934IS6-1 独立式 350mA 锂离子电池充电器的典型应用电路
- AM1/4S-0507SH30Z 7.2V 0.25 瓦 DC-DC 转换器的典型应用
- IR4311集成数字音频差分放大器的典型应用
- LT3970HMS-5 5V 同步降压转换器的典型应用
- 适用于工业应用的 C8051F534 MCU 的 C8051F52x-53x-DK、8051 开发系统
- CH340N_迷你USB串口
- DC9007A,基于 LTP5903 的 SmartMesh WirelessHART 入门套件
- 使用 NXP Semiconductors 的 FXAS21002C 的参考设计
- AL5809 60V 两端恒流 LED 驱动器 PowerDI 与高端 LED 串的典型应用
- 2.4G自制手柄2.0