原创 spwm

2009-1-13 13:48 1978 5 5 分类: 处理器与DSP
/*****************************************************************************?
* Filename: MAIN.C?
******************************************************************************?
*?
* Author: Dave Karipides?
* Company: APS, Inc.?
* Date: 3-3-97?
* Compiled Using MPLAB-C Rev 1.21?
*? ?? ? 编译平台:MAPLAB-C Rev1.21()?
******************************************************************************?
******************************************************************************?
*?
* Description: The main routine calls all the functions for generating?
* an OPEN_LOOP or FEEDBACK sine wave of either 50 or 60 Hz.?
*? ?? ? 软件描述:主程序调用函数产生开环和闭环调节的正弦波可设置50HZ或60HZ? ?
******************************************************************************?
*?
*?
******************************************************************************/?
/*****************************************************************************?
* main()?
*?
* Description: The main routine initializes the registers and loops?
* forever.??All control is handled in the TMR0 INT?
* routine.?
*? ?? ? 主程序描述:主程序初始化个积存器组后台循环。所有控制操作在TMRO中断子程序处理。?
*?
* 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声明A/D采样函数?
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;AD转换数值寄存器?
void main(void)?
{?
CLRWDT();//清看门狗,一般PIC初始化之前需要加次命令,以免不必要的中断?
PORTC = 0; // Zero out portc latches;C端口积存器清零?
DDRC = 0x22; // Set up Data direction register for C;PORTC端口方向积存器定义?
DDRB = 0; // Set up Data direction register for B;PORTB端口方向积存器定义?
PR1 = 0xFF; // Setup PR1 register (24.4Khz @ 25Mhz clk)设置PWM频率在25MHZ时,PR1=0XFF,则PWM频率为24.4KHZ。具体计算见手册?
PW1DCL = 0; // Set low bits of PWM to 0?
PW1DCH = 0; // Init PWM duty cycle to 0;初始化占空比为零?
T0STA = 0x20; // Configure Timer0 prescaler;设置定时期T0预分频?
INTSTA.T0IE = 1; // Enable Timer 0 interrupt;开定时器TO中断?
TCON1.TMR1CS = 0;?
TCON1.T16 = 0;?
TCON2.TMR1ON = 1; // Start timer 1 (PWM timer);开定时器T1?
TCON2.PWM1ON = 1; // Turn on the PWM,开定TMR2,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;PORTC.0逆变允许开关,允许输出?
while(1); // Loop forever, execute in INT Routine;前台循环等待中断.......?
}?
#ifdef FEEDBACK//预编译命令,反馈闭环情况下TMRO中断处理。?
__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?
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???TMRO每0.26ms中断一次,0.26*32=8.333...ms,为60HZ半周?
#ifdef 50Hz?
TMR0L=0x5F; // Make Timer0 interrupt at 3.20KHz for 50Hz output?
TMR0H=0xF8;? ?? ?? ?? ?? ?? ?? ? TMR0每0。3125ms中断一次,0。3125*32=10ms,为50HZ半周?
#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;32个点查完后清index?
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 ;C编译器版本不同此运算不同?
}?
ad_value = read_ad(0);采样RA0端口数值,也即32个中断采样输出电压,就是半周取32个电压输出点。?
out_volt = ad_value - 512; // Read output voltage (512 counts=0 volts out)采样输出电压在512=0。?
// Form the expression y = yold + (0.09261 * (x + xold));根据PID简化公式稳定调节输出电压?
// Where yold, xold is the value of y, x from the previous sample;yold,xold为前次采样到的y,x值?
// x is the , formed by the difference between the output;X为偏差信号,由输出电压波动数值和参考电压的差值来确定?
// of the inverter and the reference signal.?
x = out_volt - reference;//x等于当前输出电压(有AD采样得到)减取参考电压?
y = ((x + xold) * 24);//?
y = y / 256;//即简化计算0.09261 * (x + xold)?
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;限制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)//读AD,CHIP?
{?
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?
}


文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /2 下一条