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.

TM4C123GH6PM: GPIO pin interrupt wont' change type

Part Number: TM4C123GH6PM

This is on the Tiva C LaunchPad.

I'm trying to use 1 pin as a Zero-crossing detection pin that I trigger an interrupt off of.  I want the interrupt type to be high level detection type so that I get an interrupt immediately when the zero-crossing happens.  However, the pin I'm trying to use is only functioning as a falling edge detection.  Here is the configuration code for the pin and interrupt (the full Initialization routine is below):

//Configure pin 1 of Port E as input with a high level detection interrupt.
//This is for zero cross detection
GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1);
IntEnable(INT_GPIOE);
GPIOIntEnable(GPIO_PORTE_BASE,GPIO_INT_PIN_1);
GPIOIntRegister(INT_GPIOE,ZeroCrossing);
GPIOIntTypeSet(INT_GPIOE,GPIO_INT_PIN_1,GPIO_HIGH_LEVEL);
dummie=GPIOIntTypeGet(INT_GPIOE,GPIO_INT_PIN_1);

I added the 'dummie' int to see what the actual value of the interrupt type was and it is always 65,536 in decimal regardless of what type I put in there (_LOW_LEVEL or _RISING_EDGE etc).  I also have a multimeter hooked up to the pin to confirm when it is at 0V and when it goes to 3.3V (sourced from the LaunchPad pin).  The interrupt portion is working correctly but only falling edge.

Any ideas as to what I might be doing wrong here?

int Initialize(void)
{

//Initialize System Clock to 40MHz
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

//enable Peripherals
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
//We must wait a few clock cycles for the peripherals to be enabled
//This while loop will allow for the peripherals to be enabled before continuing
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1))
{
}

//Configure Timer0 as a one-shot timer
TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);
//Enable and configure Interrupt on Timer0 to be when it times out
IntEnable(INT_TIMER0A);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

//initialize GPIO Port E Pin 2,3 as analog pins
GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_2|GPIO_PIN_3);

//Configure pin 1 of Port F as output. This is where the red LED is connected
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);

//Configure pin 1 of Port E as input with a high level detection interrupt.
//This is for zero cross detection
GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1);
IntEnable(INT_GPIOE);
GPIOIntEnable(GPIO_PORTE_BASE,GPIO_INT_PIN_1);
GPIOIntRegister(INT_GPIOE,ZeroCrossing);
GPIOIntTypeSet(INT_GPIOE,GPIO_INT_PIN_1,GPIO_LOW_LEVEL);
dummie=GPIOIntTypeGet(INT_GPIOE,GPIO_INT_PIN_1);


//Configure sequencer for ADC 0 & 1
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

//Configure the ADC step
ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);
ADCSequenceStepConfigure(ADC1_BASE,0,0,ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END);

//Enable ADC sequencer 0 & 1
ADCSequenceEnable(ADC0_BASE,0);
ADCSequenceEnable(ADC1_BASE,0);

//Enable interrupts
IntMasterEnable();

