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.

28035 ADC software trigger problem



Greetings.

Recently, I try to trigger ADC start of conversion via software seting flags, however, there might be something

wrong with my ADC setup so that it could not start properly as I wish.  

AdcRegs.ADCSOCFRC1.bit.SOC0 is stil zero even though I set it to 1.

Here is my code----------------------------------------------------

-------start of code(only code related to ADC)----------

--------------------------------------------------------------------------

void main()
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();

// Step 2. Initalize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
InitEPwm6Gpio();
// Initialize 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 DSP2833x_PieCtrl.c file.
InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
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 register
PieVectTable.ADCINT1 = &adc_isr;
// Enable ADCINT1 in PIE
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2803x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
InitAdc(); // For this example, init the ADC
InitEPwm6();

// Step 5. User specific code, enable interrupts:
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

LoopCount = 0;
ConversionCount = 0;

for(i=0;i<512;i++)
{
SampleTable[ConversionCount] = 0;
ConversionCount++;
}
ConversionCount = 0;

Adc_Config();
//Force start of conversion on SOC0
EALLOW;
AdcRegs.ADCSOCFRC1.all = 0x03;
EDIS;

for(;;)
{
asm("NOP");


}
}
interrupt void adc_isr(void)
{
//Wait for end of conversion.
while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){} //Wait for ADCINT1
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1

SampleTable[ConversionCount] = AdcResult.ADCRESULT0;

// If 512 conversions have been logged, start over
if(ConversionCount == 512)
{
ConversionCount = 0;
}
else ConversionCount++;

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

