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.

Simple Interrupt Using the UP button in LM4F232



Hi guys I'm quite new to programming, and I'm trying to configure my LM4F232 microcontroller such that when I press the "UP" button, it'll produce a falling edge and hence stop my LED from blinking. Releasing the button will return the LED to its blinking state. However, my code does not seem to be working. Any help would be greatly appreciated.

from main.c

#include "C:\StellarisWare\inc\hw_memmap.h"
#include "C:\StellarisWare\inc\hw_types.h"
#include "C:\StellarisWare\driverlib\sysctl.h"
#include "driverlib/interrupt.h"
#include "C:\StellarisWare\driverlib\gpio.h"
void PortMIntHandler(void);
int iBlinkLEDFlag;

int main(void){
//Enables all interrupts to processor
IntMasterEnable();
SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
//Enables Port G
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
//Enables Port M
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
//Enables interrupt for Pin 1 of Port M
GPIOPinIntEnable(GPIO_PORTM_BASE, GPIO_PIN_0);
//Sets pin's function
GPIOPinTypeGPIOInput(GPIO_PORTM_BASE,GPIO_PIN_0);
//Sets pin's type
GPIOIntTypeSet(GPIO_PORTM_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE);
GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_2);
while (1){
if (iBlinkLEDFlag == 1){
GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x04);
SysCtlDelay(400000);
GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x00);
SysCtlDelay(400000);
}
}
}
void PortMIntHandler(void)
{
iBlinkLEDFlag = GPIOPinRead(GPIO_PORTM_BASE, GPIO_PIN_1);
}

from startup.c

extern void PortMIntHandler(void);

