目录
- 引言
- led模块原理图解析
- led小灯的操作
- 1.点亮led小灯
- 位操作法
- 总线操作法
- 2.闪烁led小灯
- 位操作法
- 总线操作法
- 3.led流水灯
- 位操作法
- 总线操作法
- 总线操作-数组循环遍历法
- 总线操作-循环位移法
- 总线操作-循环位移函数法
- 4.led花样操作
- 循环流水灯
- 聚拢流水灯
- 间隔闪烁灯
- 流水似华年
- 起舞弄清影
- 总结
- 结束语
引言
51单片机led小灯的操作可以是多种多样的,操作方式也可以是多种多样的,本篇文章使用较为简单的方法实现led小灯的点亮、闪烁、流水灯等操作。
led模块原理图解析
将led模块直接集成在51单片机核心板上的,例如下图所示:
那么我们需要注意的就是
<1>led小灯的接法:共阳极接法还是共阴极接法。很显然,在上图中,我们可以看到所有led小灯的阳极接在了一起,因此这是“共阳极接法”。
理由:如果是led小灯模块是共阳极接法,那么我们在编写代码时就应该知道,需要给led小灯的阴极赋一个低电平(即赋值为0),这样才能够使小灯被点亮。如果是led小灯模块是共阳极接法,反之亦反。
<2>led小灯另一极接入的位置:这里我们看的就是led小灯阴极接入的地方,如图所示,我们可以看到8个led小灯接入到了51单片机核心板的P2 I/O口。同理,图中标的是哪里就接的是哪里。
理由:我们在编写程序的时候需要控制这个位置电平的高低,从而实现控制led小灯的亮灭。例如这里,我们就需要在编写代码时控制P2口的电平高低从而达到控制led小灯的亮灭。
其次,就是另外一种,led小灯模块是独立存在的,例如下图所示:
此时我们除了要注意它的led小灯的接法是共阳极接法以外,还需要注意的是:
独立就体现在led小灯的阴极并没有和51单片机的核心板直接连接在一起,而是接在了连接器(例如图中J19)上,这时我们必须手动用排线将这个led小灯模块与51单片机核心板连接在一起,那么连在哪个端口上就不做限制了,根据需求连接即可。正因此,这种独立出来的模块相比于上面的集成模块来说,灵活性就大大提高了。所以,我们需要根据具体需求,将连接器连接到合适的I/O并控制它,进而达到控制led模块连接器上的电平高低,最终达到控制led小灯的亮灭。
若要与上面的集成模块一致,只需要用排线将led模块与P2口连接(连接时注意方向)即可。
注解:J19的 “J” 是英文junctor,名词连接器的意思。
led小灯的操作
根据上面的分析,我们知道对于led小灯的控制,只需要判断出led小灯的接法,进而根据接法控制另外一级所接位置电平的高低即可控制小灯的亮灭。
那么对于共阳极接法,点亮led小灯只需要给阴极所接的P2口的相应位赋一个低电平(即赋值为0)即可实现点亮、赋一个高电平(即赋值为1)即可实现熄灭。共阴极接法与其反之亦反。
以下操作均以led小灯为共阳极接法并与P2口相连为例。
1.点亮led小灯
操作现象:
点亮8盏led小灯
位操作法
#include <reg52.h> //包含头文件
//使用sbit位定义
sbit led0 = P2^0; //位定义P2口第一位
sbit led1 = P2^1; //位定义P2口第二位
sbit led2 = P2^2; //位定义P2口第三位
sbit led3 = P2^3; //位定义P2口第四位
sbit led4 = P2^4; //位定义P2口第五位
sbit led5 = P2^5; //位定义P2口第六位
sbit led6 = P2^6; //位定义P2口第七位
sbit led7 = P2^7; //位定义P2口第八位
//主函数
void main()
{
while(1)
{
//点亮LED小灯
led0 = 0; //点亮第一盏小灯
led1 = 0; //点亮第二盏小灯
led2 = 0; //点亮第三盏小灯
led3 = 0; //点亮第四盏小灯
led4 = 0; //点亮第五盏小灯
led5 = 0; //点亮第六盏小灯
led6 = 0; //点亮第七盏小灯
led7 = 0; //点亮第八盏小灯
}
}
总线操作法
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//主函数
void main()
{
while(1)
{
//点亮LED小灯
led = 0xfe; //点亮第一盏小灯
led = 0xfd; //点亮第二盏小灯
led = 0xfb; //点亮第三盏小灯
led = 0xf7; //点亮第四盏小灯
led = 0xef; //点亮第五盏小灯
led = 0xdf; //点亮第六盏小灯
led = 0xbf; //点亮第七盏小灯
led = 0x7f; //点亮第八盏小灯
//led = 0x00; //全部点亮(另外一种方式)
}
}
2.闪烁led小灯
操作现象:
P2口第一位led小灯闪烁
位操作法
#include <reg52.h> //包含头文件
//使用typedef关键字
//类型重命名
typedef unsigned int uint;
//使用sbit位定义
sbit led = P2^0; //位定义P2口第一位
//函数声明
void delay(uint i); //延时函数
//主函数
int main()
{
while(1)
{
led = 0; //点亮小灯
//延时一会
delay(50000); //对于晶振11.0592MHZ :大约延时0.49s
led = 1; //熄灭小灯
//延时一会
delay(50000);
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
总线操作法
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//函数声明
void delay(uint i); //延时函数
//主函数
int main()
{
while(1)
{
led = 0xfe; //点亮P2口第一盏小灯
//延时一会
delay(50000); //对于晶振11.0592MHZ :大约延时0.49s
led = 0xff; //熄灭小灯
//延时一会
delay(50000);
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
3.led流水灯
操作现象:
led小灯从第1盏~第8盏依次点亮。
位操作法
#include <reg52.h> //包含头文件
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//使用sbit位定义
sbit led0 = P2^0; //位定义P2口第一位
sbit led1 = P2^1; //位定义P2口第二位
sbit led2 = P2^2; //位定义P2口第三位
sbit led3 = P2^3; //位定义P2口第四位
sbit led4 = P2^4; //位定义P2口第五位
sbit led5 = P2^5; //位定义P2口第六位
sbit led6 = P2^6; //位定义P2口第七位
sbit led7 = P2^7; //位定义P2口第八位
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
while(1)
{
led0 = 0; //点亮第一盏小灯
delay(50000); //延迟一会
led0 = 1; //熄灭第一盏小灯
led1 = 0; //点亮第二盏小灯
delay(50000); //延迟一会
led1 = 1; //熄灭第二盏小灯
led2 = 0; //点亮第三盏小灯
delay(50000); //延迟一会
led2 = 1; //熄灭第三盏小灯
led3 = 0; //点亮第四盏小灯
delay(50000); //延迟一会
led3 = 1; //熄灭第四盏小灯
led4 = 0; //点亮第五盏小灯
delay(50000); //延迟一会
led4 = 1; //熄灭第五盏小灯
led5 = 0; //点亮第六盏小灯
delay(50000); //延迟一会
led5 = 1; //熄灭第六盏小灯
led6 = 0; //点亮第七盏小灯
delay(50000); //延迟一会
led6 = 1; //熄灭第七盏小灯
led7 = 0; //点亮第八盏小灯
delay(50000); //延迟一会
led7 = 1; //熄灭第八盏小灯
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
总线操作法
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
while(1)
{
led = 0xfe; //点亮第一盏小灯
delay(50000); //延迟一会
led = 0xfe; //熄灭第一盏小灯
led = 0xfd; //点亮第二盏小灯
delay(50000); //延迟一会
led = 0xfd; //熄灭第二盏小灯
led = 0xfb; //点亮第三盏小灯
delay(50000); //延迟一会
led = 0xfb; //熄灭第三盏小灯
led = 0xf7; //点亮第四盏小灯
delay(50000); //延迟一会
led = 0xf7; //熄灭第四盏小灯
led = 0xef; //点亮第五盏小灯
delay(50000); //延迟一会
led = 0xef; //熄灭第五盏小灯
led = 0xdf; //点亮第六盏小灯
delay(50000); //延迟一会
led = 0xdf; //熄灭第六盏小灯
led = 0xbf; //点亮第七盏小灯
delay(50000); //延迟一会
led = 0xbf; //熄灭第七盏小灯
led = 0x7f; //点亮第八盏小灯
delay(50000); //延迟一会
led = 0x7f; //熄灭第八盏小灯
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
总线操作-数组循环遍历法
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即点亮某一位led小灯的操作数)
uchar led_location[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 8; i++)
{
led = led_location[i]; //点亮led小灯
delay(50000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
操作解析:
将每一次点亮小灯的操作数使用一个数组存放起来,然后使用循环不断遍历即可。
总线操作-循环位移法
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//利用左移运算符实现循环点亮led小灯
for(i = 0; i < 8; i++)
{
led = ~((~0xfe) << i); //点亮led小灯
//led = ~(0x01 << i); //点亮led小灯
delay(50000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
操作解析:
需要使用左移运算符(<<),由于点亮led小灯需要赋值低电平(即赋值为0),而左移运算符左移时会右补零,所以这样会多出一个零,因而我们可以利用这一点,先将操作数取反之后再左移,左移之后再取反,或者直接使用0x01(点亮第一盏led的取反操数)左移,左移之后直接取反都可达到目的,然后利用循环控制左移位数即可。
总线操作-循环位移函数法
#include <reg52.h> //包含头文件
#include <intrins.h>
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//利用左移循环函数实现循环点亮led小灯
for(i = 0; i < 8; i++)
{
led = _crol_(0xfe,i); //点亮led小灯
delay(50000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
操作解析:
需要用到包含在intrins.h的头文件中的循环左移和循环右移函数:
unsigned char _cror_ (unsigned char, unsigned char); //循环左移函数
unsigned char _crol_ (unsigned char, unsigned char); //循环右移函数
其中第一个参数为需要循环左移(或循环右移)的16进制数,第二个参数为需要循环左移(或循环右移)的位数。
循环左移(或循环右移),循环就是相应的高位(或低位)会依次循环补到相应的低位或高位),这样的话,就无需取反,即可达到点亮下一个小灯的操作数。例如:
_cror_(0xfe,1); //即将十六进制0xfe循环左移一位
该过程为:
循环右移刚好与之相反
_crol_(0x7f,1); //即将十六进制0x7f循环右移一位
若一次移位多位的话,根据以上过程举一反三即可。
4.led花样操作
循环流水灯
操作现象:
led小灯从第1盏~第8盏依次点亮;
然后再从第8盏~第1盏依次点亮
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即循环点亮led小灯的操作数)
uchar led_location[14] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,
0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 14; i++) //(第1盏 ~ 第8栈)
{
led = led_location[i]; //点亮led小灯
delay(50000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
聚拢流水灯
操作现象:
led小灯先点亮第1和第8盏小灯;
再点亮第2和第7盏;
再点亮第3和第6盏;
最后点亮第4和第5盏。
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即聚拢点亮led小灯的操作数)
uchar led_location[4] = {0x7e,0xbd,0xdb,0xe7};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 4; i++) //(第1盏 ~ 第8栈)
{
led = led_location[i]; //点亮led小灯
delay(10000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
间隔闪烁灯
操作现象:
led小灯先依次点亮第1,3,5,7盏小灯;
再点亮第8,6,4,2盏小灯。
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即间隔闪烁led小灯的操作数)
uchar led_location[8] = {0xfe,0xfb,0xef,0xbf,0x7f,0xdf,0xf7,0xfd};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 8; i++) //(第1,3,5,7盏)
{
led = led_location[i]; //点亮led小灯
delay(50000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
流水似华年
操作现象:
led小灯先点亮第1盏,再点亮第1,2盏,再点亮1,2,3盏,直到全部点亮;
再熄灭第1盏,再熄灭第1,2盏,再熄灭第1,2,3盏,直到全部熄灭。
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即流水似华年led小灯的操作数)
uchar led_location[16] = {0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,
0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 16; i++) //(第1盏 ~ 第8栈)
{
led = led_location[i]; //点亮led小灯
delay(10000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
起舞弄清影
操作现象:
led小灯先点亮第1盏,再点亮第1,2盏,再点亮1,2,3盏,直到全部点亮;
再熄灭第1盏,再熄灭第1,2盏,再熄灭第1,2,3盏,直到全部熄灭。
紧接着,led小灯先点亮第8盏,再点亮第8,7盏,再点亮8,7,6盏,直到全部点亮;
再熄灭第8盏,再熄灭第8,7盏,再941774第8,7,6盏,直到全部熄灭。
#include <reg52.h> //包含头文件
//宏定义
#define led P2 //宏定义P2口
//使用typedef关键字
//类型重命名
typedef unsigned char uchar;
typedef unsigned int uint;
//定义数组
//用来存放赋值给P2口的16进制操作数(即起舞弄清影led小灯的操作数)
uchar led_location[32] = {0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,
0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff,
0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00,
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
//函数声明
void delay(uint i); //延时函数
//主函数
void main()
{
//定义for循环计数变量i
uchar i;
while(1)
{
//遍历数组实现循环点亮led小灯
for(i = 0; i < 32; i++) //(第1盏 ~ 第8栈)
{
led = led_location[i]; //点亮led小灯
delay(10000); //延迟一会
}
}
}
//函数定义
//延时函数
void delay(uint i)
{
while(i--);
}
总结
其实所谓的花样流水灯,不过是将小灯的点亮顺序按照特定的组合方式排列在一起,在配上合适的间隔时间,就可以达到。举一反三很重要!
结束语
好的,51单片机实验系列之LED小灯的操作(一)就介绍到这里。夯实基础,勇攀高峰,加油!💪
本次励志:
Rest at the end,not in the middle.