Tool/software: Code Composer Studio
Hello, thanks for your support.
I am trying to develep the code for a AC-DC converter with PFC. My main problem is with the sample frequency. I need a switching frequency near to 40kHz without PWM. I want to use hysteresis modulation; that is, I need to sample the input current very fast (I want to obtain 50 samples per period = 2MHz sample frequency). I am using an ISR in Timer 0 to control the switching and sample with A0 Channel in ADC. I need to use a PLL to obtain the reference signal to control the input current phase and shape. Besides, I need to use the PI algorithm to control the output voltage (DC voltage). I am trying to use the SCI for debug the signals. When I include the SCI or PLL code inside the ISR in each timer causes that I loss the sample frequency control.
I atach you the main code.
#include <math.h>
#include "spll_1ph_sogi.h" //archivo de cabecera de las funciones que implementan el pll
#include <stdio.h>
/////////////////////
//DEFINES //
/////////////////////
#define HB 0.5
#define switch_off GpioDataRegs.GPBDAT.bit.GPIO33=0
#define switch_on GpioDataRegs.GPBDAT.bit.GPIO33=1
/////////////////////
//Funtion prototypes//
/////////////////////
void scia_echoback_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(char *msg);
void delay_loop(void);
void Gpio_select(void);
void Init_Adc(void);
float adaptive_band(float L, float Fsw, float voltage_in, float voltage_dc);
// Function Prototype statements of CPU ISR interruptions
//
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);
__interrupt void adc_isr(void);
/////////////////////
// VARIABLES //
/////////////////////
volatile float adc_read = 678.0123;
volatile float current_in, current_ref_dc, current_ref_ac, S, lim_sup, lim_inf;
volatile float voltage_out, voltage_out_ref;
volatile float voltage_in;
volatile float spll_sine,spll_cosine;
volatile float borrar;
char str[20]="\n";
volatile Uint16 i,j, flag1;
volatile unsigned char ISR_timer0_flag;
volatile unsigned char ISR_timer1_flag;
volatile unsigned char ISR_timer2_flag;
/////////////////////
//Objets definitions//
/////////////////////
SPLL_1PH_SOGI spll1;//Declaracion del objeto del pll
#define BUF_SIZE 128 // Sample buffer size
Uint16 buffer_current_in[BUF_SIZE];
Uint16 buffer_voltage_in[BUF_SIZE];
volatile float buffer_pll[BUF_SIZE];
Uint16 buffer_voltage_out[BUF_SIZE];
void main(void)
{
i=0;
j=0;
lim_sup=2.6;
lim_inf=0.5;
current_ref_dc=1;
flag1=0;
InitSysCtrl();// Initialize System Control:// PLL, WatchDog, enable Peripheral Clocks
Gpio_select();//Select Gpio as output
InitSciaGpio();//Inicializa el SCIa, cambiar por a, b o c
DINT;//Clear all interrupts and initialize PIE vector table // Disable CPU interrupts
InitPieCtrl();// Initialize PIE control registers to their default state.The default state is all PIE interrupts disabled and flagsare cleared.
IER = 0x0000; // Disable CPU interrupts and clear all CPU interrupt flags
IFR = 0x0000;//Interrupt-Control Registers
InitPieVectTable();// Initialize the PIE vector table with pointers to the shell InterruptService Routines (ISR).This will populate the entire table, even if the interrupt
//
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &cpu_timer0_isr;
PieVectTable.XINT13 = &cpu_timer1_isr;
PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
InitCpuTimers(); // For this example, only initialize the Cpu Timers
//
// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 150MHz CPU Freq, 1 second Period (in uSeconds)
//
ConfigCpuTimer(&CpuTimer0, 150, 1);//Frecuencia de la interrupcion 1 de 2MHz. 0.5uS, si es necesario se puede reducir hasta 0.2uS
ConfigCpuTimer(&CpuTimer1, 150, 333);//Frecuencia de la interrupcion 40kHz. 25us
ConfigCpuTimer(&CpuTimer2, 150, 2000000);//Frecuencia de la interrupcion 10kHz. 100uS
//
// 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 DSP2833x_CpuTimers.h), the
// below settings must also be updated.
//
CpuTimer0Regs.TCR.all = 0x4000; //write-only instruction to set TSS bit = 0
CpuTimer1Regs.TCR.all = 0x4000; //write-only instruction to set TSS bit = 0
CpuTimer2Regs.TCR.all = 0x4000; //write-only instruction to set TSS bit = 0
// Step 5. User specific code, enable interrupts
// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2:
//
IER |= M_INT1;
IER |= M_INT13;
IER |= M_INT14;
// Enable TINT0 in the PIE: Group 1 interrupt 7
//
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// Step 6. IDLE loop. Just sit and loop forever (optional):
Init_Adc(); // init the ADC
EnableInterrupts();
scia_fifo_init(); // Initialize the SCI FIFO
scia_echoback_init(); // Initialize SCI for echoback
// msg = "\r\n\n\nHello World!\0";
// scia_msg(msg);
SPLL_1PH_SOGI_reset(&spll1);
SPLL_1PH_SOGI_config(&spll1, 60, 3000,(float32_t)(222.2862),(float32_t)(-222.034));
for (j=0; j<BUF_SIZE; j++){
buffer_current_in[j];
buffer_voltage_in[j];
buffer_pll[j];
buffer_voltage_out[j];
// Enable global Interrupts and higher priority real-time debug events:
//
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
}
for(;;)
{
current_in= (0.000050354)*(float)AdcRegs.ADCRESULT0;
voltage_out=(3.3/65536)*((float)(AdcRegs.ADCRESULT2));
voltage_in= ((3.3/65536)*AdcRegs.ADCRESULT1-1.65)*20;
if (ISR_timer1_flag==1){//Timer 3kHz
ISR_timer1_flag=0;
}//end Flag timer 3kHz
if (ISR_timer2_flag==1){//Timer 2sec
if(flag1==1){
for(j=0;j<BUF_SIZE;j++){
sprintf(str,"%u\n",buffer_voltage_in[j]);
scia_msg(str);
}
flag1=0;
}
ISR_timer2_flag=0;
}//end Flag timer 10kHz
}//end infinite for
}//end main
///////////////////////////////////////////////////////////////////
// Funciones
/////////////////////////////////////////////////////////////////////
//
// scia_echoback_init - Test 1,SCIA DLB, 8-bit word, baud rate 0x000F,
// default, 1 STOP bit, no parity
//
void
scia_echoback_init()
{
//
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
//
// 1 stop bit, No loopback, No parity,8 char bits,
// async mode, idle-line protocol
//
SciaRegs.SCICCR.all =0x0007;
//
// enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
//
SciaRegs.SCICTL1.all =0x0003;
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =0;
SciaRegs.SCICTL2.bit.RXBKINTENA =0;
SciaRegs.SCIHBAUD =0x0001; // 9600 baud @LSPCLK = 37.5MHz.
SciaRegs.SCILBAUD =0x00E7;
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}
//
// scia_xmit - Transmit a character from the SCI
//
void
scia_xmit(int a)
{
while (SciaRegs.SCIFFTX.bit.TXFFST != 0)
{
}
SciaRegs.SCITXBUF=a;
}
//
// scia_msg -
//
void
scia_msg(char * msg)
{
int i;
i = 0;
while(msg[i] != '\0')
{
scia_xmit(msg[i]);
i++;
}
}
//
// scia_fifo_init - Initialize the SCI FIFO
//
void
scia_fifo_init()
{
SciaRegs.SCIFFTX.all=0xE040;
SciaRegs.SCIFFRX.all=0x204f;
SciaRegs.SCIFFCT.all=0x0;
}
//
float adaptive_band(float L, float Fsw, float voltage_in, float voltage_dc)
{
return (voltage_in*(voltage_dc-voltage_in))/2*L*Fsw*voltage_dc;
}
void Gpio_select(void)
{
// Enable the pin GPIO34 as output
//
EALLOW;
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // GPIO pin
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // Output pin
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 0; // GPIO pin
GpioCtrlRegs.GPBDIR.bit.GPIO33 = 1; // Output pin
EDIS;
}
void Init_Adc(void)
{
extern void DSP28x_usDelay(Uint32 Count);
/***************************************************************************************************
* XCLKIN SYSCLKOUT HISPCLK ADCTRL3[4-1] ADCTRL1[7] ADCCLK ADCTRL1[11-8] SH Width
* HSPCP=3 ADCLKPS=0 CPS=0 ACQ_PS=0 12.5 MSPS sustained
* 30MHz 150MHz 25MHz 25MHz 25MHz 25MHz 12.5 MHz 40 ns
**************************************************************************************************/
EALLOW;//This bit, when set, enables access to emulation and other protected registers. Set this bit by using the EALLOW instruction and clear this bit by using the EDIS instruction.
SysCtrlRegs.HISPCP.all = 3; //esta instruccion equivale a ADC_MODCLK=0x3; HSPCLK = SYSCLKOUT/ADC_MODCLK;ADC_MODCLK=0x3
EDIS;
// Default - 150 MHz SYSCLKOUT // configuracon del reloj del ADC
// HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz ; i.e. (SysCtrlRegs.HISPCP.all = 3;)
// ADC module clock = HSPCLK/2*ADC_CKPS = 25.0MHz/(1*2) = 12.5MHz
//
// *IMPORTANT*
// The ADC_cal function, which copies the ADC calibration values from
// TI reserved OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs
// automatically in the Boot ROM. If the boot ROM code is bypassed during
// the debug process, the following function MUST be called for the ADC to
// function according to specification. The clocks to the ADC MUST be
// enabled before calling this function. See the device data manual and/or
// the ADC Reference Manual for more information.
//
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK=1; //Set the ADC clock enable
ADC_cal();
EDIS;
//
// To powerup the ADC the ADCENCLK bit should be set first to enable
// clocks, followed by powering up the bandgap, reference circuitry, and
// ADC core. Before the first conversion is performed a 5ms delay must be
// observed after power up to give all analog circuits time to power up
// and settle
//
// Please note that for the delay function below to operate correctly the
// CPU_RATE define statement in the DSP2833x_Examples.h file must
// contain the correct CPU clock period in nanoseconds.
//
AdcRegs.ADCTRL3.all = 0x00E0; // Power up bandgap/reference/ADC circuits
DELAY_US(5000L); // Delay before converting ADC channels//Allow a delay of 5 ms for F280xx (10 ms for F281x) after ADC power up so that the external
//capacitors on the REFP and REFN pins are charged properly . ADC counts during this
//period (delay) will not be accurate.
// Specific ADC setup
//1. Setting the ADC Clock Frequency and Sampling Rate
AdcRegs.ADCTRL1.bit.CPS=0; //ADC module clock =25.0MHz; CPS=0 => ADCCLK = Fclk/1
AdcRegs.ADCTRL1.bit.ACQ_PS = 0;//This bit field controls the width of SOC pulse, which, in turn, determines for what time duration the sampling switch is closed.ACQ_PS = 0 Fclk/1; ACQ_PS = 1 Fclk/2; S/H width in ADC module periods = 1 ADC clocks 12.5 MHz 12.5 MSPS sustained 40 ns; ADCCLKPS = 5 cause 12,5Mhz/10.
AdcRegs.ADCTRL3.bit.ADCCLKPS = 0; // ADCCLKPS = 0; ADC module clock = HSPCLK/2*ADCCLKPS = 25.0MHz/(1*2) = 12.5MHz
AdcRegs.ADCMAXCONV.all = 0x0003; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; //Set ADCCHSELSEQ1 to ADCCHSELSEQ4 registers to assign the ADC input channel (ADCINAx andADCINBx) for each conversion (CONVnn).
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; //Set ADCCHSELSEQ1 to ADCCHSELSEQ4 registers to assign the ADC input channel (ADCINAx andADCINBx) for each conversion (CONVnn).
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2; //Set ADCCHSELSEQ1 to ADCCHSELSEQ4 registers to assign the ADC input channel (ADCINAx andADCINBx) for each conversion (CONVnn).
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run
AdcRegs.ADCTRL3.bit.SMODE_SEL=0; // 0 for sequential mode and to 1 for simultaneous mode.
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 Cascaded mode
AdcRegs.ADCTRL2.all = 0x2000; // Start SEQ1 Reset sequencer1 Writing a 1 to this bit resets SEQ1 or the cascaded sequencer immediately to an initial "pretriggered" state, i.e., waiting for a trigger at CONV00. A currently active conversion sequence will be aborted.
}
// cpu_timer0_isr -Frecuencia de la interrupcion 1 de 2MHz. 0.5uS
//
__interrupt void cpu_timer0_isr(void){
if(current_in>2){switch_off;}
else if(current_in<1){switch_on;}
//if (flag1==0){buffer_current_in[i++] = AdcRegs.ADCRESULT0;}
// if(i>=BUF_SIZE){i=0;flag1=1;}
CpuTimer0.InterruptCount++;
//ISR_timer0_flag=1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Acknowledge this interrupt to receive more interrupts from group 1
}
//
// cpu_timer1_isr - -Frecuencia de la interrupcion de 40kHz. 25uS
//
__interrupt void
cpu_timer1_isr(void)
{
SPLL_1PH_SOGI_run(&spll1,voltage_in); //ejecuta el pll y obtiene la medida
spll_sine=spll1.sine;
//spll_cosine=spll1.cosine;
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;
if (flag1==0){
buffer_voltage_in[i++] = AdcRegs.ADCRESULT1;
buffer_pll[i] = spll_sine;
}
if(i>=BUF_SIZE){i=0;flag1=1;}
EALLOW;
CpuTimer1.InterruptCount++;
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Acknowledge this interrupt to receive more interrupts from group 1
//
EDIS;
ISR_timer1_flag=1;
}
//
// cpu_timer2_isr -Frecuencia de la interrupcion de 10kHz. 100uS
//
__interrupt void
cpu_timer2_isr(void)
{
EALLOW;
CpuTimer2.InterruptCount++;
// The CPU acknowledges the interrupt.
EDIS;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Acknowledge this interrupt to receive more interrupts from group 1
ISR_timer2_flag=1;
}