第十二课 LED数码管之三 玩流水灯(2)--花样式流水灯
这是一个有趣的综合性实验,会用到前面讲的一些东西
程序讲解
/*--------------------------------------------------------------*/
//LED八位数码滚动显示
//显示部分用中断方式,便于程序的拓展
/*--------------------------------------------------------------*/
//包含头文件
#include <reg52.h>
#include "74HC595.H"
/*--------------------------------------------------------------*/
//全局变量定义
#define Num sizeof(LED_Seg) //代码长度
unsigned char LED_Pos; //位扫描
unsigned char code LED_Seg[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff, //数码管段位全灭(共阳数码管)
0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7, //数码管段位只有最下面一横亮_
0xff,0xff,0xff,0xff,0xff,0xff,0xff, //数码管段位全灭(共阳数码管)
0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF, //数码管段位只有中间一横亮
0xff,0xff,0xff,0xff,0xff,0xff,0xff, //数码管段位全灭(共阳数码管)
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F, //数码管段位只有小数点亮_
0xff,0xff,0xff,0xff,0xff,0xff,0xff, //数码管段位全灭(共阳数码管)
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, //数码管段位只有最上面一横亮
0xff,0xff,0xff,0xff,0xff,0xff,0xff, //数码管段位全灭(共阳数码管)
0xF7,0xBF,0xFE,0xBF,0xF7,0xBF,0xFE,0xBF,0xF7, //波浪(1)
0xB6,0xB6,0xB6,0xB6,0xB6,0xB6,0xB6,0xB6, //数码管段三横全亮
0xF7,0xB7,0xB7,0xB6,0xB6,0xB7,0xB7,0xF7,0xF7, //波浪(2)
0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //数码管段位全灭(共阳数码管)
unsigned char Count; //移位速度控制
unsigned char n; //移位变量
/*--------------------------------------------------------------*/
如这块不是很明白,可以回到 第七课 跑马灯之六 随机显示 :http://group.ednchina.com/2031/24998.aspx 复习一下
//定时器初始化
void T0_init(void)
{
TMOD = 0x01; //定时器的工作方式设定 定时器0工作在方式1
TH0 = 0xf8; //2000us 赋给定时器高低位初始值
TL0 = 0x36;
IE = 0x82; //中断使能寄存器使EA、ETO有效,这句话可以换成EA=1; ET0=1;
TR0 = 1; //定时器0控制位,允许定时器0工作
}
/*--------------------------------------------------------------*/
//LED显示函数1
//Direction = 0 ←左移
//Direction = 1 →右移
void LED_Display1(unsigned char *p, bit Direction)
{
if(Direction)
Ser_IN(0x01 << LED_Pos); //位选,
else
Ser_IN(0x80 >> LED_Pos);
Ser_IN(*(p + LED_Pos)); //段码此时*p=&LED_Seg[n]
Par_OUT(); //上升沿锁存输出
LED_Pos++; //循环扫描
if(LED_Pos == 8) LED_Pos = 0; //扫描完成后最新开始
}
/*--------------------------------------------------------------*/
//定时器中断服务
void T0_intservice(void) interrupt 1
{
TH0 = 0xf8; //给定时器0高低位重新赋初值
TL0 = 0x36;
if((n > 6 && n < 15)||(n > 21 && n < 30)) LED_Display1(&LED_Seg[n], 1); //控制移动方向
else LED_Display1(&LED_Seg[n], 0); //控制移动方向
Count++;
if(Count == 56) //滚动速度的控制,最好为8的倍数
{
Count = 0;
n++; if(n == Num-7) n = 0;
}
}
/*-------------------------------------------------------------*/
//主函数
void main(void)
{
T0_init(); //定时器初始化
while(1);
}
本节重点:
1、指针的使用。 *p = &LED_Seg[n]表示p指向数组LED_Seg[]的第n个元素,*(p + LED_Pos)就指向数组LED_Seg[]的第n+LED_Pos个元素,这是指针的基本用法。
2、基本原理。画面的移动其实是靠n的变化来决定的,速度只是由 Count决定的,Count它控制着进入中断多少次后n变化一次(加一)。n变化一次,则指针的起始地址就向后移动一次,即让要显示数据更新一次,这样就实现了画面的更新,连续的画面更新就实现了动态显示的效果!
演示视频:
http://v.youku.com/v_show/id_XOTIzNjM2NjQ=.html
相关程序:https://static.assets-stash.eet-china.com/album/old-resources/2009/5/24/c31f6dcc-2231-41a9-838c-3bf5df19e786.rar
用户219617 2009-5-26 08:49
用户222124 2009-5-26 08:36