工程师STM32单片机学习基础手记(4):用PWM实现荧火虫灯(二) -
用PWM生成正弦波
有了PWM,自然就可以用PWM的方法生成正弦波了。下面生成500Hz正弦波的方法参考自张明峰的《PIC单片机入门与实践》
每个正弦波分成四个像限,每个像限16点,共64点,每点出现2个PWM周期,故PWM的周期为:2ms/128=156.25us,频率为64KHz。
TIM3 Frequency = TIM3 counter clock/(ARR + 1)
倒过来:
ARR=TIM3 Counter Clock/TIM3 Frequenc - 1 =562.5-1 =561
如果取ARR的值是561的话,那么实际的频率是64.056KHz,即最终生成为的正弦波频率是:500.4Hz
有了ARR,占空比就取决于CCR1的值了,使用EXCEL可以方便地计算出第一象限的16个点的数据:
280,307,335,361,387,412,436,458,478,496,513,527,539,548,555,559
有了第一象限,其他象限都可以镜像生成了。具体方法请看源程序。
要用上面的例子修改,还需要做一些工作。
前面是在SysTick中做出标志,然后在主程序中修改CCR1的值,现在不行了,肯定会有时间的误差,不能这做么,要在PWM输出后修正,这样就要在PWM波形输出时产生中断。因此,需要在main函数中增加以下这个函数。
这个函数哪里来的呢,很简单,从timebase工程中中抄来的然后将TIM2改成TIM3就行了^_^。然后在main函数中调用它。
注意,还需要打开stm32f10x_conf.h文件,将下面:
蓝色框里面的包含文件给“解放”出来。当然,同时要把库中的misc.c源程序文件加入工程中来。否则,编译是通不过的。
为了让通道1可以产生中断,还需要做一件事,就是下面蓝色的部分。
/* TIM IT enable */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
//也是从TIMEBASE工程中抄来,再将TIM2改成TIM3的。
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
现在该到stm32f10x_it.c中去了,增加一个中断处理函数:
uint16_t sinTab[]={280,307,335,361,387,412,436,458,478,496,513,527,539,548,555,559};
uint8_t Count1,Count2; //1.像限计数器,其值在0~3之间变化 2.其值在0~31之间变化
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
if(Count2%2==0) //准备更新,新的值会在下一次更新
{ switch(Count1)
{ case 0: //象限1
{
TIM3-》CCR1= sinTab[Count2/2];
break;
}
case 1: //象限2
{ TIM3-》CCR1=sinTab[15-Count2/2];
break;
}
case 2: //象限3
{ TIM3-》CCR1=560-sinTab[Count2/2];
break;
}
case 3: //象限4
{ TIM3-》CCR1=560-sinTab[15-Count2/2];
break;
}
default:break;
}
}
}
if(++Count2==32)
{ Count2=0;
if(++Count1==4)
Count1=0;
}
}
也就是在这里,搞清楚了,所谓的“我有些怀疑上面提到的那个CCR1没有立即变化仅仅只是调试器的问题”不对,这是CCR1更新方法的问题,
注意上图中红色框中的描述。
这里就是不用立即更新的方法。因为每个点的PWM波形会出现2次,因此,用
if(Count2%2==0) 来判断是第一次产生PWM波形,更新CCR1,但是这个CCR1不会立即更新,而会在下一次产生PWM事件时更新。
查看评论 回复