In lesson-2 we first write a customary Blinking LED program. Then we use Interrupt based GPIO input to change the blinking time. Most of the material in this lesson has explained miles better in the video tutorial:
ModusToolbox™ How-To - GPIO with Interrupt Callback – Video (video-cdn.net)
- (A) Blinking LED
- (B) Interrupt based GPIO Input
(A1) Create an Empty App and name it "lsn2BlinkedInterrup"
(A2) Quick Panel -> Device Configurator -> Pins
(A3) In the search bar enter "USER" to filter the pins their macro names contain USER. It shows that CYBSP_USER_BTN = P0_4 and CYBSP_USER_LED = P1_5
(A4) Change main.c to the following:
// CYBSP_USER_BTN = P0_4
// CYBSP_USER_LED = P1_5
#include "cyhal.h"
#include "cybsp.h"
int main(void)
{
cy_rslt_t result;
result = cybsp_init();
if (result != CY_RSLT_SUCCESS) CY_ASSERT(0);
/* Enable global interrupts */
__enable_irq();
for (;;)
{
}
}
(A5) Initialize GPIO Pin 5 of port 1 for LED by calling cyhal_gpio_init function:
cyhal_gpio_init(CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, CYBSP_LED_STATE_OFF);
(A6) The complete main.c to blink LED every one second is as follow:
// CYBSP_USER_BTN = P0_4
// CYBSP_USER_LED = P1_5
#include "cyhal.h"
#include "cybsp.h"
uint32_t myDelay = 1000;
int main(void)
{
cy_rslt_t result;
result = cybsp_init();
if (result != CY_RSLT_SUCCESS) CY_ASSERT(0);
/* Enable global interrupts */
__enable_irq();
cyhal_gpio_init(CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, CYBSP_LED_STATE_OFF);
for (;;)
{
cyhal_gpio_toggle(P1_5);
cyhal_system_delay_ms(myDelay);
}
}
(A7) Quick Panel -> Launches -> lsn2BlinkedInterrrup Program (KitProg3_MiniProg4) Now the red LED should blink every one second.
(B1) It's time for us to do our main job, which is to use pushbutton as interrupt. First, we should do interrupt configuration. Add the bellow codes above "for loop" to configure pushbutton as interrupt source:
cyhal_gpio_init(P0_4, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF);
cyhal_gpio_callback_data_t my_callback_data = {.callback = myCallbackFunction};
cyhal_gpio_register_callback(CYBSP_USER_BTN, &my_callback_data);
cyhal_gpio_enable_event(P0_4, CYHAL_GPIO_IRQ_FALL, CYHAL_ISR_PRIORITY_DEFAULT, true);
(B2) define myCallbackFunction just above the "main function" as following:
void myCallbackFunction(void *callback_arg, cyhal_gpio_event_t event)
{
(myDelay == 250) ? (myDelay = 1000) : (myDelay = 250);
}
(B3) So the final main.c shoud be as following:
// CYBSP_USER_BTN = P0_4
// CYBSP_USER_LED = P1_5
#include "cyhal.h"
#include "cybsp.h"
uint32_t myDelay = 1000;
void myCallbackFunction(void *callback_arg, cyhal_gpio_event_t event)
{
(myDelay == 250) ? (myDelay = 1000) : (myDelay = 250);
}
int main(void)
{
cy_rslt_t result;
result = cybsp_init();
if (result != CY_RSLT_SUCCESS) CY_ASSERT(0);
/* Enable global interrupts */
__enable_irq();
cyhal_gpio_init(P1_5, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, CYBSP_LED_STATE_OFF);
cyhal_gpio_init(P0_4, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF);
cyhal_gpio_callback_data_t my_callback_data = {.callback = myCallbackFunction};
cyhal_gpio_register_callback(CYBSP_USER_BTN, &my_callback_data);
cyhal_gpio_enable_event(P0_4, CYHAL_GPIO_IRQ_FALL, CYHAL_ISR_PRIORITY_DEFAULT, true);
for (;;)
{
cyhal_gpio_toggle(P1_5);
cyhal_system_delay_ms(myDelay);
}
}
(B4) Program the board and red LED will start blinking every one second. Once you press the USER BNT1 the blinking time will be 250ms. Blinking frequency will switch between 250ms and 1s by pressing USER BTN1.
Some explanation:- To use HAL interrupt, six steps are needed:
- 1. To call the __enable_irq function to globally enable interrupts.
/* Enable global interrupts */
__enable_irq();
- 2. To initialize the peripheral as usual. In this case initialize GPIO input using HAL Function:
cyhal_gpio_init(P0_4, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF);
- 3. To define an interrupt callback data structure. You can define it outside of the main function as well.
cyhal_gpio_callback_data_t my_callback_data = {.callback = myCallbackFunction};
- 4. To register the callback function, actually we register callback function to GPIO signal. Below code associate callback data structure with GPIO pin.
cyhal_gpio_register_callback(P0_4, &my_callback_data);
- 5. To enable and specify the desired interrupts events and to set the interrupt priority.
cyhal_gpio_enable_event(P0_4, CYHAL_GPIO_IRQ_FALL, CYHAL_ISR_PRIORITY_DEFAULT, true);
- 6. To define an interrupt callback function, which interrupt event triggers.
void myCallbackFunction(void *callback_arg, cyhal_gpio_event_t event)
{
(myDelay == 250) ? (myDelay = 1000) : (myDelay = 250);
}
An interrupt is handled with an interrupt service routine (ISR). It is important not to call any long blocking functions inside of an ISR since it will prevent other tasks from running until it completes. ISR is generally implemented using a global flag.
Comments
Please log in or sign up to comment.