Hi all,
I am trying to get the ADC to read a sequence of 4 channels, and the ADC read triggered by the CPU Timer 0.
Firstly I have the timer code working, this basically triggers every 1 sec and it toggles the 4 blue LED's on the board. This was tested separately and also uses Timer 1 as well. I have placed the code into various functions so it helps narrow down my problem, but hit a bit of a brick wall after trying various options on the ADC to get it working.
I had a working example of the ADC code, but this is triggered via PWM, my requirement however requires 2 and probably more PWM's in future so the timer is a preferable option.
My entire code so far is below, the timers still work and the LED's toggle. However observing the expressions assigned to hold the ADC read values in CCS5, has no effect as they do not change. I have all the main ADC setup code in the main function, and the 4 init_??????? functions at the beginning of main have been used for the timer code (they do have a small few additions specific to the ADC as well).
/* * 4CH ADC conversions triggered by cpu_Timer0 * C2000 Launchpad TMS320FF28027 * Ant Scranney * www.coder-tronics.com */ #include "DSP28x_Project.h" // Device Headerfile and Examples Include File #include "f2802x_common/include/adc.h" #include "f2802x_common/include/clk.h" #include "f2802x_common/include/timer.h" #include "f2802x_common/include/flash.h" #include "f2802x_common/include/gpio.h" #include "f2802x_common/include/pie.h" #include "f2802x_common/include/pll.h" #include "f2802x_common/include/wdog.h" // ADC global variables used in this example: uint16_t ADC0, ADC1, ADC2, ADC3; // Timer global variables unsigned int flag0; // Used to toggle LED's unsigned int flag1; // Used to toggle LED's unsigned long timer0_count = 0; // Can be viewed in debug to see count unsigned long timer1_count = 0; // Can be viewed in debug to see count // Function prototypes for timer interrupt handlers interrupt void cpu_timer0_isr(void); interrupt void cpu_timer1_isr(void); // Function prototypes void init_System(void); // Initialise all handles, disable watchdog, clocks, disable the PIE and all interrupts void init_Gpio(void); // Setup Gpio pins void init_Timer(void); // Setup timers void init_PIE(void); // Enable PIE and register ISR handlers ADC_Handle myAdc; CLK_Handle myClk; FLASH_Handle myFlash; GPIO_Handle myGpio; PIE_Handle myPie; TIMER_Handle myTimer0, myTimer1; CPU_Handle myCpu; PLL_Handle myPll; WDOG_Handle myWDog; void main(void) { init_System(); init_PIE(); init_Gpio(); init_Timer(); /********** Initialize ADC **********/ // Enables the ADC band gap circuit ADC_enableBandGap(myAdc); // Enables the ADC reference buffers circuit ADC_enableRefBuffers(myAdc); // Powers up the ADC ADC_powerUp(myAdc); // Enables the ADC ADC_enable(myAdc); // Sets the voltage reference source // ADCCTL1 - ADC_ADCCTL1_ADCREFSEL_BITS ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int); // Clear ADCINT1 flag reinitialize for next SOC ADC_clearIntFlag(myAdc, ADC_IntNumber_1); // Enables the specified ADC interrupt PIE_enableAdcInt(myPie, ADC_IntNumber_1); // Enables the ADC interrupt ADC_enableInt(myAdc, ADC_IntNumber_1); // Sets the interrupt pulse generation mode // ADCCTL1 - ADC_ADCCTL1_INTPULSEPOS_BITS // param[in] adcHandle The ADC object handle // param[in] pulseMode The pulse generation mode ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior); //ADCINT1 trips after AdcResults latch // Enables ADC interrupt // INTSELxNy - ADC_INTSELxNy_INTE_BITS // param[in] adcHandle The ADC object handle // param[in] intNumber The interrupt number ADC_enableInt(myAdc, ADC_IntNumber_1); // Sets the interrupt mode // INTSELxNy - ADC_INTSELxNy_INTCONT_BITS // param[in] adcHandle The ADC object handle // param[in] intNumber The interrupt number // param[in] intMode The interrupt mode ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag); // Disable ADCINT1 Continuous mode // Sets the interrupt source // INTSELxNy - ADC_INTSELxNy_INTSEL_BITS // param[in] adcHandle The ADC object handle // param[in] intNumber The interrupt number // param[in] intSrc The interrupt source ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC3); // Setup EOC3 to trigger ADCINT1 // Sets the start-of-conversion (SOC) channel number // ADCSOCxCTL - ADC_ADCSOCxCTL_CHSEL_BITS // param[in] adcHandle The ADC object handle // param[in] socNumber The SOC number // param[in] chanNumber The channel number ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A0); // Set SOC0 channel select to ADCINA0 ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A1); // Set SOC1 channel select to ADCINA1 ADC_setSocChanNumber (myAdc, ADC_SocNumber_2, ADC_SocChanNumber_A2); // Set SOC2 channel select to ADCINA2 ADC_setSocChanNumber (myAdc, ADC_SocNumber_3, ADC_SocChanNumber_A3); // Set SOC3 channel select to ADCINA3 // Sets the start-of-conversion (SOC) trigger source // ADCSOCxCTL - ADC_ADCSOCxCTL_TRIGSEL_BITS // param[in] adcHandle The ADC object handle // param[in] socNumber The SOC number // param[in] chanNumber The channel number ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_CpuTimer_0); // Set SOC0 start trigger on CpuTimer_0, due to round-robin SOC0 converts first then SOC1 ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_CpuTimer_0); // Set SOC1 start trigger on CpuTimer_0, due to round-robin SOC1 converts first then SOC2 ADC_setSocTrigSrc(myAdc, ADC_SocNumber_2, ADC_SocTrigSrc_CpuTimer_0); // Set SOC2 start trigger on CpuTimer_0, due to round-robin SOC2 converts first then SOC3 ADC_setSocTrigSrc(myAdc, ADC_SocNumber_3, ADC_SocTrigSrc_CpuTimer_0); // Set SOC4 start trigger on CpuTimer_0 // Sets the start-of-conversion (SOC) sample delay // ADCSOCxCTL - ADC_ADCSOCxCTL_ACQPS_BITS // param[in] adcHandle The ADC object handle // param[in] socNumber The SOC number // param[in] sampleDelay The sample delay ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles); // Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_7_cycles); // Set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) ADC_setSocSampleWindow(myAdc, ADC_SocNumber_2, ADC_SocSampleWindow_7_cycles); // Set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) ADC_setSocSampleWindow(myAdc, ADC_SocNumber_3, ADC_SocSampleWindow_7_cycles); // Set SOC3 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) /************************************************************************************************************************/ // Wait for ADC interrupt while(1) { while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){} // Wait until ADCINT1 is tripped ADC0 = AdcResult.ADCRESULT0; ADC1 = AdcResult.ADCRESULT1; ADC2 = AdcResult.ADCRESULT2; ADC3 = AdcResult.ADCRESULT3; AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 // Clear ADCINT1 flag reinitialize for next SOC //ADC_clearIntFlag(myAdc, ADC_IntNumber_1); } } interrupt void cpu_timer0_isr(void) { if (flag0 == 0) { GPIO_setHigh(myGpio, GPIO_Number_0); // Toggles the LEDs GPIO_setLow(myGpio, GPIO_Number_1); } if (flag0 == 1) { GPIO_setLow(myGpio, GPIO_Number_0); // Toggles the LEDs GPIO_setHigh(myGpio, GPIO_Number_1); } flag0++; if (flag0 > 1) {flag0 = 0;} timer0_count++; // Can be viewed in debug to see count // Acknowledge this interrupt to receive more interrupts from group 1 // Clears an interrupt defined by group number PIE_clearInt(myPie, PIE_GroupNumber_1); } interrupt void cpu_timer1_isr(void) { if (flag1 == 0) { GPIO_setHigh(myGpio, GPIO_Number_2); // Toggles the LEDs GPIO_setLow(myGpio, GPIO_Number_3); } if (flag1 == 1) { GPIO_setLow(myGpio, GPIO_Number_2); // Toggles the LEDs GPIO_setHigh(myGpio, GPIO_Number_3); } flag1++; if (flag1 > 1) {flag1 = 0;} timer1_count++; // Can be viewed in debug to see count } void init_System(void) { // Initialize all the handles needed for this application myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj)); myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj)); myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj)); myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj)); myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj)); myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj)); myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj)); myTimer0 = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj)); myTimer1 = TIMER_init((void *)TIMER1_BASE_ADDR, sizeof(TIMER_Obj)); myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj)); // Disables the watchdog (WDOG) timer WDOG_disable(myWDog); // Enables the ADC clock CLK_enableAdcClock(myClk); // The following pointer to a function call calibrates the ADC and internal oscillators (*Device_cal)(); // Sets the internal oscillator 1 as the clock source CLK_setOscSrc(myClk, CLK_OscSrc_Internal); // Setup the PLL for x12 /2 which will yield 60Mhz = 10Mhz * 10 / 2 PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2); /*** Disable the PIE and all interrupts ***/ // Disables the peripheral interrupt expansion (PIE) PIE_disable(myPie); // Disables all of the interrupts PIE_disableAllInts(myPie); // Disables global interrupts CPU_disableGlobalInts(myCpu); // Clears all interrupt flags CPU_clearIntFlags(myCpu); // Enable Global realtime interrupt DBGM CPU_enableDebugInt(myCpu); // If running from flash copy RAM only functions to RAM #ifdef _FLASH memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); #endif } void init_Gpio() { GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Disable); GPIO_setPullUp(myGpio, GPIO_Number_1, GPIO_PullUp_Disable); GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output); GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output); GPIO_setPullUp(myGpio, GPIO_Number_2, GPIO_PullUp_Disable); GPIO_setPullUp(myGpio, GPIO_Number_3, GPIO_PullUp_Disable); GPIO_setDirection(myGpio, GPIO_Number_2, GPIO_Direction_Output); GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output); } void init_Timer() { // // Stops the timer (TIMER) // TIMER_stop(myTimer0); // // Stops the timer (TIMER) // TIMER_stop(myTimer1); // Sets the timer (TIMER) period TIMER_setPeriod(myTimer0, 60000000); // 60MHz therefore every 1 second, cpu_timer0_isr // Sets the timer (TIMER) prescaler TIMER_setPreScaler(myTimer0, 0); // Reloads the timer (TIMER) value TIMER_reload(myTimer0); // Sets the timer (TIMER) emulation mode TIMER_setEmulationMode(myTimer0, TIMER_EmulationMode_RunFree); // Enables the timer (TIMER) interrupt TIMER_enableInt(myTimer0); //Starts the timer (TIMER) TIMER_start(myTimer0); // Sets the timer (TIMER) period TIMER_setPeriod(myTimer1, 60000000); // 60MHz therefore every 1 second, cpu_timer1_isr // Sets the timer (TIMER) prescaler TIMER_setPreScaler(myTimer1, 0); // Reloads the timer (TIMER) value TIMER_reload(myTimer1); // Sets the timer (TIMER) emulation mode TIMER_setEmulationMode(myTimer1, TIMER_EmulationMode_RunFree); // Enables the timer (TIMER) interrupt TIMER_enableInt(myTimer1); // Starts the timer (TIMER) TIMER_start(myTimer1); } void init_PIE(void) { // Initializes the vector table with Debug interrupt handlers PIE_setDebugIntVectorTable(myPie); // Enables the peripheral interrupt expansion (PIE) PIE_enable(myPie); // Registers a handler for a PIE interrupt // cpu_timer0_isr PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_7, (intVec_t)&cpu_timer0_isr); // Registers a handler for a PIE interrupt // cpu_timer1_isr PIE_registerSystemIntHandler(myPie, PIE_SystemInterrupts_TINT1, (intVec_t)&cpu_timer1_isr); /********** Enable ADC iterrupts **********/ // Clear ADCINT1 flag reinitialize for next SOC ADC_clearIntFlag(myAdc, ADC_IntNumber_1); // Enables the specified ADC interrupt PIE_enableAdcInt(myPie, ADC_IntNumber_1); /********** Enable timer iterrupts **********/ // Enables a specified interrupt number CPU_enableInt(myCpu, CPU_IntNumber_1); // CPU int1 which triggers on CPU-Timer 0 // Enables a specified interrupt number CPU_enableInt(myCpu, CPU_IntNumber_13); // CPU int13 which triggers on CPU-Timer 1 // Enables the Cpu Timer 0 interrupt PIE_enableTimer0Int(myPie); // Enables global interrupts CPU_enableGlobalInts(myCpu); }
I am thinking of having an interrupt handler for the ADC, then assigning the ADC results to the variables there, but wanted to get this method working first.
Any pointers or help would be greatly appreciated.
Regards,
Ant