流水灯设计
目的与要求
通过采用单片机控制8个LED发光二极管顺序点亮的流水灯系统设计与制作,让读者了解C语言的数据类型、常量与变量、运算符和表达式等基本概念及使用方法。
设计要求:首先点亮连接到P1.7引脚的发光二极管,延时一定时间后熄灭,再点亮连接到P1.6引脚的发光二极管,直到电量最后一个连接到P1.0引脚的发光二极管,再从头开始,循环不止,产生一种动态显示的流水灯效果。
电路设计
流水灯控制系统设计电路如 图1 所示。
图1:
源程序设计
流水灯控制系统的源程序如下。
//程序:流水灯设计.c
//功能:采用库函数实现的流水灯控制程序
#include <reag51.h>
#incllude <intrins.h>
//函数名:delay
//函数功能:实现软件延时
//形式参数:无符号整形变量i,控制空循环的次数
//返回值:无
void delay(unsigned int i)//定义延时函数
{
unsigned int k;
for(k=0;k<i;k++);
}
void main() //主函数
{ //主函数开始
P1=0x7F; //P1端口输出0x7f,即01111111B,点亮P1.7连接的LED
while(1) //无限循环
{ //循环体语句组开始
P1=_cror_(P1,1); //调用内部函数_cror_(),将P1的二进制数值循环右移
delay(5000); //延时
} //循环体语句组开始
} //结束控制程序
通过向P1口写入一个8位二进制数来改变每个引脚的输出电平状态,从而控制8个发光二极管的亮灭。在 流水灯设计.c源程序中,语句“P1=0x7F;”将P1口8位引脚设置为按8位01111111输出,电量P1.7引脚连接的发光二极管。将P1端口在01111111、10111111、11011111、11101111、11110111、11111011、11111101、11111110这8种状态之间顺序转换,就可以实现流水灯效果。
容易看出,P1端口顺序彼岸花的8个状态是最高位旁边的”0“依次右移,调用内部函数
cror
() 可以实现循环右移功能。程序中使用了while循环语句不停地重复着”P1端口状态循环右移→延时“的循环程序段,程序流程图如 图2 所示。
图2:
Keil C51提供_cror_()是循环右移函数,就是把低位移出去的部分补到高位去。
循环右移函数_cror_()需要两个参数。第一个参数存放被移位的数据,例如此例中的P1端口状态;第二个参数是常数,用来说明移位次数,此例中常数为1,表示右移1位。
Keil C51还提供了一个循环左移函数_crol_(),使用原理与_cror_()相同。
任务小结
本任务通过用51单片机控制连接到P1口的8个发光二极管实现流水灯效果的软、硬件设计过程,使读者初步了解C语言程序的基本结构和特点,学习如何用C语言编程来控制单片机的并行I/O端口。
举一反三
C51提供左移运算“<<”和右移运算“>>”,运算的结果是把二进制操作数左移或右移若干位。对无符号数左移后,高位移出的数丢掉,对低位补0。对无符号数右移后,低位移出的数丢掉,对高位补0。
例如:如果 aa=01111111 ,执行命令“aa>>1”后,aa=00111111。使用移位运算符实现流水灯的源程序如下。
//程序:流水灯设计2.c //功能:采用库函数实现的流水灯控制程序 #include <reag51.h> //函数名:delay //函数功能:实现软件延时 //形式参数:无符号整形变量i,控制空循环的次数 //返回值:无 void delay(unsigned int i)//定义延时函数 { unsigned int k; for(k=0;k<i;k++); } void main() //主函数 { unsigned char aa,i; //定义字符变量aa,i while(1) //无限循环 { //循环体语句组开始 aa=0x80; //给变量aa赋值0x80,即10000000 for(i=0;i<8;i++) //用for循环控制逐位移动8次 { P1=~aa; //将aa的值取反后经8位P1引脚输出,~为取反运算符 delay(5000); //延时 aa>>=1; //将aa的二进制数值右移一位 } //结束循环 } //循环体语句组开始 } //结束控制程序