大家好,有问题求助于大家。我现在在做的是:利用一个定时器控制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)频率的周期不准确。
*/
一周热门 更多>