第十五届蓝桥杯单片机组——利用定时器生成PWM波

本文介绍了PWM的基本概念,包括其工作原理和两个关键参数(频率和占空比),并详细讲解了如何在51单片机上通过定时器和中断实现PWM,给出了代码示例以控制设备功率。
摘要由CSDN通过智能技术生成

一、PWM介绍

  PWM是脉宽调制(Pulse Width Modulation)的缩写,你可以把它想象成一个迷你的开关,这个开关可以非常非常快地打开和关闭。正如你在开关灯时,灯是全亮或全暗,同样,这个小开关也只有两种状态:全开(满电)或全关(没电)。但是,如果我们足够快地打开和关闭这个开关,我们就可以获得介于全开和全关之间的任何效果。这就是PWM的原理。
  举个例子,假设你的小车上有一个可以用PWM控制的电动风扇。如果你想让风扇全速运转,你就让开关一直保持打开状态(这就像把灯开到最大一样)。如果你想让风扇停止运转,你就让开关保持关闭状态(就像把灯关掉一样)。但是,如果你想让风扇以半速运转,那么你可以让该开关半时间打开,半时间关闭。这样,风扇就会以你想要的速度运转了。
  总的来说,PWM就像是一个快速的开关,可以控制各种设备的功率,从而改变它们的工作状态。不论是控制小车的速度,亮度的LED灯,还是家里的空调,使用PWM的设备都无处不在。

二、PWM的两个重要参数

2.1 频率

频率是指PWM信号每秒钟重复的次数。例如,如果一个PWM信号的频率是100Hz,那就意味着这个信号在每秒钟内会重复100次。

2.2 占空比

占空比是指PWM信号在一个周期内处于"高"电平(通常是电压的最大值)的时间占整个周期时间的百分比。例如,如果一个PWM信号的频率是100Hz,每个周期的时间就是1/100秒,如果在这个周期内,它有1/2的时间处于高电平,那么我们就说它的占空比是50%。

三、51生成PWM

3.1 如何实现

有接触过51就可以知道,51的定时器不像STM32可以通过配置相关寄存器直接输出PWM。那么51怎么实现PWM呢?

具体做法:
在定时器中断中不断翻转IO状态来模拟PWM,比如每隔100us进入一次定时器中断,进入100次中断算一个周期,(T=100us*100=10ms)那么PWM的频率就是 1 s / 100 u s ∗ 100 = 100 H z 1s/100us*100=100Hz 1s/100us100=100Hz
在第50次进入中断时,翻转一次IO口状态,那么我们就生成了占空比为50%,频率为100Hz的PWM波。

3.2 定时器初始化

PWM周期和占空比控制精度决定了定时器的初始化,例如PWM频率为100Hz,控制精度为1%,那么定时器进入中断的频率就为: 1 / 100 H z ∗ 100 = 100 u s 1/100Hz*100=100us 1/100Hz100=100us
如果我们想把控制精度提高到0.1%,那么定时器进入中断的频率为:
1 / 100 H z ∗ 1000 = 10 u s 1/100Hz*1000=10us 1/100Hz1000=10us

三、代码示例

这里演示的PWM频率为100Hz,控制精度为1%。
这里我在keyscan里面写了一行duty+=25;也就是S7按键每按下一次,LED灯变亮一点,一共有四个档位,大家可以把代码直接复制到工程里面直接使用。

#include <stc15f2k60s2.h>

/************* bit define ***************/
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;

sbit C1=P4^4;
sbit C2=P4^2;
sbit C3=P3^5;
sbit C4=P3^4;
/************* end define   ***************/

volatile unsigned char count=0;
unsigned char duty=0;

void Delay20ms(void)	//@12.000MHz
{
	unsigned char data i, j;

	i = 234;
	j = 115;
	do
	{
		while (--j);
	} while (--i);
}


void selectHC573(unsigned char num)  
{
	switch(num)
	{
		case 4:
			P2=(P2 & 0x1f) | 0x80;
			break;
		case 5:
			P2=(P2 & 0x1f) | 0xa0;
			break;
		case 6:
			P2=(P2 & 0x1f) | 0xc0;
			break;
		case 7:
			P2=(P2 & 0x1f) | 0xe0;
			break;
		case 0:
			P2=(P2 & 0x1f) | 0x00;
			break;
	}
}

void system_Init()
{
	selectHC573(5);
	P0=0x00;
	selectHC573(0);
	selectHC573(4);
	P0=0xff;
	selectHC573(0);
}

void keyscan()
{
    char keyID=-1;
    R1=0;R2=1;R3=1;R4=1;        //扫描第一行
    C1=1;C2=1;C3=1;C4=1;
    if(C1==0)
    {
        Delay20ms();
        if(C1==0)
        {
            while(C1==0);
            duty+=25;
            if(duty>100)
            {
                duty=0;
            }
        }
    }
}

void Timer0_Isr(void) interrupt 1
{
    count++;
    if(count==100)     // 一个周期结束
    {
        count=0;
    }
    if(count <= duty)
    {
        selectHC573(4);
        P0=~0x01;           // 点亮LED灯
        selectHC573(0);
    }
    else
    {
        selectHC573(4);
        P0=~0x00;           // 熄灭LED灯
        selectHC573(0);
    }
}

void Timer0_Init(void)		//100us@12.000MHz
{
	AUXR &= 0x7F;			//Timer clock is 12T mode
	TMOD &= 0xF0;			//Set timer work mode
	TL0 = 0x9C;				//Initial timer value
	TH0 = 0xFF;				//Initial timer value
	TF0 = 0;				//Clear TF0 flag
	TR0 = 1;				//Timer0 start run
	ET0 = 1;				//Enable timer0 interrupt
    
}


int main()
{
    system_Init();
    Timer0_Init();	
    
    EA=1;
    while(1)
    {
        keyscan();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值