#include "p33EP512MU810.h"
_FOSCSEL(FNOSC_FRC)
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT)
_FGS(GSS_OFF)
_FWDT(FWDTEN_OFF)
int _sin(int y);
int _cos(int y);
int sine(int x);
int cosine(int x);
void InitPWM1(void);
void RS_SVM();
volatile int rho;
volatile int deltarho;
volatile int PI2PER3;
volatile int PWMMAX;
volatile int u_alfa, u_beta;
volatile int ud,uq;
volatile int cosrho,sinrho;
volatile int sin_a,sin_b,sin_c;
volatile int vref_a,vref_b,vref_c;
volatile int vref_mid,vh;
volatile int duty_a,duty_b,duty_c;
volatile int sqrt3_2;
int main(void)
{
// Crystal Frequency * M
// Fcy = ------------------------
// N1*N2
// Crystal = 8 MHz
// Fosc = 120 MHz
// Fcy = 60 MIPs
PLLFBD = 58; // M=58
CLKDIVbits.PLLPOST = 0; // N1=2
CLKDIVbits.PLLPRE = 0; // N2=2
__builtin_write_OSCCONH(0x03);
__builtin_write_OSCCONL(0x01);
while(OSCCONbits.COSC != 0b011);
// Wait for PLL to lock
while(OSCCONbits.LOCK != 1);
TRISEbits.TRISE6=0;
InitPWM1();
rho=0x1000;
deltarho = 0x0444; //angle step, mf=60, f1=50Hz
PI2PER3 = 0x5553; //2PI/3
PWMMAX = 10000;
ud=0x2000;
uq=0;
sqrt3_2=0x6EDA;
while(1);
}
void InitPWM1(void)
{
PTCONbits.PTEN = 0; //PWM module is disabled
/* Set Independent Time Bases, Center-Aligned mode and Independent Duty Cycles */
PWMCON1 = PWMCON2 = PWMCON3 = 0x0204;
/* Set PWM Mode to Complementary */
IOCON1 = IOCON2 = IOCON3 = 0xC000;
PTCON2bits.PCLKDIV = 1; //Prescaler 2
/* Set PWM Period on Primary Time Base */
PHASE1 = 10000;
PHASE2 = 10000;
PHASE3 = 10000;
/* Set Duty Cycles */
PDC1 = 0;
PDC2 = 0;
PDC3 = 0;
/*Set dead-time */
ALTDTR1 = ALTDTR2 = ALTDTR3 = 120; //2us
/* Configure Faults */
FCLCON1 = FCLCON2 = FCLCON3 = 0x0003;
PTCONbits.EIPU = 0; //immediate update disable
/* interrupt */
IPC14bits.PSEMIP = 3;
IFS3bits.PSEMIF = 0;
IEC3bits.PSEMIE = 1;
PTCONbits.SEIEN = 1; //Special Event Interrupt Enable
PTCONbits.SEVTPS = 0; //interrupt at every special event
PTPER = 20000; //Primary Time Base Period Register
SEVTCMP = 10000; //Special Event Compare Register
PTCONbits.PTEN = 1; //PWM module is enabled
}
void __attribute__(( interrupt, shadow, no_auto_psv )) _PWMSpEventMatchInterrupt(void)
{
LATEbits.LATE6=1;
RS_SVM();
LATEbits.LATE6=0;
IFS3bits.PSEMIF = 0; //Clear Flag
}
void RS_SVM()
{
rho+=deltarho;
cosrho=cosine(rho);
sinrho=sine(rho);
/*Rotate back*/
u_alfa = ((__builtin_mulss(ud,cosrho))>>15) - ((__builtin_mulss(uq,sinrho))>>15);
u_beta = ((__builtin_mulss(ud,sinrho))>>15) + ((__builtin_mulss(uq,cosrho))>>15);
/*Inverse Park*/
vref_a = u_alfa;
vref_b = ((__builtin_mulss(u_beta,sqrt3_2))>>15)- ((u_alfa)>>1);
vref_c = -vref_a - vref_b;
if (vref_a > vref_b)
if (vref_b> vref_c)
vref_mid = vref_b; //sector 1
else if (vref_a > vref_c)
vref_mid = vref_c; //Sector 6
else
vref_mid = vref_a; //Sector 5
else if (vref_b < vref_c)
vref_mid = vref_b; //Sector 4
else if (vref_a > vref_c)
vref_mid = vref_a; //Sector 2
else
vref_mid = vref_c; //Sector 3
vh=((vref_mid)>>1) + 0x4000;
vref_a+=vh;
vref_b+=vh;
vref_c+=vh;
//phase a
duty_a=(__builtin_mulss(vref_a,PWMMAX)>>15);
//phase b
duty_b=(__builtin_mulss(vref_b,PWMMAX)>>15);
//phase c
duty_c=(__builtin_mulss(vref_c,PWMMAX)>>15);
PDC1 = duty_a;
PDC2 = duty_b;
PDC3 = duty_c;
}
int _sin(int y) //input range 0xE000 (-pi/4) till 0x2000 (pi/4)
{
int s5=0x28CD;
int s3=0x52AF;
int s1=0x3244;
int z, prod, sum;
z=((__builtin_mulss(y,y))>>15);
prod = ((__builtin_mulss(s5,z))>>15);
sum = s3 - prod;
prod = ((__builtin_mulss(sum,z))>>15);
sum = s1 - prod;
prod = ((__builtin_mulss(sum,y))>>15);
return prod<<3;
}
int _cos(int y) //input range 0xE000 (-pi/4) till 0x2000 (pi/4)
{
int c4=0x40F0;
int c2=0x4EF5;
int c0=0x7FFF;
int z, prod, sum;
z=((__builtin_mulss(y,y))>>15);
prod = ((__builtin_mulss(c4,z))>>15);
sum = c2 - prod;
prod = ((__builtin_mulss(sum,z))>>15)<<3;
sum = c0 - prod;
return sum;
}
int sine(int x) //input range 0x8000 (-pi) till 0x7FFF (pi)
{
unsigned int n = ((unsigned int)x +0x2000) >> 14;
x -= n * 0x4000; /* translate input down to +/- pi/4 */
switch(n){
case 0:
return _sin(x);
case 1:
return _cos(x);
case 2:
return -_sin(x);
case 3:
return -_cos(x);
default:
return 0;
}
}
int cosine(int x) //input range 0x8000 (-pi) till 0x7FFF (pi)
{
return sine(x + 0x4000);
}