MCU-51:让LED闪烁起来
目录
- 一、LED闪烁
- 1.1 编写代码
- 1.2 延时函数
- 1.3 由0和1控制实现
- 二、LED流水灯
- 2.1 流水灯基础版
- 2.2 移位法实现LED流水灯
一、LED闪烁
昨天我们初识单片机,点亮了一个灯开启了我们51单片机的学习之旅。那么今天我们来一步步深入学习。
1.1 编写代码
会了点亮一个灯,那么闪烁应该就是一亮一灭循环,那代码应该如下
#include <REGX52.H>
void main()
{
while(1)
{
P2=0xFE;
P2=0xFF;
}
}
将以上代码进行编译并无问题。
但是将以上代码烧写到单片机,你会发现单片机LED灯一直长亮。
这是为什么?使我们的代码有问题吗?
其实不是,代码正确,只是单片机晶振频率是12MHz,是M哦,那么一秒会闪几万次,我们的肉眼根本看不到
所以要在程序中加入延时函数
1.2 延时函数
延时函数有两种方法:
第一种方法:通过STC内的工具实现
选择软件演技计算器进行代码生成
延时代码如下
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
将以上代码加入到刚刚写的程序中
#include <REGX52.H>
#include <INTRINS.H>
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0xFE;
Delay500ms();
P2=0xFF;
Delay500ms();
}
}
注意需要包含头文件
#include <INTRINS.H>
在while函数中进行调用
while(1)
{
P2=0xFE;
Delay500ms();
P2=0xFF;
Delay500ms();
}
将以上代码编译烧进单片机,奇迹就出现了。
第二种方法:通过函数调用配合while语句实现
void delay(unsigned int i)
{
while(i--);
}
学过C语言的都知道什么意思,这里就不解释了
完整代码如下
#include <REGX52.H>
void delay(unsigned int i)
{
while(i--);
}
void main()
{
while(1)
{
P2=0xFE;
delay(50000);
P2=0xFF;
delay(50000);
}
}
这是不是比第一种方法代码要简单的多,越简单,计算越快
1.3 由0和1控制实现
代码如下,每一行代码都有解释,这里不做解释
#include <reg52.h> //定义单片机的一些特殊功能寄存器
sbit led=P2^0; //定义指定LED灯的管脚
void delay(unsigned int i) //延时函数。unsigned int定义无符号整型,范围0-655535
{
while(i--); //i=1时,大约延时10us
}
void main() //主函数,程序从这里开始执行
{
while(1)
{
led=0; //0表示低电平,共阳极二极管点亮
delay(50000); //大约延时450ms
led=1; //1表示高电平,LED熄灭
delay(50000); //大约延时450ms
}
}
二、LED流水灯
2.1 流水灯基础版
8个LED灯的定义,以共阳极为例,让某一个灯点亮就是让这个LED灯为低电平。从左到右依次为01111111、10111111、11011111、11101111、11110111、11111011、11111101、11111110。其中1就是高电平、0位低电平,为低电平时LED点亮。
代码如下
#include <reg52.h> //定义单片机的一些特殊功能寄存器
sbit led1=P2^0; //定义指定LED灯的管脚
sbit led2=P2^1;
sbit led3=P2^2;
sbit led4=P2^3;
sbit led5=P2^4;
sbit led6=P2^5;
sbit led7=P2^6;
sbit led8=P2^7;
void delay(unsigned int i) //延时函数。unsigned int定义无符号整型,范围0-655535
{
while(i--); //i=1时,大约延时10us
}
void main() //主函数,程序从这里开始执行
{
while(1)
{
led1=0; //0表示低电平,led1点亮
delay(5000);
led1=1; //1表示高电平,led1熄灭
delay(5000);
led2=0; //0表示低电平,led2点亮
delay(5000);
led2=1; //1表示高电平,LED2熄灭
delay(5000);
led3=0; //0表示低电平,LED3点亮
delay(5000);
led3=1; //1表示高电平,LED3熄灭
delay(5000);
led4=0; //0表示低电平,LED4点亮
delay(5000);
led4=1; //1表示高电平,LED4熄灭
delay(5000);
led5=0; //0表示低电平,LED5点亮
delay(5000);
led5=1; //1表示高电平,LED5熄灭
delay(5000);
led6=0; //0表示低电平,LED6点亮
delay(5000);
led6=1; //1表示高电平,LED6熄灭
delay(5000);
led7=0; //0表示低电平,LED7点亮
delay(5000);
led7=1; //1表示高电平,LED7熄灭
delay(5000);
led8=0; //0表示低电平,LED8点亮
delay(5000);
led8=1; //1表示高电平,LED8熄灭
delay(5000);
}
}
最基础最原始的流水灯方式,就是单纯让LED按照顺序依次点亮,从而达到流水灯的效果,看似笨拙、程序繁多,却突出流水灯的思想和原理,为后面库函数、左移右移、数组索引法奠定基础。
2.2 移位法实现LED流水灯
从左开始循环
#include <reg51.h>
void delay(unsigned int i) //延时函数
{
while(i--);
}
void main(void) //主函数,程序从这里开始执行
{
int j; //引入变量,定义字符
while(1)
{
P2=0xfe; //即11111110,将8个LED的状态赋值给P2
delay(50000);
for(j=0;j<8;j++) //循环8次,因为有8个LED灯
{
P2=P2<<1 | 0x01; //实现程序左移1位,或运算,有1为1,全0为0
delay(50000);
}
}
}
那么右循环就是与上面相反
#include <reg51.h>
void delay(unsigned int i) //延时函数
{
while(i--);
}
void main(void) //主函数,程序从这里开始执行
{
int j; //定义字符
while(1)
{
P2=0x7f; //即01111111,将8个LED的状态赋值给P2
delay(50000);
for(j=0;j<8;j++) //循环8次,因为有8个LED灯
{
P2=P2>>1 | 0x80; //实现程序右移1位,或运算,有1为1,全0为0
delay(50000);
}
}
}
还有其他方法可以实现流水灯,小伙伴们自己探索吧