上QQ阅读APP看书,第一时间看更新
例3-2 单片机控制点亮发光LED案例2
控制发光二极管由上至下,再由下至上的反复循环点亮的流水灯,原理电路如图3-3所示。为了电路图简洁,电路中省去了时钟电路和复位电路,引脚与+5V电源的连接也可省略,Proteus已经默认,不影响仿真效果。
图3-3 单片机控制的流水灯点亮原理电路
下面采用3种方法来实现题目要求,具体如下。
1. 数组的字节操作实现
本方法是建立1个字符型数组,将控制8个LED显示的8位数据作为数组元素,依次送到P1口来实现。
参考程序如下。
#include <reg51.h> #define uchar unsigned char uchar tab[ ]={ 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; //前8个数据为由上至下的点亮数据,后8个为由下至上的点亮数据 void delay( ) { uchar i,j; for(i=0; i<255; i++) for(j=0; j<255; j++); } void main( ) //主函数 { uchar i; while (1) //反复循环 { for(i=0;i<16; i++) { P1=tab[i]; //向P1口送出点亮数据的数组元素 delay( ); //延时,即点亮一段时间 } } }
2. 通过移位运算符实现控制
本方法是使用C51编程语言中的移位运算符“>>”“<<”,把送到P1口的显示控制数据移位,从而实现发光二极管的依次点亮。
参考程序如下。
#include <reg51.h> #define uchar unsigned char void delay( ) //延时函数 { uchar i,j; for(i=0; i<255;i++) for(j=0; j<255;j++); } void main( ) //主函数 { uchar i,temp; while (1) { temp=0x01; //左移初值赋给temp for(i=0;i<8;i++) { P1=~temp; //temp中的数据取反后送P1口 delay( ); //延时 temp=temp<<1; //temp中的数据左移一位 } temp=0x80; //将右移初值赋予temp for(i=0;i<8;i++) { P1=~temp; //temp中的数据取反后送P1口 delay( ); //延时 temp=temp>>1; //temp中的数据右移一位 } } }
程序说明如下。
本例使用了左移、右移移位运算符。注意使用移位运算符“>>”“<<”与C51中的库函数循环左移函数“_crol_”和循环右移函数“_cror_”的区别。左移移位运算“<<”是将高位丢弃,低位补0;右移移位运算“>>”是将低位丢弃,高位补0。循环左移函数“_crol_”是将移出的高位再补到低位,即“循环”移位。同理,循环右移函数“_cror_”是将移出的低位再补到高位。
3. 用循环左、右移位函数实现
本方法是使用C51中提供的库函数,即循环左移n位函数和循环右移n位函数,控制发光二极管的点亮。
参考程序如下。
#include <reg51.h> #include <intrins.h> //包含循环左、右移位函数的头文件 #define uchar unsigned char void delay( ) { uchar i,j; for(i=0;i<255;i++) for(j=0;j<255;j++); } void main( ) // 主函数 { uchar i,temp; while (1) { temp=0xfe; // 初值为11111110B for(i=0;i<7;i++) { P1=temp; // temp中的点亮数据送P1口,控制点亮显示 delay( ); // 延时 temp=_crol_(temp,1); // 执行左移函数,temp中的数据循环左移1位 } for(i=0;i<7;i++) { P1=temp; // temp中的数据送P1口输出 delay( ); // 延时 temp=_cror_( temp,1); // 执行循环右移函数,temp中的数据循环右移1位 } } }