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/TMS320F28062: ADC didn't work when it was configured to be triggered by CPU timer0.

Part Number: TMS320F28062
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

Tool/software: Code Composer Studio

I need SOC3-SOC12 of ADC module to start conversion every 1ms.My ADC module configuration is listed below:

    EALLOW;
    AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 0x03;///< SOC0-SOC2 are high priority;
    AdcRegs.SOCPRICTL.bit.ONESHOT = 1;   ///< Enable one shot mode.

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0x03; 
    AdcRegs.ADCSOC1CTL.bit.CHSEL = 0x05; 
    AdcRegs.ADCSOC2CTL.bit.CHSEL = 0x0C; 

    AdcRegs.ADCSOC3CTL.bit.CHSEL = 0x00; ///< ADCINA0,Grid voltage L1n;
    AdcRegs.ADCSOC4CTL.bit.CHSEL = 0x01; ///< ADCINA1,Grid voltage L2n;
    AdcRegs.ADCSOC5CTL.bit.CHSEL = 0x02; ///< ADCINA2,Grid voltage L3n;
    AdcRegs.ADCSOC6CTL.bit.CHSEL = 0x0A; ///< ADCINB2,DC bus voltage;
    AdcRegs.ADCSOC7CTL.bit.CHSEL = 0x07; ///< 

    AdcRegs.ADCSOC8CTL.bit.CHSEL = 0x04; ///< ADCINA4,Charging Module temperature;
    AdcRegs.ADCSOC9CTL.bit.CHSEL = 0x06; ///< ADCINA6,IPM temperature;
    AdcRegs.ADCSOC10CTL.bit.CHSEL = 0x08;///< ADCINB0,Air temperature;
    AdcRegs.ADCSOC11CTL.bit.CHSEL = 0x09;///< ADCINB1,Motor temperature;
    AdcRegs.ADCSOC12CTL.bit.CHSEL = 0x0B;///< ADCINB3,IGBT temperature;

    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0x06;///< ePWM1 ADCSOCB trigger SOC0
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0x06;///< ePWM1 ADCSOCB trigger SOC1
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 0x06;///< ePWM1 ADCSOCB trigger SOC2

    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC3
    AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC4
    AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC5
    AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC6
    AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC7
    AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC8
    AdcRegs.ADCSOC9CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC9
    AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC10
    AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC11
    AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 1;   ///< CPU Timer0 trigger SOC12

    AdcRegs.INTSEL1N2.bit.INT1CONT = 1; ///< Enable continuous mode.
    AdcRegs.INTSEL1N2.bit.INT1SEL = 2;  ///< A interruption will be generated after competition of SOC2.
    AdcRegs.INTSEL1N2.bit.INT2CONT = 1; ///< Enable continuous mode.
    AdcRegs.INTSEL1N2.bit.INT2SEL = 12; ///< A interruption will be generated after competition of SOC11.
    AdcRegs.INTSEL1N2.bit.INT1E = 1;
    AdcRegs.INTSEL1N2.bit.INT2E = 1;

    AdcRegs.ADCINTSOCSEL1.all = 0;
    AdcRegs.ADCINTSOCSEL2.all = 0;

    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;    //ADCINTs generated at end of conversion
    AdcRegs.ADCCTL1.bit.VREFLOCONV = 0;
    AdcRegs.ADCCTL1.bit.TEMPCONV = 0;
    AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;  ///< Select internal reference voltage.
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1;
    EDIS;

There were two ADC interruption,one for SOC2 and another for SOC12.CPU TIMER 0 was configured to gernated a interruption every 1ms,and it worked well.But ISR of ADCINT2 was called only twice by CPU.The problem bothered me all day.At last,I had to change the trigger source to software trigger .

Is there anyone who can tell me why the ADC don't work with CPU TIMER 0 as its trigger source?

