/******************************************************************************
ZJ_SineInverter.c xtal-locked push-pull sinewave Inverter driver
Open-source - 8th Dec 2009 - www.RomanBlack.com/one_sec.htm
(Original inspiration by Mike McLaren K8LH).
PIC 12F675, xtal (see below).
This manually generates dual inverted sinewave PWM outputs.
PWM frequency varies from 25kHz to 47kHz depending on the step.
It will drive push-pull FETs to make a mains inverter;
10MHz xtal; 50Hz output (same code is used for both)
12MHz xtal; 60Hz output
GP0 - this is push-pull outputA (hi = FET on)
GP1 - this is push-pull outputB (hi = FET on)
_BODEN_OFF _MCLRE_OFF _PWRTE_ON _WDT_OFF _HSOSC
******************************************************************************/
// edit PERIOD to give the freq; PERIOD = (xtal / 4 / (freq*20))
// Note! we need 20 period events per mains cycle, so use (freq * 20)
#define PERIOD 2500 // 10Mhz xtal = 50Hz, 12MHz xtal = 60Hz. (don't edit)
#define PERHI (PERIOD / 256) // don't edit this!
#define PERLO (PERIOD - (PERHI*256)) // don't edit this!
unsigned char step; // sequences each of the 20 PWM steps
#define PHASEA 0b00000001; // push-pull outputA on
#define PHASEB 0b00000010; // push-pull outputB on
//=============================================================================
void interrupt()
{
// TMR1 interrupt. This is a very simple zero-error TMR1 correction.
// It generates an interrupt every 2500 PIC instructions.
// (this code was hardware tested to exact cycle accuracy)
TMR1L -= (PERLO - 2); // fix TMR1, retain error for next period
TMR1H -= (PERHI + 1);
step++;
PIR1.TMR1IF = 0;
}
//=============================================================================
void Delay10(void)
{
// gives a total delay of 10 PIC instructions
asm goto $+1; // 2 insts each
asm goto $+1;
asm goto $+1;
}
//=============================================================================
void Delay20(void)
{
// gives a total delay of 20 PIC instructions
asm goto $+1; // 2 insts each
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
}
//=============================================================================
void main ()
{
//-----------------------------------------------------
// PIC 12F675 setup ports
ANSEL = 0; // ADC off
CMCON = 0x07; // comparators off
GPIO = 0b00000000; // clear GPIO
TRISIO = 0b00000000; // All outputs
//-----------------------------------------------------
// timer setup etc
OPTION_REG = 0b00001000; // TMR0 on, 1:1 prescale
T1CON = 0b00000001; // TMR1 on, 1:1 prescale
INTCON = 0b11000000; // GIE on, PEIE on
PIE1 = 0b00000001; // TMR1 int ON
//-----------------------------------------------------
// 20 sine PWM values provided by Mike McLaren K8LH;
// (I have tweaked these slightly in code below)
// sine[] = { 49,64,78,89,96,99,96,89,78,64,
// 49,34,20,9,2,0,2,9,20,34 };
//-----------------------------------------------------
// main run loop here
while(1)
{
//---------------------------------
// 50% PWM
sinestep0:
step = 0;
sinestep0b:
GPIO = PHASEA;
if(step == 1) goto sinestep1;
Delay20();
GPIO = PHASEB;
Delay20();
asm goto $+1;
asm goto $+1;
goto sinestep0b;
//---------------------------------
// 64% PWM
sinestep1:
GPIO = PHASEA;
if(step == 2) goto sinestep2;
Delay20();
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEB;
Delay20();
goto sinestep1;
//---------------------------------
// 78% PWM
sinestep2:
GPIO = PHASEA;
if(step == 3) goto sinestep3;
Delay20();
Delay10();
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEB;
Delay10();
goto sinestep2;
//---------------------------------
// 89% PWM
sinestep3:
GPIO = PHASEA;
if(step == 4) goto sinestep4;
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEB;
asm goto $+1;
asm goto $+1;
goto sinestep3;
//---------------------------------
// 96% PWM
sinestep4:
GPIO = PHASEA;
if(step == 5) goto sinestep5;
Delay20();
Delay20();
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEB;
asm goto $+1;
goto sinestep4;
//---------------------------------
// 100% PWM
sinestep5:
GPIO = PHASEA;
if(step == 6) goto sinestep6;
goto sinestep5;
//---------------------------------
// 96% PWM
sinestep6:
GPIO = PHASEA;
if(step == 7) goto sinestep7;
Delay20();
Delay20();
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEB;
asm goto $+1;
goto sinestep6;
//---------------------------------
// 89% PWM
sinestep7:
GPIO = PHASEA;
if(step == 8) goto sinestep8;
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEB;
asm goto $+1;
asm goto $+1;
goto sinestep7;
//---------------------------------
// 78% PWM
sinestep8:
GPIO = PHASEA;
if(step == 9) goto sinestep9;
Delay20();
Delay10();
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEB;
Delay10();
goto sinestep8;
//---------------------------------
// 64% PWM
sinestep9:
GPIO = PHASEA;
if(step == 10) goto sinestep10;
Delay20();
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEB;
Delay20();
goto sinestep9;
//---------------------------------
// 50% PWM
sinestep10:
GPIO = PHASEA;
if(step == 11) goto sinestep11;
Delay20();
GPIO = PHASEB;
Delay20();
asm goto $+1;
asm goto $+1;
goto sinestep10;
//---------------------------------
// 64% PWM inv
sinestep11:
GPIO = PHASEB;
if(step == 12) goto sinestep12;
Delay20();
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEA;
Delay20();
goto sinestep11;
//---------------------------------
// 78% PWM inv
sinestep12:
GPIO = PHASEB;
if(step == 13) goto sinestep13;
Delay20();
Delay10();
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEA;
Delay10();
goto sinestep12;
//---------------------------------
// 89% PWM inv
sinestep13:
GPIO = PHASEB;
if(step == 14) goto sinestep14;
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEA;
asm goto $+1;
asm goto $+1;
goto sinestep13;
//---------------------------------
// 96% PWM inv
sinestep14:
GPIO = PHASEB;
if(step == 15) goto sinestep15;
Delay20();
Delay20();
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEA;
asm goto $+1;
goto sinestep14;
//---------------------------------
// 100% PWM inv
sinestep15:
GPIO = PHASEB;
if(step == 16) goto sinestep16;
goto sinestep15;
//---------------------------------
// 96% PWM inv
sinestep16:
GPIO = PHASEB;
if(step == 17) goto sinestep17;
Delay20();
Delay20();
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEA;
asm goto $+1;
goto sinestep16;
//---------------------------------
// 89% PWM inv
sinestep17:
GPIO = PHASEB;
if(step == 18) goto sinestep18;
Delay20();
Delay20();
asm goto $+1;
asm goto $+1;
GPIO = PHASEA;
asm goto $+1;
asm goto $+1;
goto sinestep17;
//---------------------------------
// 78% PWM inv
sinestep18:
GPIO = PHASEB;
if(step == 19) goto sinestep19;
Delay20();
Delay10();
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEA;
Delay10();
goto sinestep18;
//---------------------------------
// 64% PWM inv
sinestep19:
GPIO = PHASEB;
if(step == 20) goto sinestep0;
Delay20();
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm goto $+1;
asm nop;
GPIO = PHASEA;
Delay20();
goto sinestep19;
}
}
//-----------------------------------------------------------------------------