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

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数组我是用来调节调制深度的,改变这里的值就可以改变输出的幅度了
  • 9
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
要使用MSP430F5529生成SPWM(Sine Wave Pulse Width Modulation)形,您可以结合50Hz正弦和10,000Hz三角。下面是一个示例代码: ```c #include <msp430.h> #include <math.h> #define PI 3.14159265 #define BUFFER_SIZE 100 volatile int sine_buffer[BUFFER_SIZE]; volatile int triangle_buffer[BUFFER_SIZE]; volatile int buffer_index = 0; volatile int timer_count = 0; void setupTimer() { TA0CCTL0 = CCIE; // Enable Timer A0 interrupt TA0CCR0 = 20000; // Set Timer A0 period (20,000 cycles for 50Hz) TA0CTL = TASSEL_2 + MC_1 + TACLR; // Use SMCLK, Up mode, Clear TAR } void setupDAC() { // Configure DAC output pins P6SEL |= BIT6 | BIT7; // Configure DAC12 DAC12_0CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; DAC12_0DAT = 0; DAC12_1CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; DAC12_1DAT = 0; } void generateSinWave() { float amplitude = 2047.5; // Half of the DAC range (4095 / 2) float frequency = 50; // 50Hz float time_step = 1.0 / frequency; float time = timer_count * time_step; int sin_value = amplitude * sin(2 * PI * frequency * time) + amplitude; DAC12_0DAT = sin_value; } void generateTriangleWave() { float amplitude = 2047.5; // Half of the DAC range (4095 / 2) float frequency = 10000; // 10,000Hz float time_step = 1.0 / frequency; float time = timer_count * time_step; int triangle_value = amplitude * (2 * (time - floor(0.5 + time))) + amplitude; DAC12_1DAT = triangle_value; } void generateSPWMWave() { int spwm_value = (sine_buffer[buffer_index] > triangle_buffer[buffer_index]) ? 1 : 0; // Output SPWM value to a GPIO pin if (spwm_value) { P1OUT |= BIT0; // Set GPIO P1.0 high } else { P1OUT &= ~BIT0; // Set GPIO P1.0 low } buffer_index++; if (buffer_index >= BUFFER_SIZE) { buffer_index = 0; } } void main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer setupTimer(); setupDAC(); // Configure GPIO P1.0 as output for SPWM waveform P1DIR |= BIT0; __bis_SR_register(GIE); // Enable global interrupts while (1) { generateSPWMWave(); } } #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_A(void) { generateSinWave(); generateTriangleWave(); timer_count++; if (timer_count >= BUFFER_SIZE) { timer_count = 0; } } ``` 这段代码使用了MSP430F5529的定时器和DAC模块来生成SPWM形。在`generateSinWave`函数中,使用50Hz正弦生成DAC0的输出。在`generateTriangleWave`函数中,使用10,000Hz三角生成DAC1的输出。在`generateSPWMWave`函数中,将DAC0和DAC1的输出进行比较,根据结果设置GPIO P1.0的高低电平,从而生成SPWM形。 请注意,这只是一个基本的示例代码,您可能需要根据您的具体需求进行修改和优化。还请确保正确配置MSP430F5529的时钟和引脚设置。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值