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.

How do I write an ADC-conversion-done interrupt?

Other Parts Discussed in Thread: EK-TM4C1294XL, EK-TM4C123GXL

My goal here is to change the PWM duty cycle in response to an ADC value. I made a little circuit board with some pots and test points and had it doing just that with the EK-TM4C123GXL. That code just monitored the ADC done flag in the while (1) loop and the update the duty cycles. Now I want to do it properly with an ADC interrupt on the EK-TM4C1294XL. I am having trouble compiling this which leads to a couple of questions. First the code:

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
//#include "driverlib/uart.h"
#include "driverlib/pwm.h"
#include "driverlib/adc.h"
//#include "utils/uartstdio.h"
	uint32_t ADC_data[4];
	volatile uint32_t load_velocity;
    volatile uint32_t CIM_velocity;
    volatile uint32_t frequency_input;
    volatile uint32_t acceleration_input;
    uint32_t dead_band_value;
//	void INT_ADC0SS1_TM4C129(void);

void main(void)
{


	SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |// Set the clocking to run directly from the crystal at 120MHz.
	                                             SYSCTL_OSC_MAIN |
	                                             SYSCTL_USE_PLL |
	                                             SYSCTL_CFG_VCO_480), 120000000);
    // Set the PWM clock to the system clock.
    PWMClockSet(PWM_GEN_0, PWM_SYSCLK_DIV_1);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);	// for the PWM outputs
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);	// for the ADC inputs

    GPIOPinConfigure(GPIO_PK4_M0PWM6);
    GPIOPinConfigure(GPIO_PK5_M0PWM7);

    GPIOPinTypePWM(GPIO_PORTK_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);

    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH3|ADC_CTL_IE|ADC_CTL_END);
    ADCSequenceEnable(ADC0_BASE, 1);

    PWMGenConfigure(PWM0_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN |
                    PWM_GEN_MODE_NO_SYNC);

    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, 64000);

    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0,
                     PWMGenPeriodGet(PWM0_BASE, PWM_GEN_3) / 2);

    PWMDeadBandEnable(PWM0_BASE, PWM_GEN_3, 160, 160);


    // Enable the PWM0 Bit 0 (PD0) and Bit 1 (PD1) output signals.
    PWMOutputState(PWM0_BASE, PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);

    // Enables the counter for a PWM generator block.
    PWMGenEnable(PWM0_BASE, PWM_GEN_3);

    void INT_ADC0SS1_TM4C129(void) {
    	ADCIntClear(ADC0_BASE, 1);
    	        ADCSequenceDataGet(ADC0_BASE, 1, ADC_data);
    	        load_velocity = ADC_data[0];
    	        CIM_velocity = ADC_data[1];
    	        frequency_input = ADC_data[2];
    	        acceleration_input = ADC_data[3];
    	        ADCProcessorTrigger(ADC0_BASE, 1);
    }
    // Loop forever while the PWM signals are generated.
    while(1)
    {

        dead_band_value =
        		acceleration_input * PWMGenPeriodGet(PWM0_BASE, PWM_GEN_0) / 8192 + 80;
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, frequency_input);
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0,
                                 PWMGenPeriodGet(PWM1_BASE, PWM_GEN_0) / 2);
            PWMDeadBandEnable(PWM0_BASE, PWM_GEN_0, dead_band_value, dead_band_value);
        }
    }

And here is relevant snippets from startup_ccs.c

//*****************************************************************************
//
// External declarations for the interrupt handlers used by the application.
//
//*****************************************************************************
extern void INT_ADC0SS1_TM4C129(void);

And the vector table:

    IntDefaultHandler,                      // Quadrature Encoder 0
    IntDefaultHandler,                      // ADC Sequence 0
    INT_ADC0SS1_TM4C129,                      // ADC Sequence 1
    IntDefaultHandler,                      // ADC Sequence 2
    IntDefaultHandler,                      // ADC Sequence 3
    IntDefaultHandler,                      // Watchdog timer

The (CCS6.1 on Win7) compiler complains about line 76

void INT_ADC0SS1_TM4C129(void) {

with the errors: 

"../shaker_tiva.c", line 76: error #41: expected an identifier
"../shaker_tiva.c", line 76: error #66: expected a ";"

I got INT_ADC0SS1_TM4C129 from hw_ints.h. My first question: Is hw_ints.h the file one goes to get values to paste into startup_ccs.c? Since hw_ints.h is included, I should not have to declare it again in my code, which is why I commented it out.

In Amit Ishara's excellent answer in this post, he suggests sticking ADC0IntHandler in startup.ccs.c. I don't see that in hw_ints.h, but does it matter? Anyway, my code faulted on that, also.

  • Hello Otto,

    No. The ADC interrupt handler function is what goes into the code in the main application and the startup_ccs.c The define is the interrupt vector entry number and the map in the interrupt vector table.

    Now, when you put the ADC0IntHandler in the startup_ccs.c and the function in the main code, what does it fault on?

    Regards
    Amit
  • Hi Amit,

    When I substitute ADC0IntHandler for INT_ADC0SS1_TM4C129 in startup_ccs.c (at the top and in the vector table) and in my source code, there is one failure at the ADC0IntHandler function within main(). It is:

    "../shaker_tiva.c", line 76: error #66: expected a ";"

  • Hi Otto,

    This interrupt handler function should be outside and on top of main() .

    void INT_ADC0SS1_TM4C129(void)

    - kel
  • Sure enough, Markel, I put the ISR above main(), just below the function prototype, and it compiles without error. Thanks!

    So that leaves my other question: what is the purpose of hw_ints.h? My code also compiles with I_Love_Chocolate in place of ADC0IntHandler. Would leaving it that way bite me at some point?