This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F28335: Send ADC senses over SCI for debug signals

Part Number: TMS320F28335

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 "DSP28x_Project.h" // Device Headerfile and Examples Include File
#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;
}