SPWM波的定義和生成方法在這里就不多說了,本文主要說SPWM波在單片機上的實現,以及如何調節濾出后的正弦波的頻率及幅度。
先弄清楚SPWM在單片機上如何產生,比如你要輸出100HZ的SPWM正弦波,每個周期100個點,則定時器B的中斷頻率為100*100=10K,用于載波(定時器A)的PWM頻率應>=10K(這里我建議載波為1M,因為定時器的配合問題會有+-1的誤差,所以載波盡量的大則濾出的正弦波的波形越好)。
通過軟件,你先得到100個點的正弦波采樣值,你可以用定時器A來產生1MHZ的PWM,然后用定時器B,做定時器中斷,10KHZ的頻率,每次中斷,就把一個采樣值賦值給定時器A的輸出通道:CCRx。然后不停的循環,每中斷一百次,就輸出1個波。不停的循環就不停的輸出,那么PWM輸出端,經過濾波后(外部濾波電路要找相關電路去設計),就是100HZ的正弦波了。
調節頻率要通過定時器B,公式:正弦波頻率*每個周期的點數=定時器B中斷頻率
調節幅度要依據載波中最大與最小占空比之差也即是調制深度,這個沒有公式……..
剩下的就要參考我給出的程序作出自己的理解吧,靠你們了,騷年們!
程序示例:
函數
/*----------------------------------------------------------------------------------------------
* 功能:產生單路SPWM波
* 輸入:無
* 輸出:P1.4
* 注意:定時器也為TA1.1;載波頻率為126.26K;;默認正弦頻率為100HZ,幅度未知
*/
void SPWM_1Way_Init(void)
{
P1SEL |=BIT4;
P1DIR |=BIT4;
//P1DS |=BIT4; //全力驅動
P1OUT &=~BIT4;
spwm_i=0;
TA0CCR0 =198;//載波126.26KHZ
TA0CCR3 =Lab1[spwm_i];
TA0CCTL3 =OUTMOD_7;
TA0CTL =TASSEL_2+MC_1+TACLR;//選擇時鐘為SMCLK,UP模式
P2SEL |=BIT0;
P2DIR |=BIT0;
P2OUT &=~BIT0;
TA1CCR0 =2499;//25000000/(100*100)=2500:100Hz,100個點:10KHZ(時間不太準我做了些補償)
TA1CTL =TASSEL_2+MC_1+TACLR;//選擇時鐘為SMCLK,UP模式
TA1CTL |= TAIE;//開啟中斷
__enable_interrupt();//開啟總中斷
}
void SPWM_1Way_Set_Freq(unsigned int freq)
{
unsigned long freq_num;
freq_num=250000/(freq)-1;
TA1CCR0 =freq_num;
}
/*
* 功能:輸出兩路SPWM波,相位可調
* 輸入:無
* 輸出:P1.4,P1.5
* 注意:定時器也為TA1.1;載波頻率為126.26K;;默認正弦頻率為100HZ,幅度未知
*/
void SPWM_2Way_Init(void)
{
P1SEL |=BIT4+BIT5;
P1DIR |=BIT4+BIT5;
//P1DS |=BIT4+BIT5; //全力驅動
P1OUT &=~BIT4+BIT5;
spwm_i=0;
spwm_j=50;//控制相位
TA0CCR0 =198;//載波126.26KHZ
TA0CCR3 =Lab1[spwm_i];
TA0CCR4 =Lab1[spwm_j];
TA0CCTL3 =OUTMOD_7;
TA0CCTL4 =OUTMOD_7;
TA0CTL =TASSEL_2+MC_1+TACLR;//選擇時鐘為SMCLK,UP模式
P2SEL |=BIT0;
P2DIR |=BIT0;
P2OUT &=~BIT0;
TA1CCR0 =2499;//25000000/(100*100)=2500:100Hz,100個點:10KHZ
TA1CTL =TASSEL_2+MC_1+TACLR;//選擇時鐘為SMCLK,UP模式
TA1CTL |= TAIE;//開啟中斷
__enable_interrupt();//開啟總中斷
}
void SPWM_2Way_Set_Freq(unsigned int freq)
{
unsigned long freq_num;
freq_num=250000/(freq)-1;
TA1CCR0 =freq_num;
}
/*
* 功能:中斷函數,改變SPWM中占空比寄存器的值
* 輸入:無
* 輸出:無
* 注意:為0時雙路輸出,為1時單路輸出
*/
#if 0
#pragma vector=TIMER1_A1_VECTOR
__interrupt void TimerA1(void)
{
TA0CCR3 =Lab1[spwm_i++];
if(spwm_i==100)spwm_i=0;
TA1IV=0; //GPIO的單獨中斷會自動清零,可TIMER的不會,所以要軟件清零;!!
}
#else
#pragma vector=TIMER1_A1_VECTOR
__interrupt void TimerA1(void)
{
TA0CCR3 =Lab1[spwm_i++];
if(spwm_i==100)spwm_i=0;
TA0CCR4 =Lab1[spwm_j++];
if(spwm_j==100)spwm_j=0;
TA1IV=0; //GPIO的單獨中斷會自動清零,可TIMER的不會,所以要軟件清零;!!
}
#endif
頭文件PWM.h
/*
* PWM.h
*
* Created on: 2016-8-22
* Author: Flyskyr
*/
#ifndef PWM_H_
#define PWM_H_
extern unsigned int spwm_i,spwm_j;
extern unsigned int Lab_base[];
extern float Lab1[];
extern void SPWM_1Way_Init(void);
extern void SPWM_1Way_Set_Freq(unsigned int freq);
extern void SPWM_2Way_Init(void);
extern void SPWM_2Way_Set_Freq(unsigned int freq);
#endif /* PWM_H_ */
頭文件include.h
/*
* include.h
*
* Created on: 2016-8-18
* Author: Flyskyr
*/
#include
#include"PWM.h"
unsigned int spwm_i,spwm_j;
unsigned int Lab_base[]={99,105,111,117,123,129,135,141,146,152,157,162,166,171,175,179,182,185,188,191,193,194,196,197,197,198,197,197,196,194,193,191,188,185,182,179,175,171,166,162,157,152,146,141,135,129,123,117,111,105,99,92,86,80,74,68,62,56,51,45,40,35,31,26,22,18,15,12,9,6,4,3,1,0,0,0,0,0,1,3,4,6,9,12,15,18,22,26,31,35,40,45,51,56,62,68,74,80,86,92
};
float Lab1[]={99,105,111,117,123,129,135,141,146,152,157,162,166,171,175,179,182,185,188,191,193,194,196,197,197,198,197,197,196,194,193,191,188,185,182,179,175,171,166,162,157,152,146,141,135,129,123,117,111,105,99,92,86,80,74,68,62,56,51,45,40,35,31,26,22,18,15,12,9,6,4,3,1,0,0,0,0,0,1,3,4,6,9,12,15,18,22,26,31,35,40,45,51,56,62,68,74,80,86,92
};//這個float數組我是用來調節調制深度的,改變這里的值就可以改變輸出的幅度了
上一篇:STC15單片機6路專用PWM
下一篇:STC12C5A60S2單片機-雙串口通信
推薦閱讀
史海拾趣