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.

CCSTUDIO-C2000: Any F28M36x ADC1 document

Part Number: CCSTUDIO-C2000
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

Hi, 

I am trying to understand how to program ADC1 and is there any document I can refer to?

I have some existing sample codes for initialization but when i tried to print out the reading value and it seems all 0s. 

void ADC_Init()

{

*(unsigned int*)0x4E58 = 7; // Workaround for InitAnalogSystemClock() Advisory
if( ((**InitAnalogSystemClock)(ACLKDIV4) | 0x8000) != 0xA005 ) {
// If return value is not 0xA005, then analog subsystem did not initialize correctly
asm (" ESTOP0");
for(;;) ;
}

EALLOW;
// Initialize the Analog Sub-System and set the clock divider to divide by 4
while((**AnalogClockEnable)(AnalogConfig1,ADC1_ENABLE)); // Enable ADC 1
while((**AnalogClockEnable)(AnalogConfig2,ADC2_ENABLE)); // Enable ADC 2
(**ReadAnalogClockStatus)(AnalogConfig2); // Wait for AnalogClockEnable function to finish

// Reset both ADC in case the last reset was a debugger reset (which doesn't
// reset the ADCs
Adc1Regs.ADCCTL1.bit.RESET = 1;

// Wait to ensure ADCs are out of reset before device cal is called
__asm(" nop");
__asm(" nop");

// Calibrate the device for temperature
(**Device_Cal)();

EDIS;

//Init the ADC
InitAdc1();


// Configure ADC readings to trigger continuously (ping-pong between ADCINT1 and ADCINT2)
EALLOW;
Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1; // Enable non-overlap mode i.e. conversion and future sampling events don't overlap
Adc1Regs.ADCCTL1.bit.INTPULSEPOS = 0; // ADCINT1 trips after ADCResults latch
Adc1Regs.INTSEL1N2.bit.INT1E = 1; // Enabled ADCINT1
Adc1Regs.INTSEL1N2.bit.INT2E = 1; // Enabled ADCINT2
Adc1Regs.INTSEL1N2.bit.INT1CONT = 1; // Enable ADCINT1 Continuous mode
Adc1Regs.INTSEL1N2.bit.INT2CONT = 1; // Enable ADCINT2 Continuous mode
Adc1Regs.INTSEL1N2.bit.INT1SEL = 3; // setup EOC3 to trigger ADCINT1 to fire
Adc1Regs.INTSEL1N2.bit.INT2SEL = 1; // setup EOC1 to trigger ADCINT2 to fire

Adc1Regs.ADCSOC0CTL.bit.CHSEL = 0; // set SOC0 channel select to ADC1A0 (EOC0)
Adc1Regs.ADCSOC1CTL.bit.CHSEL = 2; // set SOC1 channel select to ADC1A2 (EOC1)
Adc1Regs.ADCSOC2CTL.bit.CHSEL = 3; // set SOC2 channel select to ADC1A3 (EOC2)
Adc1Regs.ADCSOC3CTL.bit.CHSEL = 4; // set SOC3 channel select to ADC1A4 (EOC3)

Adc1Regs.ADCINTSOCSEL1.bit.SOC0 = 2; // ADCINT2 triggers SOC0
Adc1Regs.ADCINTSOCSEL1.bit.SOC1 = 2; // ADCINT2 triggers SOC1
Adc1Regs.ADCINTSOCSEL1.bit.SOC2 = 1; // ADCINT1 triggers SOC2
Adc1Regs.ADCINTSOCSEL1.bit.SOC3 = 1; // ADCINT1 triggers SOC3

Adc1Regs.ADCSOC0CTL.bit.ACQPS = 25; // set SOC0 S/H Window to 26 ADC Clock Cycles, (25 ACQPS plus 1)
Adc1Regs.ADCSOC1CTL.bit.ACQPS = 25; // set SOC1 S/H Window to 26 ADC Clock Cycles, (25 ACQPS plus 1)
Adc1Regs.ADCSOC2CTL.bit.ACQPS = 25; // set SOC2 S/H Window to 26 ADC Clock Cycles, (25 ACQPS plus 1)
Adc1Regs.ADCSOC3CTL.bit.ACQPS = 25; // set SOC3 S/H Window to 26 ADC Clock Cycles, (25 ACQPS plus 1)
EDIS;


DELAY_US(5000);

// EALLOW;
// PieVectTable.ADCINT1 = &ADC_ISR;
// EDIS; // This is needed to disable write to EALLOW protected registers
//
// // Enable ADCINT1 in PIE
// PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
// IER |= M_INT1; // Enable CPU Interrupt 1


//Manually start a conversion
Adc1Regs.ADCSOCFRC1.bit.SOC0 = 1; // trigger a conversion on SOC0
Adc1Regs.ADCSOCFRC1.bit.SOC1 = 1; // trigger a conversion on SOC1
Adc1Regs.ADCSOCFRC1.bit.SOC2 = 1; // trigger a conversion on SOC2
Adc1Regs.ADCSOCFRC1.bit.SOC3 = 1; // trigger a conversion on SOC3

}

  • Hi,

    You need to refer the ADC section of TRM (Technical Reference Manual) of this device. You can view the same here:
    www.ti.com/.../spruhe8

    You can also view other documents here:
    www.ti.com/.../technicaldocuments

    Regards,
    Gautam
  • Chenkun,

    You can also refer to some examples in controlSUITE or C2000Ware like adc_soc.

    -Tommy
  • Hi Tommy, 

    Thanks for getting back. 

    I followed similar steps as C28_adc file in my code but i found when calling InitAdc1(), my code will crash and i couldn't see any error from debug mode

    And I have to comment this API to let the SW run but i think without this API call, the ADC will not be able to run since the ADC value I get is really small. 

    code snippet:

    // Initialize system control
    InitSysCtrl();

    // Initialize GPIO
    InitGpio();

    Flash_Init();

    // InitAdc1(); // initialize ADC1

    ...

  • Chenkun,

    Are you able to set a breakpoint in InitAdc1() and single-step through the function to see which statement causes your program to crash?

    Are you executing out of FLASH or RAM? If you are executing out of flash, are you executing the memcpy procedure for moving ram functions from flash to ram? DELAY_US() tends to misbehave if the memcpy step is skipped.

    I would recommend using a RAM build for initial development because it is faster and has fewer complications like the above.

    -Tommy
  • Hi Tommy,

    1. Can you confirm if i didn't call InitAdc1(), the ADC block should not work so i get the smaller value, like 190 out of 4096?

    2. I tried to add b.p at the entry point of InitAdc1() but i get the error below when I resume from main.
    [C28xx_0] {module#22}: line 1022: E_unpluggedInterrupt: Unplugged interrupt flagged: intr# 19
    xdc.runtime.Error.raise: terminating execution
    Basically, i tried to put breakpoint but i failed to do so if i have InitAdc1() API call in my code.

    3. I executing out FLASH, i think because in my M3 code, i do have this

    /* The Flash API functions MUST be run out of RAM memory. If the Flash API is already
    * in RAM then this step can be skipped.
    *
    * DO NOT RUN THE FLASH API FROM FLASH. */
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    However, I used the API in C28 and do i also need to have this in my C28 code?

    4. As for RAM build, i am not sure how to configure it to RAM build. I don't want to add more complication to my development. If this is easy step to configure, can you please let me know how?

    Thanks again for your help.
  • chenkun chuang said:
    1. Can you confirm if i didn't call InitAdc1(), the ADC block should not work so i get the smaller value, like 190 out of 4096?

    This is not necessarily the case.  If InitAdc1() is skipped, I would treat the state of the ADC as being unknown rather than disabled.

    The expected result values depend entirely on what voltage you are forcing onto the ADC pin.

    chenkun chuang said:
    2. I tried to add b.p at the entry point of InitAdc1() but i get the error below when I resume from main.
    [C28xx_0] {module#22}: line 1022: E_unpluggedInterrupt: Unplugged interrupt flagged: intr# 19
    xdc.runtime.Error.raise: terminating execution
    Basically, i tried to put breakpoint but i failed to do so if i have InitAdc1() API call in my code.

    This might be related to executing out of flash: processors.wiki.ti.com/.../FAQs

    chenkun chuang said:
    3. I executing out FLASH, i think because in my M3 code, i do have this

    /* The Flash API functions MUST be run out of RAM memory. If the Flash API is already
    * in RAM then this step can be skipped.
    *
    * DO NOT RUN THE FLASH API FROM FLASH. */
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    However, I used the API in C28 and do i also need to have this in my C28 code?

    The C28 and M3 are completely independent in code base and program execution so you will need the memcpy for the C28 as well.

    chenkun chuang said:
    4. As for RAM build, i am not sure how to configure it to RAM build. I don't want to add more complication to my development. If this is easy step to configure, can you please let me know how?

    If you are using an example project from controlSUITE, you can change the build target by: Right-click on project or go to Project menu >> Build Configurations >> Set Active >> RAM 

  • Hi Tommy, 

    I have tried some experiments and was glad some of the issue resolved. 

    1. Can you confirm if i didn't call InitAdc1(), the ADC block should not work so i get the smaller value, like 190 out of 4096?

    This is not necessarily the case.  If InitAdc1() is skipped, I would treat the state of the ADC as being unknown rather than disabled.

    The expected result values depend entirely on what voltage you are forcing onto the ADC pin.

    [Chenkun] In my experiment, i will need to call this initAdc1(); otherwise, the ADC value is 4095 without changing. 

    2. I tried to add b.p at the entry point of InitAdc1() but i get the error below when I resume from main. 

    [C28xx_0] {module#22}: line 1022: E_unpluggedInterrupt: Unplugged interrupt flagged: intr# 19
    xdc.runtime.Error.raise: terminating execution
    Basically, i tried to put breakpoint but i failed to do so if i have InitAdc1() API call in my code.

    This might be related to executing out of flash: processors.wiki.ti.com/.../FAQs

    [Chenkun] I found that i can't just resume to the next b.p. Instead, i have to "step into" so i was able to identify where the PC got error.

     


    The solution is to add ram function for this delay API as you mentioned previously. WIth following steps resolve the issue.

    1. copy F28M36x_usDelay.asm in the same folder which has this API called in another file. 

    2. Adding  memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); in my init function in C28. 

    Thanks for your help. 

  • Chenkun,

    I'm glad that you were able to make progress. Your observations sound reasonable to me.

    -Tommy