基于 dsPIC30F 系列(以 dsPIC30F4011 为例)的逆变器程序框架,这是单相全桥 SPWM 逆变器的经典写法,适用于 光伏逆变器 / UPS / 电机驱动 等场景。
使用 MPLAB X + XC16
基于 PWM + ADC + 中断
支持 电压闭环 / 软启动 / 保护
一、硬件
| 功能 | dsPIC30F4011 |
|---|---|
| PWM | PWM1L/H ~ PWM4L/H |
| ADC | AN0 / AN1(输出电压 / 电流) |
| 振荡器 | 7.3728 MHz |
| 逆变拓扑 | 全桥 SPWM |
| 输出频率 | 50 Hz |
| 载波频率 | 20 kHz |
二、SPWM 原理简述
- PWM 频率:20 kHz
- 正弦表:200 点
- 调制比 M:0~1
- 占空比:
Duty = (1 + M × sin(ωt)) / 2
三、核心代码(XC16)
1、头文件 & 全局变量
#include <xc.h>
#include <libpic30.h>
#define FCY 7372800UL
#define FSW 20000 // PWM 频率
#define SINE_TABLE_SIZE 200
volatile unsigned int sine_index = 0;
volatile int output_voltage = 0;
extern const unsigned int sine_table[SINE_TABLE_SIZE];
2、正弦波查找表(50Hz)
const unsigned int sine_table[SINE_TABLE_SIZE] =
{
2048, 2148, 2248, 2348, 2447, 2545, 2642, 2737, 2831, 2923,
/* ... 省略中间 ... */
2148, 2048
};
3、PWM 初始化(SPWM)
void PWM_Init(void)
{
PTCON = 0x0000;
PWMCON1 = 0x00FF; // PWM1~PWM4 独立模式
PTPER = FCY / FSW - 1; // PWM周期
PDC1 = 0;
PDC2 = 0;
PDC3 = 0;
PDC4 = 0;
PTMR = 0;
PTCONbits.PTEN = 1; // 启动 PWM
}
4、定时器中断(SPWM 更新)
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void)
{
float M = 0.9; // 调制比
unsigned int duty;
duty = (unsigned int)(PTPER *
(1.0 + M * sine_table[sine_index] / 4096.0) / 2.0);
PDC1 = duty;
PDC2 = duty;
PDC3 = duty;
PDC4 = duty;
sine_index++;
if (sine_index >= SINE_TABLE_SIZE)
sine_index = 0;
IFS0bits.T1IF = 0;
}
5、定时器1 初始化
void Timer1_Init(void)
{
T1CON = 0x0000;
TMR1 = 0;
PR1 = FCY / SINE_TABLE_SIZE / 50; // 50Hz
T1CONbits.TON = 1;
IEC0bits.T1IE = 1;
IPC0bits.T1IP = 5;
}
6、ADC 采样(输出电压/电流)
void ADC_Init(void)
{
ADPCFG = 0xFFFC; // AN0 AN1 模拟
ADCSSL = 0x0003;
ADCON1 = 0x006C;
ADCON2 = 0x0000;
ADCON3 = 0x0000;
ADCHS = 0x0000;
ADCON1bits.ADON = 1;
}
void Read_ADC(void)
{
ADCON1bits.SAMP = 1;
__delay_us(10);
ADCON1bits.SAMP = 0;
while (!ADCON1bits.DONE);
output_voltage = ADCBUF0;
}
7、主函数
int main(void)
{
PWM_Init();
Timer1_Init();
ADC_Init();
while (1)
{
Read_ADC(); // 可用于闭环
}
}
参考代码 基于dsPIC30F系列单片机的逆变器程序 www.youwenfan.com/contentcsv/72981.html
四、逆变器保护功能
过压保护
欠压保护
过流保护
短路保护
软件死区
if (output_voltage > OVER_VOLTAGE_LIMIT)
{
PTCONbits.PTEN = 0; // 关 PWM
}