搜索
bottom↓
回复: 0

关于pwm波问题!程序已经贴出!

[复制链接]

出0入0汤圆

发表于 2014-6-20 10:09:07 | 显示全部楼层 |阅读模式
大家好,有问题求助于大家。我现在在做的是:利用一个定时器控制4个IO口输出不同频率的占空比可改pwm波,频率分别是333,444,666,888hz。输出的顺序是444,666,888,333,每个频率大约0.5s左右,它们是连续输出的。每个频率占空比变化是这样的:从0%到50%耗时40ms左右,保持50%占空比不变194ms左右,50%到2%占空比耗时250ms左右,前面的三个时间可以适当的调整,只要不偏很远就行。也就是说第一个频率变化0.5s后,输出第二个频率,依次类推。我下面贴出自己写的程序,现在用示波器测试时,就是第一个频率到第二个频率之间的变化不好看,它是直接跳变过去,而不是连续变化。还有每个频率的波形变化不是很平整,不太像一个光滑的包络。


#include"STC89C516RD.H"

sbit PWMOUT1 = P0^0;
sbit PWMOUT2 = P0^1;          
sbit PWMOUT3 = P0^2;
sbit PWMOUT4 = P0^3;


unsigned long PeriodCnt = 0; //PWM周期计数值
unsigned char HReloadH = 0;  //高电平重载值的高字节
unsigned char HReloadL = 0;  //高电平重载值的低字节
unsigned char LReloadH = 0;  //低电平重载值的高字节
unsigned char LReloadL = 0;  //低电平重载值的低字节
                                 

static unsigned char index1 = 0;
static unsigned char index2 = 0;


unsigned char flag_444 = 1;                   //播出的第一个频率
unsigned char flag_333 = 0;
unsigned char flag_888 = 0;
unsigned char flag_666 = 0;



unsigned char a=0;                             //444hz,666hz,888hz,333hz的标志位
unsigned char b=0;                               

unsigned char flag1_2=1;        //进入该频率的标志 ,对应444hz
unsigned char flag1_0=0;
unsigned char flag1_5=0;
//
unsigned char flag2_2=1;        //进入该频率的标志 ,对应666hz
unsigned char flag2_0=0;
unsigned char flag2_5=0;

unsigned char flag3_2=1;        //进入该频率的标志 ,对应888hz
unsigned char flag3_0=0;
unsigned char flag3_5=0;

unsigned char flag4_2=1;        //进入该频率的标志 ,对应333hz
unsigned char flag4_0=0;
unsigned char flag4_5=0;


void ConfigPWM1(unsigned int fr, unsigned char dc);


void main ()
{
  
    EA = 1;                                //开总中断

while(1)             
  {
    if( flag_444 == 1 )
    {
         ConfigPWM1(444,5); //配置并启动PWM
         //PWMOUT1 = 1;     //输出高电平
    }

        else if( flag_666 == 1 )
        {
         ConfigPWM1(666,5);
         //PWMOUT2 = 1;     //输出高电平
        }

        else if( flag_888 == 1 )
        {
         ConfigPWM1(888,5);
         //PWMOUT3 = 1;     //输出高电平
        }

        else if( flag_333 == 1 )
        {
         ConfigPWM1(333,5);
         //PWMOUT4 = 1;     //输出高电平
        }
  }
}



void ConfigPWM1(unsigned int fr, unsigned char dc)  //PWM配置函数,fr-频率,dc-占空比
{
    unsigned int high, low;
   
    PeriodCnt = (12000000 / 12) / fr;  //计算一个周期所需的计数值
    high = (PeriodCnt * dc) / 100;     //计算高电平所需的计数值
    low  = PeriodCnt - high;           //计算低电平所需的计数值
    high = 65536 - high + 13 ;          //计算高电平的定时器重载值并修正
    low  = 65536 - low + 13 ;          //计算低电平的定时器重载值并修正
   
    HReloadH = (unsigned char)(high >> 8);  //高电平重载值拆分为高低字节
    HReloadL = (unsigned char)high;
    LReloadH = (unsigned char)(low >> 8);   //低电平重载值拆分为高低字节
    LReloadL = (unsigned char)low;

    if( flag_444 == 1 )
        {
         PWMOUT1 = 1;
        }

          if( flag_666 == 1 )
        {
         PWMOUT2 = 1;
        }

          if( flag_888 == 1 )
        {
         PWMOUT3 = 1;
        }

          if( flag_333 == 1 )
        {
         PWMOUT4 = 1;
        }
   
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = HReloadH; //加载T0重载值
    TL0 = HReloadL;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0

}


