51单片机定时中断利用修改pwm的占空比和周期

当前只可调占空比,怎么改成周期、占空比都可调,周期3ms~7ms,步长0.5ms,改周期时占空比不能改变,且不能出现直流。

#include
#include
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
unsigned char PWMH; //高电平脉冲的个数
unsigned char PWM; //PWM周期
unsigned char COUNTER; 
void K1CHECK();
void K2CHECK();
void INTTO() interrupt 1 
{
 COUNTER++; //计数值加1
 if((COUNTER!=PWMH)&&(COUNTER==PWM)) //如果等于高电平脉冲数
  {
   COUNTER=1; //计数器复位
   P1_0=1; //P1.0为高电平
  }
 else if(COUNTER==PWMH)
  P1_0=0; //P1.0变为低电平
}
void main()
{
 PWMH=0x02; 
 COUNTER=0x01;
 PWM=0x15; 
 TMOD=0x02; //定时器0在模式2下工作
 TL0=0x38; //定时器每200us产生一次溢出
 TH0=0x38; //自动重装的值
 ET0=1; //使能定时器0中断
 EA=1; //使能总中断
 TR0=1; //开始计时
 while(1)
 {
  if(P1_1==0) 
   K1CHECK();//扫描KEY1,如果按下KEY1,跳转到KEY1处理程序
  if(P1_2==0)
   K2CHECK();//扫描KEY2
 }
}
void K1CHECK()
 while(P1_1==0);
  if(PWMH!=PWM)
   {
    PWMH++;
    if(PWMH==PWM)
     {
      TR0=0;
      P1_0=1; 
     }
   else
   {
    if(PWMH==0x02)
     {TR0=1;} 
   }
   }
}
void K2CHECK()
{
 unsigned char TEMP;
 while(P1_2==0);
 if(PWMH!=0x01)
 {
  PWMH--;
  TEMP=PWM;
  TEMP--;
  if(PWMH==0x01)
  {
   TR0=0;
   P1_0=0; 
  }
  else
  {
  if(PWMH==TEMP)
  {TR0=1;} 
  }
 }
}

  • 这篇博客: 电机控制基础——定时器基础知识与PWM输出原理中的 5 测试效果 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 将程序下载到板子,我用的一块STM32F407的板,A6引脚上接了一个LED灯,实际效果的LED逐渐变亮,再逐渐变暗,依次循环。

    再通过逻辑分析仪来查看实际的输出波形,如下图,测得的pwm周期0.5ms(频率2kHz),与软件中设定的一致。

    在某一时刻,脉宽55us。

    在另一时刻,脉宽0.365ms,即实现了PWM脉宽的动态调整。