一.概述
流水灯是指LED从低位到高位或者从高位到低位逐一轮流被点亮,看起来像是一只发亮的LED在流动一样。
在C编译器里,用位移操作符“<<”和“>>”来处理一个数据,不管是从高位向低位移位还是从低位向高位移位,补上来的最高位或最低位永远是0。51单片机因其IO口的高电平不能驱动大电流负载,所以LED流水灯只能接成低电平驱动的形式,使得51单片机不像AVR单片机和PIC单片机那样直接用位移操作符来实现流水灯效果,而是需要编程技巧。导致51单片机的流水灯程序困扰了不少单片机初学者,偷懒的人调用库函数实现,聪明的人利用数组实现,而执着的人却使用位移操作符实现。笔者认为,会利用位移操作符实现流水灯效果的才算是真正懂得流水灯编程。
二.电路设计
在WSF-51DB开发板上,利用AT89S52单片机的P2口来驱动8位LED。这8位LED设了电源开关(由两位贴片拨码开关SW-DIP的第一位控制),以免P2口驱动其他资源的时候LED闪烁影响视觉。
三.程序设计
/**************************************************************************
*程序名称:流水灯
*程序功能:三种方法实现流水灯效果
*
* MCU型号:AT89S52-24PU
*时钟频率:12MHZ
**************************************************************************/
#include<reg52.h>
#include <intrins.h>//包含左右移位函数
unsigned char code ledm[8]={0xfe,0xfd,0xfb,0xf7,0xfef,0xdf,0xbf,0x7f};//流水灯数组
//延时ms函数:
void Delayms(unsigned int t)
{
unsigned int i,j;
for(i=t;i>0;i--)
for(j=120;j>0;j--);//延时大约1毫秒
}
//主函数:
int main(void)
{
unsigned char lv,rv,i;
while(1)
{
//方法一:利用数组实现
for(i=0;i<8;i++)//左移
{
P2=ledm;//数组由小到大取值
Delayms(400);//延时400毫秒
}
for(i=8;i>0;i--)//右移
{
P2=ledm[i-1];//数组由大到小取值
Delayms(400);
}
//方法二:利用位移操作符实现
lv=0x01; //左移初值,技巧
for(i=0;i<8;i++)//左移
{
P2=~lv;//取反后赋值,技巧
Delayms(400);
lv<<=1;//左移
}
rv=0x80;//右移初值,技巧
for(i=0;i<8;i++)//右移
{
P2=~rv;//取反后赋值,技巧
Delayms(400);
rv>>=1;//右移
}
//方法三:调用库函数实现
for(i=0;i<8;i++)
{
P2=_crol_(0xfe,i);//调用左移函数
Delayms(400);
}
for(i=0;i<8;i++)
{
P2=_cror_(0x7f,i);//调用右移函数
Delayms(400);
}
}
return 0;
}