void AdjustDutyCycle(unsigned char dc)  //占空比调整函数,频率不变只调整占空比
{
    unsigned int  high, low;
   
    high = (PeriodCnt * dc) / 100;     //计算高电平所需的计数值
    low  = PeriodCnt - high;           //计算低电平所需的计数值
    high = 65536 - high + 13;          //计算高电平的定时器重载值并修正
    low  = 65536 - low  + 13;          //计算低电平的定时器重载值并修正

    HReloadH = (unsigned char)(high >> 8);  //高电平重载值拆分为高低字节
    HReloadL = (unsigned char)high;
    LReloadH = (unsigned char)(low >> 8);   //低电平重载值拆分为高低字节
    LReloadL = (unsigned char)low;
}

void InterruptTimer0() interrupt 1
{
  unsigned char code table1[9] = {  //占空比上升调整表                         
     10, 15, 20, 25, 30, 35, 40, 45, 50                  
    };                                                                                               
                                                                                                       
  unsigned char code table2[24] ={48,46,44,42,
        40,38,36,34,32,30,28,26,24,22,20,18,16,14,12,10         //占空比下降调整表
        ,8,6,4,2          
        };
       
        a++;              
       
                                                                                                         
/*444hz产生,变化规律:0-50%---45ms; 50%---198ms; 50%-2%---270ms*/
/*上升期间2个脉冲变化一次占空比5%,下降期间5个脉冲变化一次占空比2%*/
  if(flag_444==1)
{
   
   if (PWMOUT1 == 1)  //当前输出为高电平时,装载低电平值并输出低电平
    {
        TH0 = LReloadH;
        TL0 = LReloadL;
        PWMOUT1 = 0;
    }
   else              //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HReloadH;
        TL0 = HReloadL;
        PWMOUT1 = 1;
    }


   
   if((a == 4)&&(flag1_2==1))                   //前50%时,占空比变化快,进入第四次中断时,也就是两个脉冲可以变化一次
    {
         
         AdjustDutyCycle(table1[index1]); //调整PWM的占空比 ,出现标志flag1 = 1时占空比逐渐增加
        }

        if(flag1_0 == 1)
        {
         AdjustDutyCycle(50);
        }

        if((flag1_5 == 1)&&(a == 10))
        {
         AdjustDutyCycle(table2[index2]); //调整pwm的占空比
    }


   if ((flag1_2 == 1)&&(a==4))        //逐步增大占空比,第一次是5%,index1=1,进一次中断index1加一下;
    {
        index1++;
                a=0;
        if (index1 >= 8)                  
        {
            index1=0;
                       
                        flag1_0=1;                   //该标志是进入第二个状态,第二个状态的flag1_0表示状态不变标志
        }                                          
    }

       
        else  if(( flag1_0 == 1 )&&(a==1))    //进入第二个状态
        {
          b++;                                             //b做计数脉冲使用,一个脉冲记一次
          a = 0;
         if(b == 176)
         {
          flag1_5= 1 ;                                    
          flag1_0= 0 ;
          b= 0 ;
         }
   }


    else  if( (flag1_5 == 1)&&(a == 10) )   //逐步减小占空比,5个脉冲变化一次
    {
        index2++;
                a=0;
        if (index2 >= 23)
        {
            flag_666 = 1 ;      //进入下一个频率
                        flag_444 = 0 ;         //关闭第一个频率
                        flag1_5 = 0 ;                 //关闭第3个状态
                        index2 = 0;
        }
    }

}

  
/*666hz产生,变化规律:0-50%---45ms; 50%---195ms; 50%-2%---252ms*/
/*上升期间3个脉冲变化一次占空比5%,下降期间7个脉冲变化一次占空比2%*/  
  if(flag_666==1)
{

  if (PWMOUT2 == 1)  //当前输出为高电平时,装载低电平值并输出低电平
   {
        TH0 = LReloadH;
        TL0 = LReloadL;
        PWMOUT2 = 0;
   }
    else              //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HReloadH;
        TL0 = HReloadL;
        PWMOUT2 = 1;
    }


     
  if((a == 6)&&(flag2_2==1))                          //前50%时,占空比变化快
    {
         
         AdjustDutyCycle(table1[index1]); //调整PWM的占空比 ,出现标志占空比逐渐增加
        }

        if(flag2_0 == 1)
        {
         AdjustDutyCycle(50);
        }

        if((flag2_5 == 1)&&(a == 14))
        {
         AdjustDutyCycle(table2[index2]); //调整pwm的占空比,出现的标志占空比逐渐减小
    }


   if ((flag2_2 == 1)&&(a==6))             //逐步增大占空比,第一次是5%,index1=1
    {
        index1++;
                a=0;
        if (index1 >= 8)                  //这一句判断没有问题
        {
            index1=0;
               
                        flag2_0=1;                   //该标志是进入第二个状态,第二个状态的flag2_0表示状态不变标志
        }                                          
    }

       
        else  if(( flag2_0 == 1 )&&(a==1))    //进入第二个状态
        {
          b++;                                             //b做计数脉冲使用,一个脉冲记一次
          a = 0;
         if(b == 260)
         {
          flag2_5= 1 ;                                    
          flag2_0= 0 ;
          b= 0 ;
         }
   }


    else  if( (flag2_5 == 1)&&(a == 14) )       //逐步减小占空比,7个脉冲变化一次
    {
        index2++;
                a=0;
        if (index2 >= 23)
        {
            flag_888 = 1 ;      //进入下一个频率
                        flag_666 = 0;        //关闭第二个频率
                        flag2_5 = 0 ;                 //关闭第3个状态
                        index2 = 0;
        }
    }


}


