一、原理部分
1、脉宽调制(PWM)基本原理
控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等但宽度不一致的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,既可改变逆变电路输出电压的大小,也可改变输出频率。
简单来说,就是通过调节一个周期内高电平的占比来实现对电压的控制,如上图,第一个脉冲为50%高电平、50%低电平,占空比为50%,第二个25%高电平、75%低电平,占空比为25%。
2、 PWM的实现
一般使用定时器,实现的流程为:
①编写定时器初始化函数,初始化定时器,设置定时器的THx、TLx的初始值
②编写中断服务函数,函数参数可以为占空比,在这个函数中实现PWM脉冲信号的周期设置与信号发生
定时器的设置可以观看我上一节的定时器原理及其应用。下面通过一个实际案例了解一下PWM的应用
二、程序案例
例子:通过按键S7实现对L1指示灯的4级控制,占空比分别为10%、50%、90%、0%
#include "reg52.h"
sbit L1=P0^0;//定义引脚
sbit S7=P3^0;
/*****************************************************************
*@Function: SelectHC573 //
*@Description: 锁存器选择,这里只用到LED相关的锁存器 //
*@Input:无 //
*@Output:无 //
*@Return:无 //
*@Others:无 //
/*****************************************************************/
void SelectHC573()
{
P2=P2&0x1f|0x80;
}
unsigned char count=0;
unsigned char PWM_duty=0;
/*****************************************************************
*@Function:InitTimer0 //
*@Description: 定时器0初始化 //
*@Input:无 //
*@Output: 无//
*@Return: 无 //
*@Others: 无 //
/*****************************************************************/
void InitTimer0()
{
TMOD=0x01;//设置定时器模式 16位不可重装载模式
TH0=(65536-100)/256;//设置定时器初始计数值,为100us
TL0=(65536-100)%256;
ET0=1;//使能定时器0中断
EA=1;//使能总中断
}
/*****************************************************************
*@Function: ServiceTimer0 //
*@Description: 定时器中断服务函数 //
*@Input:无 //
*@Output:无 //
*@Return:无 //
*@Others: 无 //
/*****************************************************************/
void ServiceTimer0() interrupt 1
{
TH0=(65535-100)/256;//重新设置定时器初始值
TL0=(65535-100)%256;
count++;//计数变量加1
// if(count<=PWM_duty)
// {
// L1=0;
// }else if(count<100)
// {
// L1=0;
// }else if(count==100)
// {
// count=0;
// }
if(count==PWM_duty)//如果等于设置的占空比(100份占比多少份)
{
L1=1;//将L1灯开启
}else if(count==100)//计数变量如果等于100,即100个100us后,为一个周期
{
L1=0;//关闭L1灯
count=0;//计数变量置0,重新计数
}
}
/*****************************************************************
*@Function: DelayK //
*@Description:用于按键延时 //
*@Input:无 //
*@Output:无 //
*@Return:无 //
*@Others:无 //
/*****************************************************************/
void DelayK(unsigned char t)
{
while(t--);
}
unsigned char stat=0;//设置状态变量
/*****************************************************************
*@Function: ScanKeys //
*@Description: 按键扫描S7 //
*@Input:无 //
*@Output:无 //
*@Return: 无 //
*@Others:无 //
/*****************************************************************/
void ScanKeys()
{
if(S7==0)//若S7按下
{
DelayK(100);
if(S7==0)
{
switch(stat)//switch实现S7四个状态,占空比分别为10%、50%、90%、0,实现对L1的亮度控制
{
case 0:
L1=0;
TR0=1;
PWM_duty=10;
stat=1;
break;
case 1:
L1=0;
TR0=1;
PWM_duty=50;
stat=2;
break;
case 2:
L1=0;
TR0=1;
PWM_duty=90;
stat=3;
break;
case 3:
L1=1;
TR0=0;
stat=0;
break;
}
while(S7==0);
}
}
}
void main()
{
SelectHC573();
L1=1;
InitTimer0();
while(1)
{
ScanKeys();
}
}
感谢大家的观看
欢迎大家提出问题并指正~