* Filename: MAIN.C
******************************************************************************
*
* Author: Dave Karipides
* Company: APS, Inc.
* Date: 3-3-97
* Compiled Using MPLAB-C Rev 1.21
*
******************************************************************************
******************************************************************************
*
* Description: The main routine calls all the functions for generating
* an OPEN_LOOP or FEEDBACK sine wave of either 50 or 60 Hz.
*
******************************************************************************
*
*
*
******************************************************************************/
/*****************************************************************************
* main()
*
* Description: The main routine initializes the registers and loops
* forever. All control is handled in the TMR0 INT
* routine.
*
*
* Input Variables: NONE
*
* Output Variables: NONE
*
*
******************************************************************************/
//#define OPEN_LOOP
#define FEEDBACK
//#define 50Hz
#define 60Hz
#pragma option v
#include <17c43.h>
#include
#include
#ifdef OPEN_LOOP
// This table yields Full VRMS input
unsigned char const pwmtab[32]={0,25,50,74,98,120,142,162,180,197,212,
225,235,244,250,254,255,254,250,244,235,
225,212,197,180,162,142,120,98,74,50,25};
#endif
#ifdef FEEDBACK
// This table yields slightly less than Full VRMS input
unsigned char const pwmtab[32]={0,20,40,60,79,97,114,131,145,159,171,
181,189,197,202,205,206,205,202,197,189,
181,171,159,145,131,114,97,79,60,40,20};
#endif
long read_ad(unsigned char); // Prototype for A/D converter function
unsigned char index; // Index into the sinewave reference table
unsigned char sign; // Flag used to unfold sinewave reference table
long reference; // Value of the sinewave refrence after unfolding
unsigned char reference_lo @ reference; // V1.21 of Compiler does not type cast unsigned
// char to long so we will write to low byte separately
long out_volt; // Magnitude of the output voltage;
long y; // Variables used in compensation routine
long yold;
long x;
long xold;
long ad_value; // A/D Converter Value
void main(void)
{
CLRWDT();
PORTC = 0; // Zero out portc latches
DDRC = 0x22; // Set up Data direction register for C
DDRB = 0; // Set up Data direction register for B
PR1 = 0xFF; // Setup PR1 register (24.4Khz @ 25Mhz clk)
PW1DCL = 0; // Set low bits of PWM to 0
PW1DCH = 0; // Init PWM duty cycle to 0
T0STA = 0x20; // Configure Timer0 prescaler
INTSTA.T0IE = 1; // Enable Timer 0 interrupt
TCON1.TMR1CS = 0;
TCON1.T16 = 0;
TCON2.TMR1ON = 1; // Start timer 1 (PWM timer)
TCON2.PWM1ON = 1; // Turn on the PWM
CPUSTA.GLINTD = 0; // Unmask the interrupts
index = 0; // Initialize variables
sign = 0;
y = 0;
yold = 0;
x = 0;
xold = 0;
PORTC.0 = 1; // Enable the Inverter
while(1); // Loop forever, execute in INT Routine
}
#ifdef FEEDBACK
__TMR0() // Timer interrupt
{
T0STA.T0CS = 0; // Stop timer
PORTB.7=1;
#ifdef 60Hz
TMR0L=0xA5;
TMR0H=0xF9; // Make Timer0 interrupt at 3.84KHz for 60Hz output
#endif
#ifdef 50Hz
TMR0L=0x5F; // Make Timer0 interrupt at 3.20KHz for 50Hz output
TMR0H=0xF8;
#endif
T0STA.T0CS = 1; // Start timer
CLRWDT();
reference = 0; // Clear Reference Value
reference_lo = pwmtab[index]; // Lookup the value of the sinewave reference
if (!index) // Toggle Sign Every Cycle Through table
sign = ~sign;
++index; // Increment index
if (index == 32) // If end of table, reset counter
index = 0;
if (sign) // If negative going wave
{
reference = ~reference; // V1.21 of Compiler negate (-ref) doesn't work for
reference = reference + 1;// ref<=0
}
ad_value = read_ad(0);
out_volt = ad_value - 512; // Read output voltage (512 counts=0 volts out)
// Form the expression y = yold + (0.09261 * (x + xold))
// Where yold, xold is the value of y, x from the previous sample
// x is the
// of the inverter and the reference signal.
x = out_volt - reference;
y = ((x + xold) * 24);
y = y / 256;
y = y + yold;
if (y >= 0)
{
PORTC.2 = 0; // Set positive going cycle
} else
{
PORTC.2 = 1; // Set negative going cycle
y = ~y;
y = y + 1;
}
if (y > 255)
y = 255; // Limit y
PW1DCH = y; // Update duty cycle
xold = x; // Store previous sample's state
yold = y;
PORTB.7=0;
}
#endif
#ifdef OPEN_LOOP
// The inverter runs in an open loop mode with OPEN_LOOP defined.
__TMR0() // Timer interrupt
{
T0STA.T0CS = 0; // Stop timer
#ifdef 60Hz
TMR0L=0xA5;
TMR0H=0xF9; //Make Timer0 interrupt at 3.84KHz for 60Hz output
#endif
#ifdef 50Hz
TMR0L=0x5F; //Make Timer0 interrupt at 3.20KHz for 50Hz output
TMR0H=0xF8;
#endif
T0STA.T0CS=1; //Start timer
CLRWDT();
PW1DCH = pwmtab[index];
if (!index)
{
PORTC.0 = 0; // Gate Drive off
PORTC.2 = ~PORTC.2; // Flip Pos/Neg bit
PORTC.0 = 1; // Gate Drive on
}
++index;
if (index == 32)
index = 0;
PORTC.3 = ~PORTC.3; // Toggle bit to test freq.
}
#endif
long read_ad(unsigned char channel)
{
long result;
PORTC.6 = 1; // Write bit high
PORTC.7 = 1; // Read bit high
PORTC.4 = 1; // Chip select high
DDRD = 0; // Make PORTD an output
PORTD = 0x04; // Single ended mode signed 10 bit chan 0 Right justified
PORTC.4 = 0; // Select chip
PORTC.6 = 0; // latch command word int A/D
PORTC.6 = 1; // Start conversion
PORTC.4 = 1; // Deselect chip
while (PORTC.5); // Wait for conversion to complete
DDRD = 0xFF; // Make PORTD an input
PORTC.4 = 0; // Select chip
PORTC.7 = 0; // Read high byte
*( ((unsigned char*)&result) + 1) = PORTD;
PORTC.7 = 1;
PORTC.4 = 1;
PORTC.4 = 0;
PORTC.7 = 0; // Read low byte
*( ((unsigned char*)&result) ) = PORTD;
PORTC.7 = 1;
PORTC.4 = 1; // Reset chip select lines
return (result); // Return data
}