Dear all,
I am doing software for single phase PLL for grid applications.
I written the software for PLL when compiling using CCSV6 some error occurs.
Error:
Description Resource Path Location Type
unresolved symbol __IQ15sqrt, first referenced in ./Ti_spll_main.obj SPLL_TI_forum C/C++ Problem
unresolved symbol __IQ15isqrt, first referenced in ./Ti_spll_main.obj SPLL_TI_forum C/C++ Problem
unresolved symbol __IQ15div, first referenced in ./Ti_spll_main.obj SPLL_TI_forum C/C++ Problem
unresolved symbol _SGENT_3D_calc, first referenced in ./Ti_spll_main.obj SPLL_TI_forum C/C++ Problem
Please give the suggestion to solve this problem.
/*
* task_main.c
*
* Created on: Aug 28, 2014
* Author: selvanm
*/
#include "F2806x_Device.h"
#include "F2806x_Examples.h"
#include "F2806x_EPwm_defines.h" // useful defines for initialization
#include "sgen.h"
#include "DSP28x_Project.h"
#include "IQmathLib.h"
#include "SPLL_1ph.h"
#include "SineAnalyzer_diff.h"
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// FUNCTION PROTOTYPES
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//void DeviceInit(void);
void InitFlash(void);
void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr);
void cpu_timer0_isr(void);
void ADC_init(void);
void EPWM_init(void);
//void InitPieCtrl(void);
#define PI 3.14156
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// VARIABLE DECLARATIONS - GENERAL
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Used for running BackGround in flash and the ISR in RAM
extern Uint16 RamfuncsLoadStart, RamfuncsLoadEnd, RamfuncsRunStart;
Uint16 duty_cycle_A=500; // Set duty 50% initially
Uint16 duty_cycle_B=500; // Set duty 50% initially
Uint16 duty_cycle_C=500; // Set duty 50% initially
//SGENT_1 sgen=SGENT_1_DEFAULTS;
SGENT_3D sgen=SGENT_3D_DEFAULTS;
int x11,x12,x13,x21,x22,x23;
unsigned int pippo=0, peppe;
Uint16 Adc_Results,i;
int32 Vac_in;
_iq15 InvSine,InvSine1,appoggio_InvSine1,VrmsReal, InvSine3,VavgReal,Vfreq,InvSine2,Theta_pi,sen_theta,theta,kappa,theta_old=0;
_iq16 fase;
float var_float;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// FUNCTION
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void ADC_init(void)
{
EALLOW;
AdcRegs.ADCCTL1.bit.ADCREFSEL = 0; // use internal band gap reference
AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // power up band gap
AdcRegs.ADCCTL1.bit.ADCREFPWD = 1; // power up reference
AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // power up rest of ADC
AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // enable ADC output
for(i=0; i<5000; i++){} // wait 60000 cycles = 1ms (each iteration is 12 cycles)
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // create int pulses 1 cycle prior to output latch
//EOC = end of conversion event, SOC = start of conversion event
AdcRegs.INTSEL1N2.bit.INT1SEL = 1; // ADCCH1 (ADC-A1) EOC causes ADCInterrupt1
// AdcRegs.INTSEL1N2.bit.INT1CONT = 1; // set ADCInterrupt 1 to auto clr (continuous conversion)
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // clear ADCINT1 flag to begin a new set of conversions
AdcRegs.ADCINTFLG.bit.ADCINT1 = 0; // clear interrupt flag for ADCINT1
AdcRegs.INTSEL1N2.bit.INT1E = 1; // enable ADCInterrupt1; 0=none, 1=ADCInt1, 2=ADCInt2
// AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 1; // ADCInterrupt1 causes SOC1
AdcRegs.ADCINTSOCSEL1.all=0x0000; // No ADCInterrupt will trigger SOCx
AdcRegs.ADCINTSOCSEL2.all=0x0000;
AdcRegs.ADCSOC1CTL.bit.CHSEL= 1; // convert ADC-A1 (CH1) when SOC1 is received
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // set S/H window to 6 clk cycles (117ns)
AdcRegs.ADCSOC1CTL.bit.TRIGSEL=9; //Epwm3 adc socA trigger source
EDIS;
AdcRegs.ADCSOCFRC1.all = 0x2; // kick start ADC by causing an ADCInterrupt1 event
}
void EPWM_init(void)
{
#define period 1680 // 60kHz when PLL is set to 0xC (60MHz)
// period 500 // 120kHz when PLL is set to 0xC (60MHz)
//****************************Epwm 2**************************
EPwm2Regs.TBPRD = period; // Set timer period, PWM frequency = 1 / period
EPwm2Regs.TBPHS.all = 0; // Time-Base Phase Register
EPwm2Regs.TBCTR = 0; // Time-Base Counter Register
EPwm2Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // Set Immediate load
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count-up mode: used for asymmetric PWM
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadow register load on ZERO
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero
// Set Compare values
EPwm2Regs.CMPA.half.CMPA = duty_cycle_A; // Set duty 50% initially
EPwm2Regs.CMPB = duty_cycle_B; // Set duty 50% initially
// Set actions
EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM2A on Zero
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM2A on event A, up count
EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM2B on Zero
EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM2B on event B, up count
//****************************Epwm 3**************************
EPwm3Regs.TBPRD = period; // Set timer period, PWM frequency = 1 / period
EPwm3Regs.TBPHS.all = 0; // Time-Base Phase Register
EPwm3Regs.TBCTR = 0; // Time-Base Counter Register
EPwm3Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // Set Immediate load
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count-up mode: used for asymmetric PWM
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadow register load on ZERO
EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero
EPwm3Regs.CMPA.half.CMPA = duty_cycle_C; // Set duty 50% initially
EPwm3Regs.CMPB = duty_cycle_C; // Set duty 50% initially
EPwm3Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM2A on Zero
EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM2A on event A, up count
EPwm3Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM2B on Zero
EPwm3Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM2B on event B, up count
// SOC for PLL
EPwm3Regs.ETSEL.bit.SOCAEN = 1;
EPwm3Regs.ETSEL.bit.SOCASEL = 3; // Use PRD event as trigger for ADC SOC
EPwm3Regs.ETPS.bit.SOCAPRD = 2; // Generate pulse on 2nd event
//****************************Epwm 4**************************
EPwm4Regs.TBPRD = period; // Set timer period, PWM frequency = 1 / period
EPwm4Regs.TBPHS.all = 0; // Time-Base Phase Register
EPwm4Regs.TBCTR = 0; // Time-Base Counter Register
EPwm4Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // Set Immediate load
EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count-up mode: used for asymmetric PWM
EPwm4Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm4Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm4Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadow register load on ZERO
EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero
EPwm4Regs.CMPA.half.CMPA = duty_cycle_C; // Set duty 50% initially
EPwm4Regs.CMPB = duty_cycle_C; // Set duty 50% initially
EPwm4Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM2A on Zero
EPwm4Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM2A on event A, up count
EPwm4Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM2B on Zero
EPwm4Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM2B on event B, up count
}
// ------------- Sine Analyzer Block to measure RMS, frequency and ZCD
SineAnalyzer_diff sine_mainsV = SineAnalyzer_diff_DEFAULTS;
SPLL_1ph spll1;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// MAIN CODE - starts here
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void main(void)
{
//=================================
// INITIALISATION - General
//=================================
//DeviceInit(); // Device Life support & GPIO mux settings
// Only used if running from FLASH
// Note that the variable FLASH is defined by the compiler (-d FLASH)
#ifdef FLASH
// Copy time critical code and Flash setup code to RAM
// The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
// symbols are created by the linker. Refer to the linker files.
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM
InitFlash(); // Call the flash wrapper init function
#endif //(FLASH)
//-------------------------------------------------------------
//****************************Configurazione interrupt timer0 **************************
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2802x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2802x_DefaultIsr.c.
// This function is found in DSP2802x_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize the Device Peripheral. This function can be
// found in DSP2802x_CpuTimers.c
InitCpuTimers(); // For this example, only initialize the Cpu Timers
// Configure CPU-Timer 0 to interrupt every 500 milliseconds:
// 60MHz CPU Freq, 50 millisecond Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, 60, 50);
// To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any
// of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2802x_CpuTimers.h), the
// below settings must also be updated.
CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
// Enable CPU INT1 which is connected to CPU-Timer 0:
IER |= M_INT1;
// Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
//****************************EPWM INITIALISATION**************************
EPWM_init();
//****************************ADC INITIALISATION**************************
ADC_init();
//=================================
// Forever LOOP
//=================================
// Just sit and loop forever:
// No interrups needed in this example.
// PWM pins can be observed with a scope.
kappa=_IQ15(0.1);
sgen.offset=0;
sgen.gain=0x7fff; /* gain = 1 in Q15 */
sgen.freq=5369; /* freq = (Required Freq/Max Freq)*2^15 */
/* = (50/305.17)*2^15 = 5369 */
sgen.step_max=1000; /* Max Freq= (step_max * sampling freq)/65536 */
/* Max Freq = (1000*20k)/65536 = 305.17 */
sgen.phase=0x4000; /* Phase = (required Phase)/180 in Q15 */
/* = (+90/180) in Q15 = 4000h */
// for(;;)
SPLL_1ph_init(50,_IQ21(0.00005),&spll1);
//sine analyzer initialization
sine_mainsV.Vin=0;
sine_mainsV.SampleFreq=_IQ15(8571428.6);//(20000.0)
sine_mainsV.Threshold=_IQ15(0.5);
while(1)
{
EPwm2Regs.CMPA.half.CMPA = (x11/40)+819; // Add duty_cycle_A to watch window
EPwm2Regs.CMPB = (x12/40)+819;
// EPwm3Regs.CMPA.half.CMPA = (x13/40)+819;
EPwm3Regs.CMPA.half.CMPA = (InvSine/40)+819;
EPwm3Regs.CMPB = (x21/40)+819;
EPwm4Regs.CMPA.half.CMPA = (x22/40)+819;
EPwm4Regs.CMPB = Adc_Results/2;
if (sine_mainsV.ZCD==1){
if (x21==0){
sgen.phase++;
}
}
if (AdcRegs.ADCINTFLG.bit.ADCINT1 == 1){
pippo++;
}
// ------------------------------------------------------------------------------
// Connect inputs to the sine analyzer block , compute RMS, Freq, ZCD
// ------------------------------------------------------------------------------
sine_mainsV.Vin =(long)((long)AdcResult.ADCRESULT1<<3);//-_IQ15(0.5);
sine_mainsV.Vin = sine_mainsV.Vin <<1;
SineAnalyzer_diff_MACRO (sine_mainsV);
// VrmsReal = _IQ15mpy (KvInv, sine_mainsV.Vrms);
VrmsReal = _IQ15(sine_mainsV.Vrms);
Vfreq = _IQ15(sine_mainsV.SigFreq);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Interrupt
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
interrupt void cpu_timer0_isr(void)
{
//GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Toggle GPIO34 once per 500 milliseconds
GpioDataRegs.GPATOGGLE.bit.GPIO16=1;
CpuTimer0.InterruptCount++;
//SPLL_1ph_run(&spll1);
sgen.calc(&sgen);
x11=sgen.out11;
x12=sgen.out12;
x13=sgen.out13;
x21=sgen.out21;
x22=sgen.out22;
x23=sgen.out23;
SPLL_1ph_MACRO(spll1);
Vac_in=(long)((long)AdcResult.ADCRESULT1<<9);
spll1.AC_input=Vac_in>>1;
InvSine = (long)(spll1.sin[0])>>6; // InvSine is in Q15
InvSine2 = (long)(spll1.cos[0])>>6; // InvCos is in Q15
// InvSine3 = _IQ15(InvSine2 * _IQ15(0.1)) + InvSine;
InvSine3 = _IQ15mpy(InvSine2,kappa)+ InvSine;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
Adc_Results = AdcResult.ADCRESULT1;
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag
}
Regards,
Muthu