转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/37967455
一.硬件
这里的LED选择直插的雾面LED,亮度可以还不失美观。注意每行要加上限流电阻。74HC138(三八译码器)作为列选,每行都连着74HC595(移位寄存器)实现串行输入,并行输出。
二.软件
led.h
#ifndef __Led_H #define __Led_H #include "STC12C5A.h" #define uint unsigned int #define uchar unsigned char #define light 127 sbit _SER = P0^0; // 74hc595 串行数据输入端 sbit _RCLK = P0^1; // 74hc595 数据输出时钟线 sbit _SRCLK = P0^2; // 74hc595 数据输入时钟线 sbit ACT_Key = P0^3; // 模式开关 sbit key1 = P0^6; // pwm调节+ sbit Key_2 = P3^3; // 时钟调节按键 extern void delayled(int ); extern void LineInput(uint dat); //extern void DisplayTime(void); //extern void TimeSetting(void); extern void ruoyun(void); #endif
led.c
#include "Led.h" uint code table1[80]={ 0x0C,0x01,0x10,0x11,0xFE,0x11,0x44,0x3F, 0x44,0x11,0x44,0x3D,0x7E,0x11,0x00,0x11,/*"若",0*/ 0x00,0x00,0x0C,0x01,0x34,0x11,0xC4,0x11, 0x04,0x11,0x14,0x11,0x0E,0x01,0x00,0x01,/*"云",0*/ 0x04,0x10,0xFC,0x1F,0x00,0x1F,0xFC,0x00, 0x00,0x1F,0xFC,0x1F,0x04,0x10,0x00,0x00,/*"M",0*/ 0xE0,0x03,0x18,0x0C,0x04,0x10,0x04,0x10, 0x04,0x10,0x08,0x10,0x10,0x1C,0x00,0x00,/*"C",0*/ 0x00,0x10,0xF8,0x1F,0x04,0x10,0x04,0x00, 0x04,0x00,0x04,0x10,0xF8,0x1F,0x00,0x10,/*"U",0*/ }; uchar code ColScan[16] = {0x20,0x24,0x22,0x26,0x21,0x25,0x23,0x27, 0x10,0x14,0x12,0x16,0x11,0x15,0x13,0x17}; // 74hc138 进行列扫描 void delayled(int z) // 延时函数 { int x,y; for(x=0;x<z;x++) for(y=0;y<110;y++); } void WriteByte(char dat) //写一个字节的数据 { char i; for(i=0;i<8;i++) //循环8次把编码传给锁存器 { dat=dat>>1; //右移一位,取出该字节的最低位 _SER=CY; //将该字节的最低位传给R _SRCLK=0; //将数据取出,上升沿 _SRCLK=1; } } void LineInput(uint dat) // 单列数据显示 { uchar n; _RCLK = 0; for(n=0;n<16;n++) { _SRCLK = 0; _SER = (dat>>n)&0x01; //将数据的值串入输入SER中,然后并行输出 _SRCLK = 1; } _RCLK = 1; } void ruoyun() { int num,k,j;//,move,speed; for(k=0;k<25;k++) //控制动画移动 { for(j=0;j<150;j++) //延时 { for(num=0;num<16;num++) //控制每一帧 { WriteByte(table1[2*(num+k)]); //送出一个字节 WriteByte(table1[2*(num+k)+1]); P2=ColScan[num]; //行选 _RCLK=1; //输出锁存器数据下降沿 _RCLK=0; delayled(2); } } }
我想最核心的东西,应该就是怎么通过三个循环实现左移的吧(虽然这样做用来三个循环,现在看来并不是很好),下面详细讲讲这段代码。
代码思路:我们都知道要想实现点阵显示只要向595串行输入16个字模数据就OK了。那么如何叫它向左面移动呢?其实很简单,下面我画图说明:
最里面的那层for循环实现了点阵的显示,就是从左到右刷一遍。
中间那层for循环是一箭双雕,有两个作用,第一个就是为了点阵能够稳定显示,就是快速的多刷几遍(要不刷一遍谁看得清)。第二个作用就是为了向左移动提供延时(要不瞬间不就左移到头了嘛)。其实规范点的写法应该是这个for提供稳定点阵显示,然后外面在加一个延时控制向左移动的速率。后来我看写的太复杂就给省略了。
最外面的那层循环控制的是左移的列数(就是向左移动多少):
for(k=0;k<25;k++) //控制动画移动
K的值代表想做移动的列数,为什么是25,因为一共是5个字每个字占8行
初始状态: *若 云*MCU
终止状态: 若云*MCU*
也就是像左面移动三个字,3*8=24,所以K<25。
最后还有一个LineInput()函数,干嘛用的呢?留个悬念,后续博客讲解。
原文地址:http://blog.csdn.net/ruoyunliufeng/article/details/37967455