Thanks in advance for the help.

 


  • Hi,
    Can you share your timer configuration & ISR code as well? Check if flags are cleared properly in ISR.

    Thanks
    Vasudha
  • Thanks for your reply.

    Fallowing are My timer configuration & ISR of ADC INT2:

    InitCpuTimers();
    ConfigCpuTimer(&CpuTimer0, 90, ANALOG_SAMPLE_PERIOD);///< ANALOG_SAMPLE_PERIOD = 1000
    
    void cpu_timer0_isr(void)///< PIE1.7
    {
    	CpuTimer0.InterruptCount++;
    	if(CpuTimer0.InterruptCount >= CFG_PERIOD_ANALOGS_TO_CONTROL)
    	{
    		CpuTimer0.InterruptCount = 0;
    	}
    	AdcRegs.ADCSOCFRC1.all = 0x1FF8;///< SOC3->SOC12
    
    
    	CpuTimer0Regs.TCR.bit.TIF = 1; ///< Clear interruption flag,Write 1 clear.
    	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

    ISR of ADCINT2:

    void ADCInt2ISR(void)///< PIE1.2
    {
    	g_AnalogsStruc.m_L3N.m_ValADC = (short)AdcResult.ADCRESULT3 - (short)AdcResult.ADCRESULT5;   ///< Line voltage:WU
    	g_AnalogsStruc.m_L2N.m_ValADC = (short)AdcResult.ADCRESULT4 - (short)AdcResult.ADCRESULT3;   ///< Line voltage:VW
    	g_AnalogsStruc.m_L1N.m_ValADC = (short)AdcResult.ADCRESULT5 - (short)AdcResult.ADCRESULT4;   ///< Line voltage:UV
    	g_AnalogsStruc.m_DCBus.m_ValADC = AdcResult.ADCRESULT6 + DCBUS_V_COMPST;
    	g_AnalogsStruc.m_MotorStallCurrent.m_ValADC = AdcResult.ADCRESULT7;
    
    	g_AnalogsStruc.m_ChargeTmpt.m_ValADC = AdcResult.ADCRESULT8;
    	g_AnalogsStruc.m_SinkTmpt.m_ValADC = AdcResult.ADCRESULT9;
    	g_AnalogsStruc.m_AirTmpt.m_ValADC = AdcResult.ADCRESULT10;
    	g_AnalogsStruc.m_MotorTmpt.m_ValADC = AdcResult.ADCRESULT11;
    	g_AnalogsStruc.m_IGBTTmpt.m_ValADC = AdcResult.ADCRESULT12;
    
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_L3N);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_L2N);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_L1N);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_DCBus);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_MotorStallCurrent);
    
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_ChargeTmpt);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_SinkTmpt);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_AirTmpt);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_MotorTmpt);
    	DF1st(&g_DF1stAnalog,&g_AnalogsStruc.m_IGBTTmpt);
    
    
    	AdcRegs.ADCINTFLGCLR.bit.ADCINT2 = 1;
    	AdcRegs.ADCINTOVFCLR.bit.ADCINT2 = 1;
    	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
    }

  • void cpu_timer0_isr(void)///< PIE1.7 { CpuTimer0.InterruptCount++; if(CpuTimer0.InterruptCount >= CFG_PERIOD_ANALOGS_TO_CONTROL) { CpuTimer0.InterruptCount = 0; } AdcRegs.ADCSOCFRC1.all = 0x1FF8;///< SOC3->SOC12 CpuTimer0Regs.TCR.bit.TIF = 1; ///< Clear interruption flag,Write 1 clear. PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }

    Hi,

    I think the problem is because you are acknowledging the Group 1 interrupt in both CPU Timer & ADCINT ISR. Do you need both the ISRs in your application? You can disable the timer 0 interrupt at PIE level and use the timer 0 as trigger for ADC or try using timer 1 or timer 2 as ADC triggers.

    Thanks

    Vasudha

  • Hi,

    I realized that both timer0, ADCINT1 & ADCINT2 are in same group i.e. group 1 and it is acknowledged in both the timer & ADC ISR. This might be creating the problem. Can you try using timer 1 or timer 2 as trigger and see if ADCINT2 ISR is getting called.

    Thanks
    Vasudha
  • Hi,
    I'm sorry I forgot to provide some information.I used the same software prioritized interrupt as TI provided example.Priority of ADCINT1 ,ADCINT2 and timer0 interrupt is 1,2,2 respectively.ADCSOC1-ADCSOC2 was triggered by ePWM1 at frequency 20kHz.EOC2 event triggered ADCINT1.
    Back to my problem,what you sayed really puzzles me.would it block the CPU from calling ADCINT2 to acknowledge the interrupt group at the end of timer& ADC ISR ?But In TI provided example,every ISR include a statement to acknowledge interrupt group.
    I do comment the statement of acknowledging interrupt group at the end of my every interrupt service function.But the problem exists as before.
  • Hi,
    Yes you are correct, we need to acknowledge the interrupt in every ISR. I have modified the earlier reply. I thought the ADC interrupt is getting acknowledged in timer ISR as well.

    Do you need timer 0 ISR in your application? You can disable the CPU Timer 0 interrupt at PIE level & still trigger the ADC. Both ADCINT and timer 0 are in same PIE group and the group interrupt is acknowledged in both the ISRs which could be the problem.

    For the solution, you can enable the Timer0 interrupt at peripheral level but disable it at PIE level. Keep the ADCINT part as-is. This should resolve the problem.

    Thanks
    Vasudha
  • Hi,
    Thanks for your patience.
    I disable the CPU TIMER0 interrupt by clearing the related bit in PIEIER and leave the ADCINT as it was.But the ISR of ADCINT2 is still not called.
    I think there is no wrong about interrupt.Maybe,Something is wrong in configuring SOC2-SOC12 trigger sources .So, the SOC2-SOC12 of ADC did not work.
    I debuged my program in application,and found that the result register of SOC2-SOC12 did not change.
  • Xing,

    You probably do not want to perform a software SOC force in your TIMER ISR:

    AdcRegs.ADCSOCFRC1.all = 0x1FF8;///< SOC3->SOC12
    

    The TIMER itself will generate a trigger as configured.  You are almost certainly creating an overflow by triggering the SOCs again.

    It may be a good idea to go back to the adc_soc example from C2000Ware or controlSUITE to make sure that your ADC hardware conversions are working with EPWM triggers.  Then change the EPWM trigger to TIMER trigger to make sure that your software configuration for TIMER triggers is good.

    -Tommy

  • Hi,
    I compared carefully my ADC configuration with TI example as you suggest.Finally,I found that TI example didn't configure ADC to work in ONESHOT mode.After commented the ONESHOT mode statement,the ADCINT2 worked normally!
    But i still want to know the reason.
    According to “Piccolo Technical Reference Guide”,the ADC will perform a single conversion on the next triggered SOC in the round robin scheme. So,no matter the performing sequence,SOC12 is eventually triggered ,then EOC12 will generate a interrupt.But the reality is the ADCINT2 ISR is never called again after be called twice at the beginning.
  • Xing,

    Does it work if you remove the extraneous ADCSOCFRC1 trigger?

    -Tommy
  • Tommy,
    The ADCSOCFRC1 trigger was added after i had found that CPU timer0 didn't trigger ADC conversion.
    Removing configuration for ONESHOT mode can solve my problem.But i don't know why!

  • Xing,

    I am unable to conclude why removing ONESHOT would make everything work.  In my opinion, there are too many variables at play here.  For example, double-triggering the ADC can result in strange behavior.

    If you wish to fully debug the behavior, you will need to simplify the code and make sure that every register setting is producing the desired behavior.  This includes TIMER0 successfully triggering the ADC.

    -Tommy

  • Xing,

    You can start with the adc_soc example and proceed as below.  Make sure that you clear the interrupt flags by performing a CPU reset or power-down between steps.

    1. Build & run unmodified example with breakpoint set in ISR on instruction "ConversionCount = 0;"  This should behave as expected with a breakpoint halt every 10 EPWM triggers.
    2. Remove the EPWM configuration.  Build & run with the same ADC ISR breakpoint.  This run should never halt because the EPWM is not issuing ADC triggers.
    3. Change the ADC TRIGSEL settings from EPWM (5) to CPU TIMER (1).  The TIMER is already enabled.  Build & run with the same ADC ISR breakpoint.  This run should halt every 10 TIMER triggers.
    4. Enable the TIMER interrupt by setting TCR[TIE] and PIEIER1[INTx7].  Add in a TIMER ISR that does nothing but set PIEACK[PIEACK_GROUP1].  Set a breakpoint in the TIMER ISR and at the normal ADC ISR breakpoint.  Build & run.  This run should halt at the TIMER ISR 10 times for every ADC ISR halt.

    -Tommy