SPWM波在单片机上的实现与调节(基于MSP430F5529)

来源:互联网 发布:立秋网络怎么获得学时 编辑:程序博客网 时间:2024/06/11 17:48

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 <msp430.h>#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数组我是用来调节调制深度的,改变这里的值就可以改变输出的幅度了
0 0