简介简介简介简介
学习嵌入式第一个例子通常都是控制一个 LED 亮灭,然后是花样繁多的流水灯,但不管灯
的花样如何变化,单个 LED 的亮度没有变化,只有亮、灭两个状态,本章我们实现如何控制 LED
的亮度。
1111 什么是什么是什么是什么是 PWMPWMPWMPWM
脉冲宽度调制(Pulse Width Modulation,简称 PWM),是利用微处理器的数字输出来
对模拟电路进行控制的一种技术。在本章的应用中可以认为 PWM 就是一种方波。比如图 1:
是周期为 10ms,占空比为 60%的 PWM。
占空比:高电平在一个周期之内所占的时间比率。
图 1 方波
2222 硬件设计
硬件设计硬件设计硬件设计
在例说 51 单片机的第三章,我们讲过如何控制开发板上 LED 的亮灭。首先译码器输出端
LEDS6 为低,T10 导通,给 8 个 LED 供电,然后通过缓冲器 8 个输出端 BD0~BD7 的控制 LED
的亮灭(低亮高灭)。
图 2 LED 硬件连接
如果 BD 口输出高低不断变化,则 LED 会闪烁;如果这种高低电平变化非常快,由于人的视觉
暂留现象,LED 就会出现不同的亮度。
3333 软件设计
软件设计软件设计软件设计
3.13.13.13.1 PWMPWMPWMPWM 能否控制亮度
能否控制亮度
能否控制亮度
能否控制亮度
下面我们就用实践验证 PWM 是否能够控制 LED 的亮度,测试代码如下:
能否控制能否控制能否控制 LEDLEDLEDLED 的亮度的亮度的亮度的亮度
程序清单程序清单程序清单 L1L1L1L1:::: 验证验证验证验证 PWMPWMPWMPWM 能否控制
程序清单
#include
#include "my_type.h"
#include "hw_config.h"
void main(void)
{
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++) //第 22 行
{
if(i<10)
{
P0 &= 0xFD;
//第二个灯亮
}
else
{
}
P0 |= 0x02;
//第二个灯灭
} //第 32 行
}
}
L1(22-32):这段代码实现 P0.1 输出占空比为 96%的方波,而 P0.0 恒为低。
P0.1 输出如图 3 所示(受纸张限制,图中高低电平长度比例和实际有偏差)。
图 3
下载验证:从开发板上可以看到运行效果,D1 比 D2 亮。(这里说明一点:当 P0 输出低电平时,
LED 亮,所以,PWM 的占空比越小越亮)。
3.23.23.23.2 产生产生产生产生 8888 个亮度级别
个亮度级别
个亮度级别
个亮度级别
3.1 节的例子证实了我们的设想,PWM 可控制 LED 的亮度,下面我们设计几组占空比不
同的 PWM,看看对 LED 亮度的控制效果。代码如下:
:不同占空比对 LEDLEDLEDLED 亮度的控制
:不同占空比对
程序清单程序清单程序清单 L2L2L2L2:不同占空比对
亮度的控制
:不同占空比对
亮度的控制
程序清单
亮度的控制
#include
#include "hw_config.h"
#include "my_type.h"
//亮度级别表
code u8 LightLevel[8]={0,1,2,4,8,16,32,64};
void main(void)
{
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
for(i=0; i<64; i++) //第 29 行
{
for(j=0; j<8; j++)
{
if(LightLevel[j] <= i)
{
temp |= (1<
图 4
下载验证:从开发板上可以看到运行效果,从 D1 到 D8 的亮度逐渐增大。
3.33.33.33.3 水滴下落效果
水滴下落效果
水滴下落效果
水滴下落效果
根据 PWM 可控制 LED 亮度的原理,我们用 8 个 LED 实现水滴下落的效果。第一步,水
滴逐渐变大,用 D1 从暗变亮模拟;第二步,水滴下落,带有拖尾效果,LED 逐个亮,移动速
度加快,且越靠前的 LED 亮度越大。
程序清单程序清单程序清单 L3L3L3L3 水滴流水灯
水滴流水灯
水滴流水灯
程序清单
水滴流水灯
#include
#include "hw_config.h"
#include "my_type.h"
//亮度级别表
code u8 LightLevel[8]={0,1,2,4,8,16,32,64};
//水滴时间,实现加速效果
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;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
while(1)
{
//开始全灭
P0 = 0xFF;
//---------------水滴逐渐变大(第一个 LED 亮度逐渐变大)---------
for(i=0; i<64; i++)
{
//一个亮度级别发送 64 个脉冲
for(j=0; j<64; j++)
{
P0 = 0xFE;
//以 i 为亮度级别,随着 i 的增大,占空比增大
for(k=0; k<64; k++)
{
if(k > i)
{
P0 = 0xFF;
}
}
}
}
//----------------------水滴降落过程---------------------
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
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));
P0 = ~((~temp) << (state-7));
}
else
{
}
}
}
}
}
}
L2(31-46).实现水滴变大效果,这段代码的作用可用图形表达,如图 5:
图 5
控制 D1 由暗变亮,用了 64 个亮度级别,每个级别发送 64 个脉冲。
L2(49-81).实现水滴下落。代码就不逐行解释了,大家可根据注释自己分析,主要说一下实现
的方法。
定义 LED 有 8 个亮度级别,若用开发板上的 8 个 LED 表示,如图 6:
图中的红色面积代表亮度程度。实现流水效果的方法就是:让所有的亮度依次经过在所有 LED,
如图 7:
图 6