return(0);
}

  • Shane,
    1) Are you sure you refer to zero crossing? GPIO's are logical inputs, they read either YES or NO. The minimum voltage that represents yes is not a perfect threshold, and is something around 0.7 x VDD (check and confirm on datasheet). The maximum voltage that represents NO is also not a perfect value, and is also informed in the datasheet. If you are looking for zero crossing (as in to measure mains AC frequency/phase, for example), you will need additional circuitry and will need to let us know how that modifies your logic levels into the GPIO.
    2) Please paste you code using the </> button of the rich formatting interface, or it gets too confusing for one to try and help.
    Regards
    Bruno
  • My problem is not with the signal getting to the pin so let's ignore external circuitry and assume I get a +3.3 to 5Vdc signal at the pin when there is a zero crossing.  My question is what have I done
    improperly with the pin configuration that it will only give me falling edge detection. I've pasted the code below with the </> but here is the code that deals with this pin and the interrupt specifically:
     
    //Configure pin 1 of Port E as input. This represents a 0 cross detection GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1); //Enable interrupts on Port E pin 1 IntEnable(INT_GPIOE); IntRegister(INT_GPIOE,ZeroCrossing); GPIOIntEnable(GPIO_PORTE_BASE,GPIO_INT_PIN_1); GPIOIntTypeSet(INT_GPIOE,GPIO_INT_PIN_1,GPIO_HIGH_LEVEL);






    //******************************************************************************
    //                          Declare Header Files
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/tm4c123gh6pm.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/debug.h"
    #include "driverlib/adc.h"
    #include "driverlib/fpu.h"
    #include "driverlib/rom.h"
    
    #define SYSCYC_DEG 1852     //The number of system clock cycles/degree of firing angle
                                //Results from:
                                //40MHz (system clock freq)
                                //--------------------------
                                //[60 (line freq)*2(we are only interested in half cycles)*180(number of degrees in 1 half cycle)
                                //= 1851.8 cycles/degree of firing angle in 1/2 of the line frequency sine wave
    
    
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare Functions
    int Initialize(void);
    int Sample(void);
    int Control(void);
    int Manipulation(void);
    void ZeroCrossing(void);
    void Timer0(void);
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare/Initialize Variables
    uint32_t Theta=0;
    uint32_t FireTime=0;
    uint32_t Reference=0;
    uint32_t VelocityFB=0;
    int32_t  Error=0;
    
    
    //******************************************************************************
    
    
    int main(void)
    {
        //Initialize peripherals (I/O, ADC, etc)
        Initialize();
    
        //Run an infinite loop where we sample, calculate control, and output manipulation
        while(1)
        {
            //Sample ADC pins
            Sample();
    
            //Calculate the manipulation based on
            Control();
    
        }
    }
    
    
    //*********************************************************************************
    //***************************   Function Declarations   ***************************
    //*********************************************************************************
    
    
    //**************************************************************************************
    //                                      Initialize() function
    int Initialize(void)
    {
    
        //Initialize System Clock to 40MHz
        SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
        //enable Peripherals
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
        //We must wait a few clock cycles for the peripherals to be enabled
        //This while loop will allow for the peripherals to be enabled before continuing
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1))
        {
        }
    
        //Configure Timer0 as a one-shot timer
        TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);
        //Enable and configure Interrupt on Timer0 to be when it times out
        IntEnable(INT_TIMER0A);
        TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    
        //initialize GPIO Port E Pin 2,3 as analog pins
        GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_2|GPIO_PIN_3);
    
        //Configure pin 1 of Port F as output.  This is where the red LED is connected
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    
        //Configure pin 1 of Port E as input.  This represents a 0 cross detection
        GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1);
    
        //Enable interrupts on Port E pin 1
        IntEnable(INT_GPIOE);
        IntRegister(INT_GPIOE,ZeroCrossing);
        GPIOIntEnable(GPIO_PORTE_BASE,GPIO_INT_PIN_1);
        GPIOIntTypeSet(INT_GPIOE,GPIO_INT_PIN_1,GPIO_HIGH_LEVEL);
    
    
        //Configure sequencer for ADC 0 & 1
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
        ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
    
        //Configure the ADC step
        ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);
        ADCSequenceStepConfigure(ADC1_BASE,0,0,ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END);
    
        //Enable ADC sequencer 0 & 1
        ADCSequenceEnable(ADC0_BASE,0);
        ADCSequenceEnable(ADC1_BASE,0);
    
        //Enable interrupts
        IntMasterEnable();
    
        return(0);
    }
    //*********************************************************************************
    
    //*********************************************************************************
    //                                  Sample() function
    int Sample(void){
    
        //clear the ADC interrupt status flag
        ADCIntClear(ADC0_BASE, 0);
        ADCIntClear(ADC1_BASE, 0);
    
        //trigger the ADC
        ADCProcessorTrigger(ADC0_BASE, 0);
        while(!ADCIntStatus(ADC0_BASE, 0, false))
        {
        }
    
        ADCProcessorTrigger(ADC1_BASE, 0);
        while(!ADCIntStatus(ADC1_BASE, 0, false))
        {
        }
    
        //Get sample and put it into buffer
        ADCSequenceDataGet(ADC0_BASE, 0, &Reference);
        ADCSequenceDataGet(ADC1_BASE, 0, &VelocityFB);
    
        return(0);
    }
    //**********************************************************************
    
    
    //**********************************************************************
    //                              Control() function
    int Control(void)
    {
    
        //Calculate error
        Error=(Reference-VelocityFB);
    
        //If error is greater than 0 then we calculate a Theta
        if(Error>0){
            //Calculate the firing time by getting the % error and multiplying that by 180
            //  to get the number of degrees we need to fire at.  Then we multiply by the
            //  cycles/degree to get the firing time that is shoved into Timer0.
            //  The equation looks strange because we are dealing with integers so the division
            //  will lead to truncation and thus is needs to happen last.
            FireTime= (SYSCYC_DEG*(4095-Error)*180)/4095;
        }
        //If error is less than 0 then we set firing time to 333,361 which is 1 above the maximum value
        //  of the equation above for FireTime
        else
        {   FireTime=333361;
    
        }
    
        return(0);
    }
    //******************************************************************************
    
    
    //*****************************************************************************
    //                                  ZeroCrossing() ISR
    void ZeroCrossing(void)
    {
    
        //clear the interrupt
        GPIOIntClear(GPIO_PORTE_BASE,GPIO_INT_PIN_1);
    
        //Determine whether Timer0 should be loaded/enabled on if we have positive error
        //  (ie if the reference is greater than the feedback)
    
        if (FireTime<333361){
        //Load the latest manipulation
        TimerLoadSet(TIMER0_BASE, TIMER_A, FireTime-1);
        //enable and start timer
        TimerEnable(TIMER0_BASE, TIMER_A);
        }
    }
    //*******************************************************************************
    
    //*****************************************************************************
    //                                  Timer0() ISR
    void Timer0(void){
        //Clear the interrupt
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        //Disable timer to reset it
        TimerDisable(TIMER0_BASE, TIMER_A);
        //Write a 1 to PF1
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x02);
        //Delay clock cycles
        SysCtlDelay(FireTime*100);
        //Write a 0 to PF1
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00);
    
    }
    //*******************************************************************************
    
    
    
    

  • Not sure why Rich Text formatting doesn't recognize when I press return but here's the first part I tried posting in normal format:

    My problem is not with the signal getting to the pin so let's ignore external circuitry and assume I get a +3.3 to 5Vdc signal at the pin when there is a zero crossing. My question is what have I done improperly with the pin configuration that it will only give me falling edge detection. I've pasted the code below with the </> but here is the code that deals with this pin and the interrupt specifically:
  • Use GPIO_BOTH_EDGES on your GPIOIntTypeSet();
  • Believe that your code "misses" the (required) call to, "GPIOPinIntEnable()."   Indeed - there are SO MANY such (GPIO Int) calls!

    This ""GPIOPinIntEnable()" addition should get your, "Rising Edge" to work.

    I'm concerned about your set-up of, "Timer0" as well.

    TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);   // cb1 - I believe that "TIMER_CFG_A_ONE_SHOT" proves better.   (better mates w/ your IntEnable) 

    //Enable and configure Interrupt on Timer0 to be when it times out

       IntEnable(INT_TIMER0A);

    I'd thus replace the above w/ TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_ONE_SHOT);  // cb1 version

    In addition - your "set-up/config" of this one-shot Timer seems lacking several (normal) Timer function calls...    Here's my firm's listing of such Timer calls (known good!)

    ROM_TimerDisable(TIMER1_BASE, TIMER_B);

    ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);

    ROM_TimerLoadSet(TIMER1_BASE, TIMER_B, 25000); // 500uS

    ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);

    ROM_IntEnable(INT_TIMER1B);

  • Wow I didn’t know I was missing so much.  I’ve been following the LaunchPad workshop exercises and my circuit has been working fairly well so I didn’t dig much deeper into the PDL than necessary.

    I’ve changed the configuration statements for the timers and disabled the unused half of each timer.  I’m guessing I can use Timer 0 parts A and B separately instead of using Timer0 part A and Timer 1 part A?

    Thank you for pointing that stuff out.  Is there any resource you would recommend to learn more of the PDL and how it should be used?

    As far as the pin interrupt I’ve noticed that when I touch the wire there is a voltage spike that triggers the interrupt.  So perhaps the MCU is working properly but there’s noise in the room that I’m testing in?  It seems like when I touch the wire and the fake laminate wood desk and have a meter attached I get voltage spikes up to 700mV AC and 400mVdc.  The meter connected seems to change the behavior of the circuit so I think the voltage spikes are greater than that without meter attached.  I’m also plugging the LaunchPad board into my computer which is on the desk, if that makes a difference.

    I added a pull up resistor (1k) and decoupling capacitor (330n) but still no luck getting it to do anything but falling edge.

    Wow I didn’t know I was missing so much.  I’ve been following the LaunchPad workshop exercises and my circuit has been working fairly well so I didn’t dig much deeper into the PDL than necessary.
     
    I’ve changed the configuration statements for the timers and disabled the unused half of each timer.  I’m guessing I can use Timer 0 parts A and B separately instead of using Timer0 part A and Timer 1 part A?
    Thank you for pointing that stuff out.  Is there any resource you would recommend to learn more of the PDL and how it should be used?
    As far as the pin interrupt I’ve noticed that when I touch the wire there is a voltage spike that triggers the interrupt.  So perhaps the MCU is working properly but there’s noise in the room that I’m testing in?  It seems like when I touch the wire and the fake laminate wood desk and have a meter attached I get voltage spikes up to 700mV AC and 400mVdc.  The meter connected seems to change the behavior of the circuit so I think the voltage spikes are greater than that without meter attached.  I’m also plugging the LaunchPad board into my computer which is on the desk, if that makes a difference.
    I added a pull up resistor (1k) and decoupling capacitor (330n) but still no luck getting it to do anything but falling edge.
  • Thank you - and you are welcome.    The "downside" (if any) to so powerful & extensive an API is its depth - and the resulting time/effort required to gain familiarity - later mastery.

    I don't like the idea of you (potentially) introducing ESD into your board - via "finger tests."   Note that while your meter reports "sub 1000mV spikes" - few such meters respond fast enough - to capture & display "real results!"    (scope really required for that)     It IS possible - that in conducting those tests - that specific MCU input was damaged (over-voltaged) - thus is "blind" to further, "rising edges."   (and that limited damage - may allow that same input - to sense "falling edges!"   (making you more crazy)

    Suggest that temporarily you adopt:

    • Change to another conveniently accessed MCU GPIO (one appearing on your board's header) reconfigure (via your new knowledge) - "avoid finger testing" - and test & observe.
    • It must be that your external circuitry "zero-cross detects" and provides an "MCU proper" ~3V3 or ~0V - to that "rising edge" sensitive, GPIO.    Might the "rise time" of your circuit prove "too long" (thus too slow) to be properly recognized by the MCU's (rising) edge detector?   (edge denotes some minimum dV/dT)    Again - scope aids immensely - in this.   Also - if that zero-cross detect circuit is crude - it may generate a damaging transient - which your meter would (never) note.   (note to poster - budget for scope - ASAP)   Your zero-cross detect circuit would be safest if it is powered by "unipolar 3V3" - which reduces the likelihood of voltage transients beyond MCU's acceptance.  (if instead - powered by >5V - and especially if powered via "bi-polar" (± dual supplies) - added output voltage "restrictions" must be employed - to "save" your MCU.
    • You've added a 1K pull-up R - that should "pull" to 3V3 (not higher!)    And - does your zero-cross circuit have the output capability to drive the required current sink capability - to create a valid "low?"   (1K is likely too low in value - 4K7 vicinity - suggested)    It is critical that you repeat your testing - to confirm that you are really "feeding both 3V3 & 0V" - to your MCU's GPIO.
    • Dawns that there's a superior test method - temporarily "break" the "edge detect" connection - between MCU & "zero-cross" assembly - and drive your NEW MCU input from (another) MCU GPIO - set as output.   You then may simply "toggle" that output - at a SLOW RATE - and (even) your slow responding meter can then keep up.   Of course this serves as a valid input for your "Rising Edge Detect" - providing you've followed the earlier guidance in set-up/config of the MCU input tasked for "rising edge."

    Allow plenty of time to read, explore, digest and INTERACT (load, run, single step - MANY code examples) with the PDL.   (Peripheral Driver Library)    The extensiveness of the document is "dual-edged" (deserves a Like) - demands much effort - yet really "pays off."

  • All great suggestions. I got pulled off this project for today but I'll try out your suggestions early next week. I appreciate your answers as well as explaining surrounding details I didn't know about.
  • Shane M said:
    All great suggestions.

    I thought so - yet ALL credit must flow thru to, "KISS" - which so often (prevents - or greatly reduces) our entry into, "dead-end" trails/attempts.

    You have created an "interleave" of (many) bits/pieces - have "joined them all together - and (then) pressed, "Run!"    That is FAR from the rules of "KISS!"   (and usually results in system failure!)

    KISS - in stark contrast - directs:

    • focus solely upon one small portion of the objective
    • implement and then test/observe that portion - earlier rather than later - if complex.     Repeat these 2 steps for all remaining portions.
    • ONLY when all such "portions/sections" of the project have been (successively) test/verified - attempt to join them - yet do this "intelligently" (join only 2 at a time)
    • Test ALL possible (real) "joinings or couplings" of project's "portions/sections"
    • ONLY then - with each/every "portion/section" confirmed - press, "RUN."

    Note that the (usual, for here) "method" - build everything - and ONLY then (start) testing - presents the user with an overwhelming challenge.   Everything is suspect!    And where does one begin to probe/check?      Do not ALL of those (prematurely implemented) "portion/section" interconnects - now stand very much - IN THE WAY?    Can this (method) ever make sense?

    KISS has (long) been proven to, "Speed, Ease, Enhance" most ALL efforts - across multiple fields.    Pity that the (word) is rarely (i.e. never) placed "in play" here - by vendor crue.   (who are far from motley)

  • Alright so I finally got back on this project. I cleaned up the code/comments a little and changed the Zero Crossing interrupt pin to E5 and then C5 with the same results. I also tried to change the interrupt type to any other type of interrupt with no effect. Could it be that I need to set the pins to sinking or sourcing? I'm going to read through the whole PDL for GPIO and see if there's anything I'm missing.

    Lastly, I tried the trick you recommended about configuring another pin as an output but it didn't seem to work very well. It's definately my code that's the problem but after trying different pins for the interrupt I'm pretty sure the pins are fine and I'm just missing something.

    I'll post my updated code below.
  • //******************************************************************************
    //                          Declare Header Files
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/tm4c123gh6pm.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/debug.h"
    #include "driverlib/adc.h"
    #include "driverlib/fpu.h"
    #include "driverlib/rom.h"
    
    #define SYSCYC_DEG 1852     //The number of system clock cycles/degree of firing angle
                                //Results from:
                                //40MHz (system clock freq)
                                //--------------------------
                                //[60 (line freq)*2(we are only interested in half cycles)*180(number of degrees in 1 half cycle)
                                //= 1851.8 cycles/degree of firing angle in 1/2 of the line frequency sine wave
    
    
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare Functions
    int Initialize(void);
    void Sample(void);
    int Control(void);
    int Manipulation(void);
    void ZeroCrossing(void);
    void Timer0(void);
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare/Initialize Variables
    uint32_t Theta=0;
    uint32_t FireTime=0;
    uint32_t Reference=0;
    uint32_t VelocityFB=0;
    int32_t  Error=0;
    uint32_t SampleFreq=0;
    
    
    //******************************************************************************
    
    
    int main(void)
    {
        Initialize();   //Initialization routine
    
        //Run an infinite loop and let interrupts do the hard work
        while(1)
        {
        }
    }
    
    
    //*********************************************************************************
    //***************************   Function Declarations   ***************************
    //*********************************************************************************
    
    
    //**************************************************************************************
    //                                      Initialize() function
    int Initialize(void)
    {
    
        //Initialize system clock to 40MHz
        SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
        //enable Peripherals
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1))   //Wait for last peripheral to be enabled
        {
        }
    
        //Configure Timer0A
        TimerConfigure(TIMER0_BASE,TIMER_CFG_A_ONE_SHOT);   //Configure Timer0 as one shot (for ZCD)
        TimerDisable(TIMER0_BASE, TIMER_B);                 //Disable Timer0B
        IntEnable(INT_TIMER0A);                             //Enable interrupt for Timer0A
        TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);    //Enable interrupt for Timer0A timeout
    
    
        //Timer1A set up
        TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);      //Configure Timer 1A for periodic timing
        SampleFreq=(SysCtlClockGet()/5);                       //Calculate the sample freq based on system clock
        TimerLoadSet(TIMER1_BASE, TIMER_A, SampleFreq -1);      //Load Timer1A with sample freq
        TimerDisable(TIMER1_BASE, TIMER_B);                     //Disable Timer1B
        IntEnable(INT_TIMER1A);                                 //Enable interrupts for Timer1A
        TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);        //Enable interrupts for Timer1A on timeout
        TimerEnable(TIMER1_BASE, TIMER_A);                      //Enable Timer1A
    
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); //Configure PF1 as output (red led)
    
        //Configure PC5
        GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_5);          //Configure PC5 as input
        IntEnable(INT_GPIOC);                                       //Enable interrupts on Port C
        GPIOIntRegister(INT_GPIOC,ZeroCrossing);                    //Register the interrupt for PortE
        GPIOIntEnable(GPIO_PORTC_BASE,GPIO_INT_PIN_5);              //Enable interrupt for PC5
        GPIOIntTypeSet(INT_GPIOC,GPIO_INT_PIN_5,GPIO_RISING_EDGE);  //Configure PC5 interrupt for rising level
    
        //Configure ADC's
        GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_2|GPIO_PIN_3);                      //initialize GPIO Port E Pin 2,3 as analog pins
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);               //Configure sequencer for ADC0
        ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);               //Configure sequencer for ADC1
        ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END); //Configure ADC0 step 0
        ADCSequenceStepConfigure(ADC1_BASE,0,0,ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END); //Configure ADC1 step 1
        ADCSequenceEnable(ADC0_BASE,0);                                             //Enable sequencer for ADC0
        ADCSequenceEnable(ADC1_BASE,0);                                             //Enable sequencer for ADC1
    
        //Enable all interrupts
        IntMasterEnable();
    
        return(0);
    }
    //*********************************************************************************
    
    //*********************************************************************************
    //                                  Sample() function
    void Sample(void){
    
        //clear the ADC interrupt status flag
        ADCIntClear(ADC0_BASE, 0);
        ADCIntClear(ADC1_BASE, 0);
    
        //trigger the ADC
        ADCProcessorTrigger(ADC0_BASE, 0);
        SysCtlDelay(3);
        ADCProcessorTrigger(ADC1_BASE, 0);
        SysCtlDelay(3);
    
        //Get sample and put it into buffer
        ADCSequenceDataGet(ADC0_BASE, 0, &Reference);
        ADCSequenceDataGet(ADC1_BASE, 0, &VelocityFB);
    
        //Calculate error
        Error=(Reference-VelocityFB);
    
        //If error is greater than 0 then we calculate Theta
        if(Error>0){
            //  Calculate the firing time by getting the % error and multiplying that by 180
            //  to get the number of degrees we need to fire at.  Then we multiply by the
            //  cycles/degree to get the firing time that is shoved into Timer0.
            //  The equation looks strange because we are dealing with integers so the division
            //  will lead to truncation and thus is needs to happen last.
            FireTime= (SYSCYC_DEG*(4095-Error)*180)/4095;
        }
        //If error is less than 0 then we set firing time to 333,361 which is 1 above the maximum value
        //  of the equation above for FireTime
        else
        {   FireTime=333361;
    
        }
    
    }
    //**********************************************************************
    
    
    
    //*****************************************************************************
    //                                  ZeroCrossing() ISR
    //  Detects the zero crossing and enables Timer0A if error>0 (ie FireTime<333361)
    void ZeroCrossing(void)
    {
        GPIOIntClear(GPIO_PORTC_BASE,GPIO_INT_PIN_5);   //Clear interrupt for PC5
    
        if (FireTime<333361){
            TimerLoadSet(TIMER0_BASE, TIMER_A, FireTime-1); //Load latest manipulation
            TimerEnable(TIMER0_BASE, TIMER_A);              //Enable Timer0A
        }
    }
    //*******************************************************************************
    
    //*****************************************************************************
    //                                  Timer0() ISR
    //  This ISR will fire the SCR after waiting a certain amount of time which
    //  changes the firing angle.
    
    void Timer0(void){
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); //Clear interrupt for Timer0A
        TimerDisable(TIMER0_BASE, TIMER_A);             //Disable Timer0A to reset it
        SysCtlDelay(FireTime);                          //Wait before firing SCR
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x02);//Fire SCR
        SysCtlDelay(1000000);                           //TESTING: allows us to see the LED for testing
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00);//Turn off pin
    
    }
    //*******************************************************************************
    
    
    
    

  • Shane,
    Follow cb1's suggestion earlier on this post: KIS,S
    Forget the zero crossing detection, simply put a switch there: do you get an interrupt?
    Can you actually see with a scope a rising edge from low TTL level to high TTL level?
    (and by the way, don't clear just the one pin interrupt inside your ISR - if for some accident another pin triggers an interrupt on that port, your code will get stuck).
    KISS: solve one bit at a time, only then try to send the rocket to Mars.
    Bruno
  • I finally found my problem and got it to work. The problem code was:
    GPIOIntTypeSet(INT_GPIOE,GPIO_INT_PIN_1,GPIO_HIGH_LEVEL);

    Instead it should be:
    GPIOIntTypeSet(GPIO_PORTC_BASE,GPIO_INT_PIN_5,GPIO_RISING_EDGE);

    I'm getting rising edge interrupt detection now. I guess reading the PDL carefully pays off haha
  • Good for you - yet - with so dramatic a change - (BOTH Port & Pin) - how did your (past) "Falling Edge" interrupt succeed?"

    Note too - the "TimerConfigure()" correction I earlier suggested aided your success.
  • I'm curious about why it worked before as well. Perhaps the interrupt was semi-configured because the compiler accepted the argument with a matching data type? But I would think the interrupt wouldn't work unless everything was configured properly. Maybe the interrupt defaults to falling edge detection? Or the hex value of one of the arguments from my incorrect code matched what the function was looking for? I'll post back in this thread if I find the reason.

    Regardless of the reason, finding the solution would have taken me a great deal longer without your help . And you opened my eyes to the capabilities of the PDL instead of just coding modified routines listed in the LaunchPad Workshop. You truly deserve the "Guru" title.
  • Thank you, Shane - thank you (very) much. (my best Elvis)

    Not all would agree w/your kind assessment (note - your check IS "in the mail.")     You worked your way thru the "fog of battle" - persisted - and SOLVED your Problem.

    That said - changing both Port & Pin - and "working" - in some form - under (both) regimes - is (hard) to swallow.    (I'm surprised/saddened that I was not bright enough - to catch that "IntTypeSet()" - for you.)

    As you & I (both) realize - the PDL is "worth its weight in Gold" - you seem (very) well placed now to, "Win yet more MCU battles."