/*888hz产生,变化规律:0-50%---45ms; 50%---198ms; 50%-2%---270ms*/
/*上升期间4个脉冲变化一次占空比5%,下降期间10个脉冲变化一次占空比2%*/
if(flag_888==1)
{  

  if (PWMOUT3 == 1)  //当前输出为高电平时,装载低电平值并输出低电平
   {
        TH0 = LReloadH;
        TL0 = LReloadL;
        PWMOUT3 = 0;
   }
    else              //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HReloadH;
        TL0 = HReloadL;
        PWMOUT3 = 1;
    }
   
   if((a == 8)&&(flag3_2==1))                          //前50%时,占空比变化快
    {
         
         AdjustDutyCycle(table1[index1]); //调整PWM的占空比
        }

        if(flag3_0 == 1)
        {
         AdjustDutyCycle(50);
        }

        if((flag3_5 == 1)&&(a == 20))
        {
         AdjustDutyCycle(table2[index2]); //调整pwm的占空比,出现的标志flag2 = 1时占空比逐渐减小
    }


   if ((flag3_2 == 1)&&(a==8))             //逐步增大占空比,第一次是5%,index1=1
    {
        index1++;
                a=0;
        if (index1 >= 8)                  //这一句判断没有问题
        {
            index1=0;
               
                        flag3_0=1;                   //该标志是进入第二个状态,第二个状态的flag3_0表示状态不变标志
        }                                          
    }

       
        else  if(( flag3_0 == 1 )&&(a==1))    //进入第二个状态
        {
          b++;                                             //b做计数脉冲使用,一个脉冲记一次
          a = 0;
         if(b == 352)
         {
          flag3_5= 1 ;                                    
          flag3_0= 0 ;
          b= 0 ;
         }
   }


    else  if( (flag3_5 == 1)&&(a == 20) )       //逐步减小占空比
    {
        index2++;
                a=0;
        if (index2 >= 23)
        {
            flag_333 = 1 ;      //进入下一个频率
                        flag_888 = 0 ;       //关闭第三个频率
                        flag3_5 = 0 ;                 //关闭第3个状态
                        index2 = 0;
        }
    }

}


/*333hz产生,变化规律:0-50%---60ms; 50%---192ms; 50%-2%---288ms*/
/*上升期间2个脉冲变化一次占空比5%,下降期间4个脉冲变化一次占空比2%*/
if(flag_333==1)
{


  if (PWMOUT4 == 1)  //当前输出为高电平时,装载低电平值并输出低电平
  {
        TH0 = LReloadH;
        TL0 = LReloadL;
        PWMOUT4 = 0;
  }
  else              //当前输出为低电平时,装载高电平值并输出高电平
  {
        TH0 = HReloadH;
        TL0 = HReloadL;
        PWMOUT4 = 1;
  }

   
  if((a == 4)&&(flag1_2==1))                          //前50%时,占空比变化快
    {
         
         AdjustDutyCycle(table1[index1]); //调整PWM的占空比
        }

  if(flag4_0 == 1)
        {
         AdjustDutyCycle(50);
        }

  if((flag4_5 == 1)&&(a == 8))
        {
         AdjustDutyCycle(table2[index2]); //调整pwm的占空比
    }


  if ((flag4_2 == 1)&&(a==4))             //逐步增大占空比,第一次是5%,index1=1
    {
        index1++;
                a=0;
        if (index1 >= 8)                  //这一句判断没有问题
        {
            index1=0;
               
                        flag4_0=1;                   //该标志是进入第二个状态,第二个状态的flag4_0表示状态不变标志
        }                                          
    }

       
  else  if(( flag4_0 == 1 )&&(a==1))    //进入第二个状态
        {
          b++;                                             //b做计数脉冲使用,一个脉冲记一次
          a = 0;
         if(b == 128)
         {
          flag4_5= 1 ;                                    
          flag4_0= 0 ;
          b= 0 ;
         }
   }


  else  if( (flag4_5 == 1)&&(a == 8) )       //逐步减小占空比
    {
        index2++;
                a=0;
        if (index2 >= 23)
        {
            flag_444 = 1 ;      //进入下一个频率
                        flag_333 = 0 ;      //关闭第四个频率
                        flag4_5 = 0 ;                 //关闭第3个状态
                        index2 = 0;
        }
    }
}

}




/*现在的问题是:(1)两个频率相互对接时,出现较大的跳变;
                        (2)中间的变化过程有点出入;
                       (3)频率的周期不准确。
*/

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 12:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表