return;
}
void Adc_Config()
{
// Configure ADC
EALLOW;
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch
AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //setup EOC1 to trigger ADCINT1 to fire
AdcRegs.ADCSOC0CTL.bit.CHSEL = 7; //set SOC0 channel select to ADCINA7
AdcRegs.ADCSOC1CTL.bit.CHSEL = 7; //set SOC1 channel select to ADCINA7
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; //set SOC0 start trigger on software
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0; //set SOC1 start trigger on software
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 1; //ADCINT1 will trigger SOC0. TRIGSEL field is ignored.
AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 1; //ADCINT1 will trigger SOC0. TRIGSEL field is ignored.
EDIS;
} ---------------------------------------------------------------------- -----------------end of code--------------------------------------- ---------------------------------------------------------------------- Is there something I could do to start ADC ? I would be glad, if someone could give me a hand. JOE Chao


  • Hi JOE Chao,

    I have a similar problem, i would like to trigger my SOC0 on TIMER0 but it doesn't work. After that I have tried to trigger by software, and it worked
    And my code almost looks like yours. Unfortunately the timer0 problem is still unsolved.

    In void Adc_Config() for safety maybe you should put

    	AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;   //Clear ADCINT1 flag reinitialize for next SOC


    best regards,
    Tomi

  • JOE,

    The AdcRegs.ADCSOCFRC1.bit.SOC0 bit will not become 1 when you write a 1 to it.  The action of writing a 1 will cause SOC0 to become pending, which will set the SOC0 but in the ADCSOCFLG1 register.  The bit in the ADCSOCFLG1 register will be cleared as soon as the ADC converts SOC0.  

    I would recommend that you check the ADC result registers directly to determine if your software force of the SOC was successful.

    Tomi,

    Can you be more specific about how the conversion failed?  Did the result register not get updated or was the conversion value not what you expected? 

  • Devin,

    //I configured CPU TIMER0 :

        InitCpuTimers();
        ConfigCpuTimer(&CpuTimer0, 100, 1000000);  // 1 sec     
        StartCpuTimer0();

    //ADC fonfig:
        EALLOW;
        Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;     // Enable non-overlap mode i.e.
        Adc1Regs.ADCCTL1.bit.INTPULSEPOS   = 0;           // ADCINT1 trips after AdcResults latch

        Adc1Regs.INTSEL1N2.bit.INT1SEL     = 0;                // setup EOC0 to trigger ADCINT1 to fire
        Adc1Regs.INTSEL1N2.bit.INT1E       = 1;                   // Enabled ADCINT1
        Adc1Regs.INTSEL1N2.bit.INT1CONT    = 0;             // Disable ADCINT1 Continuous mode
        
        Adc1Regs.ADCSOC0CTL.bit.CHSEL      = 0;            // set SOC0 channel select to ADC1A0
        Adc1Regs.ADCSOC0CTL.bit.TRIGSEL    = 1;           // Set SOC0 start trigger to ADC Trigger 1
        Adc1Regs.ADCSOC0CTL.bit.ACQPS      = 6;            // set SOC0 S/H Window to 7 ADC Clock Cycles
        AnalogSysctrlRegs.TRIG1SEL.bit.TRIG1SEL   = 1;   // Trigger by CPU Time 0
           
        Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 = 1;                                                                                 
        EDIS;

    And the ADC trigger does not work one second. It works much faster. The timer should trigger the conversion when it reaches the zero in this case 1 second. Am I right?

    Thank you for the help in advance!

    Best regards,
    Tomi



  • HI,Tomi.

    Firstly, thanks for your help.

    And I pinpointed the problems after several experiments.

    1.To realize continuous mode triggered by software, this have to be in interrupt void adc_isr(void):

     EALLOW;

     AdcRegs.ADCSOCFRC1.all = 0x03;

     EDIS;

    and the program run well.

    2.Another way to make it is that we can enable continuous mode:

    AdcRegs.INTSEL1N2.bit.INT1CONT  = 0; //Disable ADCINT1 Continuous mode

    substitute 0 with 1 so that we can use this mode.

    3. To avoid unexpected problems, I recommand that it is better to setup 2 SOC at the same time or to use 

    other single SOC instead of SOC0. When I only setup SOC0, I found software trigger not work properly even

    though I keep rest of setups the same as it could work.

  • Devin, thank you for answering.

    I already make it and post my solustions.

  • Unfortunately, configure more SOC at the same time doesn't help in timer trigger mode.  Anyway the software trigger for me worked properly with only SOC0 and without the 

    AdcRegs.ADCSOCFRC1.all = 0x03; line in the interrupt fuction.

    But my problem is the CPU timer trigger. It doesn't work properly.

    main()

    {

    InitSysCtrl();

    // 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 F28M35x_PieCtrl.c file.

    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:

    IER = 0x0000;

    IFR = 0x0000;

    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 register

    PieVectTable.ADCINT1 = &adc1_isr;

    EDIS; // This is needed to disable write to EALLOW protected registers

     

    InitAdc1(); // For this example, init the ADC

    InitCpuTimers(); // For this example, only initialize the Cpu Timers

    ConfigCpuTimer(&CpuTimer0, 100, 1000000); // 1 sec

    StartCpuTimer0();

     

    // Enable ADCINT1 in PIE

    // Enable TINT0 in the PIE: Group 1 interrupt 7

    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE

    IER |= M_INT1; // Enable CPU Interrupt 1

    EINT; // Enable Global interrupt INTM

    ERTM; // Enable Global realtime interrupt DBGM

    // Configure ADC

    EALLOW;

    Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;

    Adc1Regs.ADCCTL1.bit.INTPULSEPOS = 0; // ADCINT1 trips after AdcResults latch

    Adc1Regs.INTSEL1N2.bit.INT1SEL = 0; // setup EOC0 to trigger ADCINT1 to fire

    Adc1Regs.INTSEL1N2.bit.INT1E = 1; // Enabled ADCINT1

    Adc1Regs.INTSEL1N2.bit.INT1CONT = 0; // Disable ADCINT1 Continuous mode

    Adc1Regs.ADCSOC0CTL.bit.CHSEL = 0; // set SOC0 channel select to ADC1A0

    Adc1Regs.ADCSOC0CTL.bit.TRIGSEL = 1; // Set SOC0 start trigger to ADC Trigger 1

    Adc1Regs.ADCSOC0CTL.bit.ACQPS = 6;

    AnalogSysctrlRegs.TRIG1SEL.bit.TRIG1SEL = 1; // Trigger by CPU Time 0

    Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC

    EDIS;

    // Wait for ADC interrupt

    for(;;)

    {

    }

    interrupt void adc1_isr(void)

    {

    result = Adc1Result.ADCRESULT0;

    Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

    return;

    }

    I don't undertand AD conversion why not happens 1 seconds. It is much faster than i assume.

  • Markus,

    I see an error in your code that is causing your problem.  You need to set Adc1Regs.ADCSOC0CTL.bit.TRIG1SEL = 5.  This will assign CPU Timer 0 to ADC Trigger 1.  Valid values for this bit field are 0x5 - 0xC for ADC Triggers 1-8.

    Regards,

    Ricky

  • Ricky,

    Thank you for your answer.  Adc1Regs.ADCSOC0CTL.bit.TRIGSEL = 5. solved my problem.

    Once again my grateful thanks.

    Regards,
    Tamas

  • Hello,

    I have the same problem you had.

    I read your solution but I have a question:

    if you put

    ----------

    EALLOW;

     AdcRegs.ADCSOCFRC1.all = 0x03;

     EDIS;

    ------------

    inside interrupt void adc_isr(void), who calls the interrupt?

    Thanks,

    michi

  • Michi,

    The ADCSOCFRC1 register only forces the start of a conversion.  After the end of a conversion, an EOC (end of conversion) signal is generated, which can generate ADCINT1 depending on how the ADC registers are configured.  ADCINT1 will generate an interrupt and the code will jump into the ADC interrupt routine.

    Regards,

    Ricky

  • Hi Ricky,

    It's a old post but I was wondering why would you have TRIG1SEL value as 5? Isn't that value 5 corresponds to ePWM1 SOC A trigger source?
    I apologize for any inconvenience.