PWM基本参数
电平标准
PWM波形中有高电平和低电平两种状态
周期和频率
- 周期是指PWM信号从一个上升沿到下一次上升沿所需要的时间
- 频率即为周期的倒数
占空比
在一个脉冲周期内,高电平时间占整个周期的比值称为占空比
PWM控制LED亮度的原理
- 当周期T恒定时,一个周期内LED的平均功率是由引脚低电平持续时间t决定的,而低电平持续时间由PWM占空比控制
- 因此通过控制PWM的占空比,即可控制LED熄灭与亮起的时长,最终改变其亮度
PWM输出原理
输出PWM信号
- 首先通过代码位定义LED
sbit LED1 = P2 ^ 4;
- 在主函数中设定定时器0定时为100us
TMOD = 0x02; // 设置定时器0为工作模式2(8位自动重装载定时器)
TH0 = 0x9C; // 设置定时器0重装载值
TL0 = 0x9C; // 设置定时器0计数初值,定时时间为100us
TR0 = 1; // 打开定时器0
- 反复执行10ms记数
static int s_iCnt1 = 0;
s_iCnt1++;
if (s_iCnt1 >= 100) // PWM周期控制,周期为100 * 100us = 10ms
{
s_iCnt1 = 0; // 清零10ms计数变量
}
- 当s_iCnt1小于50时LED1亮起,大于50时LED1熄灭
static int s_iDuty = 50;
if (s_iCnt1 <= s_iDuty) // 若当前小于占空比
{
LED = 0; // LED1亮起
}
else
{
LED1 = 1;
}
按照规律调节PWM占空比
- 定时器0中断每100us触发一次,每次触发令s_iCnt2加1,计数到200时清零,既能反复执行20ms计数
static int s_iCnt2 = 0;
s_iCnt2++;
if (s_iCnt2 >= 200)
{
s_iCnt2 = 0;
}
- 调整占空比
static int s_iCnt2 = 0;
static char s_iFlag = 0;
s_iCnt2++;
if (s_iCnt2 >= 200) // 调节占空比,周期为200 * 100us = 20ms,用于控制呼吸快慢
{
s_iCnt2 = 0;
// 设置占空比调节标志
if (s_iDuty >= 100 && 1 == s_iFlag) // 若占空比增大到100且当前标志为增加占空比
{
s_iFlag = 0; // 设置标志为减小占空比
else if (0 == s_iDuty && 0 == s_iFlag) // 若占空比减小到0且当前标志为减小占空比
{
s_iFlag = 1; // 设置标志为增加占空比
}
// 占空比调节
if (0 == s_iFlag) // 若iFlag为0
{
s_iDuty--; // 减小占空比
}
else if (1 == s_iFlag) // 若iFlag为1
{
s_iDuty++; // 增加占空比
}
}
实例与代码解析
- 包含头文件
#include <reg52.h>
- 位定义LED
sbit LED1 = P2 ^ 4; // 定义LED1
- 编写定时器配置函数
static void InitTimer0()
{
TMOD = 0x02; // 设置定时器0为工作模式2(8位自动重装载定时器)
TH0 = 0x9C; // 设置定时器0重装载值
TL0 = 0x9C; // 设置定时器0计数初值,定时时间为100us
TR0 = 1; // 打开定时器0
}
- 编写中断初始化函数
static void InitInterrupt()
{
ET0 = 1; // 打开定时器0的中断允许
EA = 1; // 打开总中断允许
}
- 编写主函数
void main()
{
InitTimer0(); // 初始化定时器0
InitInterrupt(); // 初始化相关中断
while (1)
{
}
}
- 编写中断服务函数
void Timer0_Handler () interrupt 1
{
static unsigned int s_iCnt1 = 0; // 定义静态变量s_iCnt1作为10ms计数变量,用于控制PWM计数周期
static unsigned int s_iCnt2 = 0; // 定义静态变量s_iCnt2作为20ms计数变量,用于控制呼吸快慢
static unsigned int s_iDuty = 100; // 定义静态变量s_iDuty作为占空比
static unsigned char s_iFlag = 0; // 占空比减小或增加的标志,为0时占空比减小,为1时占空比增加
s_iCnt1++;
if (s_iCnt1 >= 100) // PWM周期控制,周期为100 * 100us = 10ms
{
s_iCnt1 = 0; // 清零10ms计数变量
}
s_iCnt2++;
if (s_iCnt2 >= 200) // 调整占空比,周期为200 * 100us = 20ms,用于控制呼吸快慢
{
s_iCnt2 = 0; // 清零20ms计数器
// 占空比调节标志
if (s_iDuty >= 100 && 1 == s_iFlag) // 若占空比增大到100且当前标志为增加占空比
{
s_iFlag = 0; // 设置标志为减小占空比
}
else if (0 == s_iDuty && 0 == s_iFlag) // 若占空比减小到0且当前标志为减小占空比
{
s_iFlag = 1; // 设置标志为增加占空比
}
// 占空比调节
if (0 == s_iFlag) // 若iFlag为0
{
s_iDuty--; // 减小占空比
}
else if (1 == s_iFlag) // 若iFlag为1
{
s_iDuty++; // 增加占空比
}
}
if (s_iCnt1 <= s_iDuty) // 控制LED的打开与关闭
{
LED1 = 1; // P2.4引脚输出高电平,关闭LED1
}
else
{
LED1 = 0;
}
}