C51_PWM与呼吸灯

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++; // 增加占空比
	}
}

实例与代码解析

  1. 包含头文件 #include <reg52.h>
  2. 位定义LED sbit LED1 = P2 ^ 4; // 定义LED1
  3. 编写定时器配置函数
static void InitTimer0()
{
    TMOD = 0x02; // 设置定时器0为工作模式2(8位自动重装载定时器)
    TH0 = 0x9C; // 设置定时器0重装载值
    TL0 = 0x9C; // 设置定时器0计数初值,定时时间为100us
    TR0 = 1; // 打开定时器0
}
  1. 编写中断初始化函数
static void InitInterrupt()
{
    ET0 = 1; // 打开定时器0的中断允许
    EA = 1; // 打开总中断允许
}
  1. 编写主函数
void main()
{
    InitTimer0(); // 初始化定时器0
    InitInterrupt(); // 初始化相关中断
    while (1)
    {
        
    }
}
  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;
    }
}
  • 24
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值