PortMIntHandler,                      // GPIO Port M

  • Hello Ken,

    Set iBlinkLEDFlag to 1 before you enter into the while(1) loop.  You would probably have to hold the button down in order to see anything because of key bounce. Then when you press the button iBlinkLEDFlag may = 0.  If it does, then it will stop the blinking and it will never start again.

    You will have to put a condition for when iBlinkLEDFlag = 0 so that you delay for a certain period of time and then set iBlinkLEDFlag back to 1.

    Thanks,

  • Hi Ken,

    Since your UP button is a mechanical one, you must take into consideration the debouncing - you already have such routine(s) in drivers/buttons.c file. More, there are some nice macros useful for your purpose, using these is simple like this:

    if(BUTTON_PRESSED(UP_BUTTON, ucState, ucDelta)) { 

    ...

     // SELECT button action } 
    You can get more info about that reading the EK-LM4F232-UG-9453.pdf, paragraph 4.3 and of coarse, files buttons.c and buttons.h
    Petrei
  • Thanks for the quick replies, I'll try these suggestions!

  • Hi guys I've tried your methods but I think I'm missing something as the LED still doesn't stop blinking. Any further help will be greatly appreciated, thanks in advance.

    #include "C:\StellarisWare\inc\hw_memmap.h"
    #include "C:\StellarisWare\inc\hw_types.h"
    #include "C:\StellarisWare\driverlib\sysctl.h"
    #include "driverlib/interrupt.h"
    #include "C:\StellarisWare\driverlib\gpio.h"
    #include "C:\StellarisWare\boards\ek-lm4f232\drivers\buttons.h"
    void PortMIntHandler(void);
    unsigned char ucState, ucDelta;
    int iBlinkLEDFlag = 1;

    int main(void){
    //Enables all interrupts to processor
    IntMasterEnable();
    //Initialises buttons
    ButtonsInit();
    SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    //Enables Port G
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    //Enables Port M
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
    //Enables interrupt for Pin 1 of Port M
    GPIOPinIntEnable(GPIO_PORTM_BASE, GPIO_PIN_0);
    //Sets pin's function
    GPIOPinTypeGPIOInput(GPIO_PORTM_BASE,GPIO_PIN_0);
    //Sets pin's type
    GPIOIntTypeSet(GPIO_PORTM_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE);
    GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_2);
    while (1){
    if (iBlinkLEDFlag == 1){
    GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x04);
    SysCtlDelay(400000);
    GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x00);
    SysCtlDelay(400000);
    }
    }
    }
    void PortMIntHandler(void){
    //Polls the buttons
    ucState = ButtonsPoll(&ucDelta, 0);

    if(BUTTON_PRESSED(UP_BUTTON, ucState, ucDelta)){
    iBlinkLEDFlag = 0;
    }
    else{
    iBlinkLEDFlag = 1;
    }
    }

  • Hi,

    I think you did not carefully read the documentation - and fast copy/paste is not a good idea without understanding how work a provided routine. ButtonsPoll() should be not called from a GPIO interrupt - but from a timer interrupt or simply from your main program (while loop) if the execution time of that loop is around several milliseconds - this is because the switch used has a bouncing time around 1-2 ms, so you need to keep reading until get a stable result. A good example which can be used as a template for your project is the one in StellarisWare/boards/ek-lm4f120xl/qs-rgb/.  

    Petrei

  • Okay thanks! Sorry, I'll read the document more thoroughly!

  • Hi, I'm really sorry but I still can't find out what is the problem with my codes. Are there any booklets that I can read, other than the peripheral library guide and firmware development package? Thank you all again for your help.

    #include "C:\StellarisWare\inc\hw_memmap.h"
    #include "C:\StellarisWare\inc\hw_types.h"
    #include "C:\StellarisWare\driverlib\sysctl.h"
    #include "driverlib/interrupt.h"
    #include "C:\StellarisWare\driverlib\gpio.h"
    #include "C:\StellarisWare\boards\ek-lm4f232\drivers\buttons.h"
    unsigned char ucState, ucDelta;
    int iBlinkLEDFlag = 0;
    int main(void){


    //Enables all interrupts to processor
    IntMasterEnable();

    //Initialises buttons
    ButtonsInit();

    SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    //Enables Port G
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

    //Enables Port M
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);

    //Enables interrupt for Pin 1 of Port M
    GPIOPinIntEnable(GPIO_PORTM_BASE, GPIO_PIN_0);

    //Sets pin's function
    GPIOPinTypeGPIOInput(GPIO_PORTM_BASE,GPIO_PIN_0);

    //Sets pin's type
    GPIOIntTypeSet(GPIO_PORTM_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE);
    GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_2);

    while (1){

    //Polls the buttons repeatedly
    ucState = ButtonsPoll(&ucDelta, 0);

    if (iBlinkLEDFlag == 0){
                    GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x04);
                    SysCtlDelay(400000);
                    GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2,0x00);
                    SysCtlDelay(400000);
                                             }
    if(BUTTON_PRESSED(UP_BUTTON, ucState, ucDelta))
    {

                     //Writes value 0 to LED
                     GPIOPinWrite(GPIO_PORTG_BASE,GPIO_PIN_2, 0x00);
                     SysCtlDelay(1000000);
                     //Reads data from UP Pin
                     iBlinkLEDFlag= GPIOPinRead(GPIO_PORTM_BASE,GPIO_PIN_0);
    }
    }
    }

  • No one wants your sorrow - but you can simplify your (and our) life by adopting "KISS."  You describe this as one of your early attempts at programming - and you then march smartly into the "valley of death" - otherwise known as interrupts.  And there is no need - trying to do too much - too soon - most always results in too little achieved...

    Suggest the following:

    a) comment out (remove) any/all code listings involving interrupts (later - after the basic read and write are verified - we can reinstall)

    b) reconfirm that the Led Port and Switch Port (and both pins) are correct.  If you can beg/borrow/steal a voltmeter - it would be useful to carefully probe the MCU trace (or pin - if you're extremely careful) seeking to learn the voltage at that pin when the switch is inactive and then active.  (active = being pushed)  If the voltage does not change by 3V or so - no amount of code analysis will succeed - all time/effort wasted.

    c) one of your "if tests" checks against a variable flag.  (iBlinkLEDFlag)  Again - this forces multiple things to be done correctly - any break in this chain will spoil your results.  Instead - suggest that you simply, repeatedly - read that pin connected to your switch.  If the switch completes the circuit to ground - you'll need a pull-up R so that the read can function properly.  (you must have about a 3V difference between switch active vs switch inactive.  Your IDE should be able to confirm the "change in state" detected by your looping read of this switch-connected pin.

    d) once you've achieved (c) - then write an output function which illuminates the Led when the switch is active - and darkens it when the switch is inactive.  You'll have to review the board schematic to see whether the GPIO output must be high or low - to illuminate the Led.  (either way will work - depending upon the wiring of the Led.)  If the Led connects either directly or thru an R to ground - the GPIO must output a high to illuminate it - and vice versa.

    KISS works very well for our group - even on very advanced projects.  (it is said that the missile will fly - only when the "stack" of paperwork/specs - is taller than the missile...  We've found this to hold true...)

     

  • START HERE.

    Then come back to this code.  You will realize that you don't poll and set an interrupt on the same pin at the same time.  You will either poll the pin in order to allow for an interrupt in some special timing application, or you use the interrupt to detect a transition of the pin state and then poll it afterwards.  It depends on you application.

    Also note, you generally do not want to use a mechanical switch for an interrupt unless you have some kind of hardware Debouncing.  There are some good Software Debouncing techniques out there, but they can sometimes be resource intensive and are generally used when polling an input.

    You will discover more as you follow the tutorial.

    Good luck,

  • Thanks everyone! I'll follow your suggestions!

  • Ken Lim Feng Guang said:
    I'll follow your suggestions!

    And that may prove a challenge...

    Suggestion 1: Turn Right.

    Suggestion 2: Turn Left.

    Too much, too soon is too hard!  One battle @ a time - leading to small victories - is the best means to build your understanding. 

    Vale of death (interrupts) should be postponed till multiple basics are safe/sound/secure - under your belt...