PWM控制流水灯
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
P0 &= 0xFD; //第二个灯亮 } else {
P0 |= 0x02; //第二个灯灭 } } } }
L1(22-32):这段代码实现 P0.1 输出占空比为 96%的方波,而 P0.0 恒为低。 P0.1 输出如图 3 所示(受纸张限制,图中高低电平长度比例和实际有偏差)。
(原文件名:120611_2.png) 图3
u8 i = 0; //使能独立 LED 的供电,即 LEDS6 输出低电平 LEDEN = 0; ADDR0 = 0; ADDR1 = 1; ADDR2 = 1; ADDR3 = 1; //第一个 LED 亮 P0 = 0xFE;
while(1) {
for(i=0; i<250; i++) {
if(i<10) {
timer0_init();
while(1) {} }
/*****************************************************************
函数名称:timer0_init 功 能:初始化定时器 0
*****************************************************************/
(原文件名:120611_5.png) 图6
图中的红色面积代表亮度程度。实现流水效果的方法就是:让所有的亮度依次经过在所有 LED,如图 7:
(原文件名:120611_6.png) 图7
状态的持续时间从 0-15 逐渐减小,以模拟水滴加速。 下载验证:下载到开发板上,可以看到水滴下落效果。 3.4 定时器产生 PWM 前面 3 个例子中,我们用循环语句虽然能产生占空比不同的 PWM,但 PWM 的周期不好控 制,对此,我们学习如何用定时器产生特定周期 PWM。关于 8051 定时器的使用方法,大 家可以参考例说 51 单片机的 4 章和 5 章。 我们用定时器 0 产生 PWM,代码如下: 程序清单 L4 定时器 0 产生 PWM
{
for(j=0; j<64; j++)
{
P0 = 0xFE; //以 i 为亮度级别,随着 i 的增大,占空比增大
for(k=0; k<64; k++)
{
if(k > i)
{
P0 = 0xFF;
//----------------------水滴降落过程---------------------
}
{
u8 i = 0;
u8 j = 0;
u8 k = 0;
u8 temp = 0;
//使能独立 LED 的供电,即 LEDS6 输出低电平
LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1; //开始全灭
P0 = 0xFF;
while(1)
//P0 端口输出 8 组占空比不同的 PWM
#include <reg52.h> #include "hw_config.h" #include "my_type.h" //亮度级别表 code u8 LightLevel[8]= {1,2,4,8,16,28,50,64}; //函数声明 void timer0_init(void);
void main(void)
简介 学习嵌入式第一个例子通常都是控制一个 LED 亮灭,然后是花样繁多的流水灯,但不管灯的花样如何变化,
单个 LED 的亮度没有变化,只有亮、灭两个状态,本章我们实现如何控制 LED 的亮度。 1 什么是 PWM
脉冲宽度调制(Pulse Width Modulation,简称 PWM),是利用微处理器的数字输出来对模拟电路进行控 制的一种技术。
程序清单 L2:不同占空比对 LED 亮度的控制
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h" //亮度级别表
code u8 LightLevel[8]= {0,1,2,4,8,16,32,64};
void main(void)
下载验证:下载到开发板上,可以看到 D1 到 D8 亮度逐渐增大。
3.5 亮百度文库不同的点阵
学习了用定时器产生 PWM,我们可以控制更多的 LED,比如 LED 点阵的亮度。下面的例
子实现 LED 点阵每行的亮度都不同。
程序清单 5 亮度不同的点阵
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
code u8 LightLevel[8]= {1,2,4,8,16,32,50,64}; //亮度级别表
void timer0_init(void);//函数声明
void main(void)
{
LEDEN = 0;
//使能控制点阵的译码器
ADDR3 = 0;
}
else
{
P0 = ~((~temp) << (state-7));
}
}
}
}
}
}
L2(31-46).实现水滴变大效果,这段代码的作用可用图形表达,如图 5:
(原文件名:120611_4.png) 图5
控制 D1 由暗变亮,用了 64 个亮度级别,每个级别发送 64 个脉冲。 L2(49-81).实现水滴下落。代码就不逐行解释了,大家可根据注释自己分析,主要说一下实 现的方法。 定义 LED 有 8 个亮度级别,若用开发板上的 8 个 LED 表示,如图 6:
code u8 LightTime[16]= {16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
void main(void)
{
u8 i,j,k;
u8 temp,count;
u8 state;
//使能独立 LED 的供电,即 LEDS6 输出低电平
LEDEN = 0;
(原文件名:120611_1.png) 图2 LED 硬件连接
如果 BD 口输出高低不断变化,则 LED 会闪烁;如果这种高低电平变化非常快,由于人的 视觉暂留现象,LED 就会出现不同的亮度。 3 软件设计 3.1 PWM 能否控制亮度 下面我们就用实践验证 PWM 是否能够控制 LED 的亮度,测试代码如下: 程序清单 L1: 验证 PWM 能否控制 LED 的亮度 #include <reg52.h> #include "my_type.h" #include "hw_config.h" void main(void) {
TL0 = 0xFA;
EA = 1;
//开启中断
ET0 = 1;
TR0 = 1;
//启动定时器
}
/************************************************************
函数名称:timer0_overflow 功 能:定时器 0 溢出中断
************************************************************/
for(j=0; j<64; j++)
//根据亮度表,依次确定 8 个 LED 当前状态,亮或灭
{
for(k=0; k<8; k++)
//以 j 为亮度级别,每个 LED 亮度不一样
{
if(LightLevel[k] == j)
{
temp |= (1 << k);
}
}
if(state <= 7)
{
P0 = ~((~temp) >> (7-state));
函数名称:timer0_init 功 能:初始化定时器 0
**********************************************************/
void timer0_init(void)
{
TMOD = 0x01; //运行模式 1
TH0 = 0xFF;
//10us 中断
逐渐变大,用 D1 从暗变亮模拟;第二步,水滴下落,带有拖尾效果,LED 逐个亮,移动速
度加快,且越靠前的 LED 亮度越大。
程序清单 L3 水滴流水灯
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h" //亮度级别表
code u8 LightLevel[8]= {0,1,2,4,8,16,32,64}; //水滴时间,实现加速效果
void timer0_overflow(void) interrupt TIMER0_OVERFLOW
{
u8 i,temp = 0;
static u8 count = 0;
count++;
count %= 64;
for(i=0; i<8; i++)
{
if(LightLevel[i] <= count)
{
for(i=0; i<64; i++)
//共64个脉冲
{
for(j=0; j<8; j++)
{
if(LightLevel[j] <= i)
{
temp |= (1<<j);
//左侧一个灯灭以LightLevel[j]==i为分界点灭i~64个脉冲
}
else
{
temp &= ~(1<<j);
//不变
}
在本章的应用中可以认为 PWM 就是一种方波。比如图1:
(原文件名:120611_0.png) 图1 方波
是周期为 10ms,占空比为 60%的 PWM。 占空比:高电平在一个周期之内所占的时间比率。 2 硬件设计 在例说 51 单片机的第三章,我们讲过如何控制开发板上 LED 的亮灭。首先译码器输出端 LEDS6 为低,T10 导通,给 8 个 LED 供电,然后通过缓冲器 8 个输出端 BD0~BD7 的控制 LED 的亮灭(低亮高灭)。
//使能独立 LED 的供电,即 LEDS6 输出低电平
{
LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
timer0_init();
while(1) { } }
/**********************************************************
void timer0_init(void)
{
TMOD = 0x01; //运行模式 1
TH0 = 0xFF;
//中断时间 10us
TL0 = 0xF7;
EA = 1;
//开启中断
ET0 = 1;
TR0 = 1;
//启动定时器
}
/*****************************************************************
下载验证:从开发板上可以看到运行效果,D1 比 D2 亮。(这里说明一点:当 P0 输出低电
平时,LED 亮,所以,PWM 的占空比越小越亮)。
3.2 产生 8 个亮度级别
3.1 节的例子证实了我们的设想,PWM 可控制 LED 的亮度,下面我们设计几组占空比不同
的 PWM,看看对 LED 亮度的控制效果。代码如下:
}
}
}
for(state=0; state<16; state++)
//每一状态维持 LightTime[state]个脉冲
{
for(count=0; count<=LightTime[state]; count++)
{//temp 记录 8 个 LED 的状态,0 代表亮,1 代表灭
temp = 0x00; //一个脉冲长度 j 从 0 到 63
}
P0 = temp;
}
}
}
L2(29-45).此段程序是让 P0 口输出 8 组占空比不同的 PWM,如图 4:
(原文件名:120611_3.png) 图4
下载验证:从开发板上可以看到运行效果,从 D1 到 D8 的亮度逐渐增大。
3.3 水滴下落效果
根据 PWM 可控制 LED 亮度的原理,我们用 8 个 LED 实现水滴下落的效果。第一步,水滴
{
temp |= (1<<i);
}
else
{
temp &= ~(1<<i);
}
}
P0 = temp;
TR0 = 0;
TH0 = 0xFF;
//重新赋值
TL0 = 0xF7; TR0 = 1; }
L4(32).初始化定时器 0,没 10us 产生一次中断。 L4(55-65).控制输出 8 组不同占空比的 PWM。这段代码功能和程序清单 2 中的功 能一致。
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
while(1)
//开始全灭
{
P0 = 0xFF; //---------------水滴逐渐变大(第一个 LED 亮度逐渐变大)---------
for(i=0; i<64; i++)
//一个亮度级别发送 64 个脉冲
P0 |= 0x02; //第二个灯灭 } } } }
L1(22-32):这段代码实现 P0.1 输出占空比为 96%的方波,而 P0.0 恒为低。 P0.1 输出如图 3 所示(受纸张限制,图中高低电平长度比例和实际有偏差)。
(原文件名:120611_2.png) 图3
u8 i = 0; //使能独立 LED 的供电,即 LEDS6 输出低电平 LEDEN = 0; ADDR0 = 0; ADDR1 = 1; ADDR2 = 1; ADDR3 = 1; //第一个 LED 亮 P0 = 0xFE;
while(1) {
for(i=0; i<250; i++) {
if(i<10) {
timer0_init();
while(1) {} }
/*****************************************************************
函数名称:timer0_init 功 能:初始化定时器 0
*****************************************************************/
(原文件名:120611_5.png) 图6
图中的红色面积代表亮度程度。实现流水效果的方法就是:让所有的亮度依次经过在所有 LED,如图 7:
(原文件名:120611_6.png) 图7
状态的持续时间从 0-15 逐渐减小,以模拟水滴加速。 下载验证:下载到开发板上,可以看到水滴下落效果。 3.4 定时器产生 PWM 前面 3 个例子中,我们用循环语句虽然能产生占空比不同的 PWM,但 PWM 的周期不好控 制,对此,我们学习如何用定时器产生特定周期 PWM。关于 8051 定时器的使用方法,大 家可以参考例说 51 单片机的 4 章和 5 章。 我们用定时器 0 产生 PWM,代码如下: 程序清单 L4 定时器 0 产生 PWM
{
for(j=0; j<64; j++)
{
P0 = 0xFE; //以 i 为亮度级别,随着 i 的增大,占空比增大
for(k=0; k<64; k++)
{
if(k > i)
{
P0 = 0xFF;
//----------------------水滴降落过程---------------------
}
{
u8 i = 0;
u8 j = 0;
u8 k = 0;
u8 temp = 0;
//使能独立 LED 的供电,即 LEDS6 输出低电平
LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1; //开始全灭
P0 = 0xFF;
while(1)
//P0 端口输出 8 组占空比不同的 PWM
#include <reg52.h> #include "hw_config.h" #include "my_type.h" //亮度级别表 code u8 LightLevel[8]= {1,2,4,8,16,28,50,64}; //函数声明 void timer0_init(void);
void main(void)
简介 学习嵌入式第一个例子通常都是控制一个 LED 亮灭,然后是花样繁多的流水灯,但不管灯的花样如何变化,
单个 LED 的亮度没有变化,只有亮、灭两个状态,本章我们实现如何控制 LED 的亮度。 1 什么是 PWM
脉冲宽度调制(Pulse Width Modulation,简称 PWM),是利用微处理器的数字输出来对模拟电路进行控 制的一种技术。
程序清单 L2:不同占空比对 LED 亮度的控制
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h" //亮度级别表
code u8 LightLevel[8]= {0,1,2,4,8,16,32,64};
void main(void)
下载验证:下载到开发板上,可以看到 D1 到 D8 亮度逐渐增大。
3.5 亮百度文库不同的点阵
学习了用定时器产生 PWM,我们可以控制更多的 LED,比如 LED 点阵的亮度。下面的例
子实现 LED 点阵每行的亮度都不同。
程序清单 5 亮度不同的点阵
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
code u8 LightLevel[8]= {1,2,4,8,16,32,50,64}; //亮度级别表
void timer0_init(void);//函数声明
void main(void)
{
LEDEN = 0;
//使能控制点阵的译码器
ADDR3 = 0;
}
else
{
P0 = ~((~temp) << (state-7));
}
}
}
}
}
}
L2(31-46).实现水滴变大效果,这段代码的作用可用图形表达,如图 5:
(原文件名:120611_4.png) 图5
控制 D1 由暗变亮,用了 64 个亮度级别,每个级别发送 64 个脉冲。 L2(49-81).实现水滴下落。代码就不逐行解释了,大家可根据注释自己分析,主要说一下实 现的方法。 定义 LED 有 8 个亮度级别,若用开发板上的 8 个 LED 表示,如图 6:
code u8 LightTime[16]= {16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
void main(void)
{
u8 i,j,k;
u8 temp,count;
u8 state;
//使能独立 LED 的供电,即 LEDS6 输出低电平
LEDEN = 0;
(原文件名:120611_1.png) 图2 LED 硬件连接
如果 BD 口输出高低不断变化,则 LED 会闪烁;如果这种高低电平变化非常快,由于人的 视觉暂留现象,LED 就会出现不同的亮度。 3 软件设计 3.1 PWM 能否控制亮度 下面我们就用实践验证 PWM 是否能够控制 LED 的亮度,测试代码如下: 程序清单 L1: 验证 PWM 能否控制 LED 的亮度 #include <reg52.h> #include "my_type.h" #include "hw_config.h" void main(void) {
TL0 = 0xFA;
EA = 1;
//开启中断
ET0 = 1;
TR0 = 1;
//启动定时器
}
/************************************************************
函数名称:timer0_overflow 功 能:定时器 0 溢出中断
************************************************************/
for(j=0; j<64; j++)
//根据亮度表,依次确定 8 个 LED 当前状态,亮或灭
{
for(k=0; k<8; k++)
//以 j 为亮度级别,每个 LED 亮度不一样
{
if(LightLevel[k] == j)
{
temp |= (1 << k);
}
}
if(state <= 7)
{
P0 = ~((~temp) >> (7-state));
函数名称:timer0_init 功 能:初始化定时器 0
**********************************************************/
void timer0_init(void)
{
TMOD = 0x01; //运行模式 1
TH0 = 0xFF;
//10us 中断
逐渐变大,用 D1 从暗变亮模拟;第二步,水滴下落,带有拖尾效果,LED 逐个亮,移动速
度加快,且越靠前的 LED 亮度越大。
程序清单 L3 水滴流水灯
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h" //亮度级别表
code u8 LightLevel[8]= {0,1,2,4,8,16,32,64}; //水滴时间,实现加速效果
void timer0_overflow(void) interrupt TIMER0_OVERFLOW
{
u8 i,temp = 0;
static u8 count = 0;
count++;
count %= 64;
for(i=0; i<8; i++)
{
if(LightLevel[i] <= count)
{
for(i=0; i<64; i++)
//共64个脉冲
{
for(j=0; j<8; j++)
{
if(LightLevel[j] <= i)
{
temp |= (1<<j);
//左侧一个灯灭以LightLevel[j]==i为分界点灭i~64个脉冲
}
else
{
temp &= ~(1<<j);
//不变
}
在本章的应用中可以认为 PWM 就是一种方波。比如图1:
(原文件名:120611_0.png) 图1 方波
是周期为 10ms,占空比为 60%的 PWM。 占空比:高电平在一个周期之内所占的时间比率。 2 硬件设计 在例说 51 单片机的第三章,我们讲过如何控制开发板上 LED 的亮灭。首先译码器输出端 LEDS6 为低,T10 导通,给 8 个 LED 供电,然后通过缓冲器 8 个输出端 BD0~BD7 的控制 LED 的亮灭(低亮高灭)。
//使能独立 LED 的供电,即 LEDS6 输出低电平
{
LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
timer0_init();
while(1) { } }
/**********************************************************
void timer0_init(void)
{
TMOD = 0x01; //运行模式 1
TH0 = 0xFF;
//中断时间 10us
TL0 = 0xF7;
EA = 1;
//开启中断
ET0 = 1;
TR0 = 1;
//启动定时器
}
/*****************************************************************
下载验证:从开发板上可以看到运行效果,D1 比 D2 亮。(这里说明一点:当 P0 输出低电
平时,LED 亮,所以,PWM 的占空比越小越亮)。
3.2 产生 8 个亮度级别
3.1 节的例子证实了我们的设想,PWM 可控制 LED 的亮度,下面我们设计几组占空比不同
的 PWM,看看对 LED 亮度的控制效果。代码如下:
}
}
}
for(state=0; state<16; state++)
//每一状态维持 LightTime[state]个脉冲
{
for(count=0; count<=LightTime[state]; count++)
{//temp 记录 8 个 LED 的状态,0 代表亮,1 代表灭
temp = 0x00; //一个脉冲长度 j 从 0 到 63
}
P0 = temp;
}
}
}
L2(29-45).此段程序是让 P0 口输出 8 组占空比不同的 PWM,如图 4:
(原文件名:120611_3.png) 图4
下载验证:从开发板上可以看到运行效果,从 D1 到 D8 的亮度逐渐增大。
3.3 水滴下落效果
根据 PWM 可控制 LED 亮度的原理,我们用 8 个 LED 实现水滴下落的效果。第一步,水滴
{
temp |= (1<<i);
}
else
{
temp &= ~(1<<i);
}
}
P0 = temp;
TR0 = 0;
TH0 = 0xFF;
//重新赋值
TL0 = 0xF7; TR0 = 1; }
L4(32).初始化定时器 0,没 10us 产生一次中断。 L4(55-65).控制输出 8 组不同占空比的 PWM。这段代码功能和程序清单 2 中的功 能一致。
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
while(1)
//开始全灭
{
P0 = 0xFF; //---------------水滴逐渐变大(第一个 LED 亮度逐渐变大)---------
for(i=0; i<64; i++)
//一个亮度级别发送 64 个脉冲