I have a digital input GPIO line where I need an interrupt whenever its input changes. In STM32CubeMX I set this pin to an EXTI line and set the interrupt to trigger on both rising and falling edges.
When, in response to either a rising or falling edge the function HAL_GPIO_EXTI_Callback() is called, is there a way to know whether it was a rising or falling edge that triggered the interrupt? Or will it be necessary to call HAL_GPIO_ReadPin() to infer this?
The prototype of the callback is:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
You will have to call HAL_GPIO_ReadPin().
When you select Interrupt on both rising and falling edge, STM32CubeMX actually sets the corresponding bits in the Rising trigger selection register (EXTI_RTSRx) and in the Falling trigger selection register (EXTI_FTSRx).
When an interrupt occurs, only one bit is set in the Pending register (EXTI_PRx) for that interrupt line and therefore you don't know if it was a rising or a falling edge.
Yeah, I did it like you said.
But the code can not distinguish between rising and falling edges.
Here is the code:
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
if (GPIO_PIN_SET! = HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_11))
{// THIS CONNECTION IS ADDED. THEN THE SET TUSUNA CAN BE PERFORMED UP AND UP DOWN PRIOR.
if (GPIO_Pin == GPIO_PIN_4) // PA4 rising edge or falling edge cut.
{// Let's say the LCD is inverted. DOWN.
// if ((GPIO_PIN_RESET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_5)) && (GPIO_PIN_SET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)))
// {
// A UCU
if ((GPIO_PIN_RESET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_5)) && (GPIO_PIN_SET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4))) // While rising edge on PA4.
{
//tsHandle.tsButtonVariables.bButton_A_DusenKenar_B_Logic0 = 0;
tsHandle.tsButtonVariables.bButton_A_YukselenKenar_B_Logic0 = 1;
//tsHandle.tsButtonVariables.bButton_B_DusenKenar_A_Logic0 = 0;
//tsHandle.tsButtonVariables.bButton_B_UpdateKenar_A_Logic0 = 0;
}
else if ((GPIO_PIN_RESET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_5)) && (GPIO_PIN_RESET == HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4))) // PA4 when the falling edge is occurring.
{
tsHandle.tsButtonVariables.bButton_A_DusenKenar_B_Logic0 = 1;
//tsHandle.tsButtonVariables.bButton_A_YukselenKenar_B_Logic0 = 0;
//tsHandle.tsButtonVariables.bButton_B_DusenKenar_A_Logic0 = 0;
//tsHandle.tsButtonVariables.bButton_B_UpdateKenar_A_Logic0 = 0;
}
else
{
}
}
Insert
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
in the HAL_GPIO_EXTI_Callback function.
Related
Hi I'm using Watchdog to control LED lights. the microcontroller is connected to laptop with a cable. Input to the microcontroller is 5V. now on the pins there is one pin PB2 which is 5V directly connected to the input. I want to do that if I remove that 5V female-to-male wire from PB2 the LED turn off. when I plug in again with PB2 it the light turn on after that the watchdog called and turn red light off after every 4 sec
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define WDTO_4S 8
void fun_red(){
PORTB.IN=0x04; // PB2 as input
PORTB.DIR=0x09; // PB0 and PB3 output
PORTB.OUTCLR=0x00; // Green
PORTB.OUTSET=0x01;
wdt_enable(WDTO_4S);
do
{
if (PORTB.IN)
{
PORTB.OUTCLR=0x00; // red
}
else{
PORTB.OUTSET=0x08;
}
} while(1);
wdt_reset();
}
int main(void)
{
fun_red();
}
OK, so in the edit it seems that you are wish to use PB2 as an input to control the LED on PB3 - is that correct?
You should not think in terms of voltages, these are digital I/O they have a high state and a low state and a threshold between the two. The inputs on your part will go high at anything above 0.8 volts. However removing the input voltage by disconnecting the wire will have no effect if you have enabled the internal pull-up, and if you have not, it will float and may not trigger a logic 0 (zero).
You either need an external pull-down resistor, or you enable the internal pull-up and invert the logic - i.e. LED on when the input is low, and LED off when input is high. Then instead of connecting PB2 to 5V you connect it to GND. Removing the GND connection will cause the logic state to become 1 because of the internal-pull up. Moreover this is much safer as it avoids any risk of applying excessive voltage to the input and damaging the processor.
Given your apparent lack of knowledge of electronics, I would ask also how you have connected the LED. You should have a current limiting series resistor and have the LED connected the correct way around.
It remains unclear what the purpose of the watchdog is in this. It serves no purpose, but if you enable it you must maintain it to prevent the processor resetting. The purpose of a watchdog is to reset the processor if the software stops running normally by resetting it regularly in the normal software execution path, so if the normal path stops executing the system restarts.
Start by reading this primer App Note: Getting Started with GPIO
First of all, you have misunderstood the function of the GPIO registers. PORTB.IN reads the input states of the PORTB pins that are configured as input. It is read-only so:
PORTB.IN=0x04; // PB2 as input
has no effect and certainly does not configure the pin as an input. That is done by DDR, so:
PORTB.DIR=0x09; // PB0 and PB3 output
sets PB0 and PB3 as outputs, and anything that is not an output is an input - so PB2 is an input by virtue of this line.
Now if you do as I recommend and use the internal pull-up for PB2, you must enable that in the PIN2CTRL register:
PORTB.PIN2CTRL = 0x08 ; // PULLUPEN
Incidentally there are symbols defined for all thse bits so you should be able to write:
PORTB.PIN2CTRL = PORT_PULLUPEN_bm ;
which also makes the comment unnecessary.
The registers OUTSET and OUTCLR, set (logic 1/high) and clear (logic 0/low) respectively. The pins to be set/clear are determined by a bit mask passed in. As such:
PORTB.OUTCLR=0x00; // Green
does nothing, it sets no pins to the low state. To set the red LED (I am assuming PB3) off and the green LED (PB0) on:
PORTB.OUTCLR = PIN3_bm ;
PORTB.OUTSET = PIN0_bm ;
Now, your test of PORTB.IN as if it were Boolean will work in this case because you have only one input. But if you have more than one input, it will not distinguish between then, and it is a bad habit in any case to use an integer expression as if it were Boolean. You should explicitly test the state of PB2:
// If PB2 is low (GND wire connected)
if( (PORTB.IN & PIN2_bm) == 0 )
{
PORTB.OUTSET = PIN3_bm ; // red on
}
else
{
PORTB.OUTCLR = PIN3_bm ; // red off
}
The purpose of a watchdog timer is to reset the processor if the software fails to operate normally. You set the timeout, then you need to reset it regularly in the code to prevent a reset. It is not a general purpose you would use for a delay. For that you would use a hardware timer. Unfortunately it gets a little complex; for your board running at 24MHz, the maximum timer period for the 16 bit TIMER1 is about 2.8 seconds. For more flexibility you would normally implement a timer interrupt to count a number of smaller periods and count the number of times the timer reloads. For example:
volatile unsigned tick = 0 ;
ISR (TIMER1_OVF_vect) // Timer1 ISR
{
tick++ ;
}
void tickStart()
{
TCCR1B = (1<<CS11) // Prescaler 24MHz / 8
TCNT1 = 3000 ; // 1 ms at 24MHz/8
TCCR1A = 0x00;
TIMSK = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
sei(); // Enable global interrupts
}
unsigned getTick()
{
unsigned t = 0 ;
do
{
t = tick ;
} while( tick != t ) ;
return t ;
}
Then for a 4 second delay while also monitoring P2 you might do:
// Wait 4 seconds or until PB2 disconnected
unsigned start = getTick() ;
while( getTick() - start < 4000 &&
(PORTB.IN & PIN2_bm) != 0 )
{
// waiting
}
Finally comment your code. It will allow you to understand what you are trying to do and and when you post a question it will tell others what you are trying to do and it it will make your question simpler by having the explanation in-line with the code so it is clear not only what you want the code to do, but how you think it is doing it.
Putting it all together, the following is more plausible:
void fun_red( void )
{
// Initialise I/O
PORTB.PIN2CTRL = PORT_PULLUPEN_bm ;
PORTB.DIR = PIN0_bm | PIN3_bm ;
PORTB.OUTSET = PIN0_bm ; // Green on
for(;;)
{
// Red off
PORTB.OUTCLR = PIN3_bm ;
// Wait for PB2 to be connected (to GND)
while( (PORTB.IN & PIN2_bm) == 0 )
{
// waiting
}
// Red on
PORTB.OUTSET = PIN3_bm ;
// Wait 4 seconds or until PB2 disconnected
unsigned start = getTick() ;
while( getTick() - start < 4000 &&
(PORTB.IN & PIN2_bm) != 0 )
{
// waiting
}
// Wait for PB2 to be reconnected
while( (PORTB.IN & PIN2_bm) != 0)
{
// waiting
}
}
}
int main( void )
{
tickStart() ;
fun_red() ;
}
Remember in this you connect PB2 to GND (0 volts) not not 5V/Vcc. The requirements in the question are not entirely clear but what this will do (untested - I don't have the hardware) is:
while PB2 is disconnected, the LED will be off,
when PB2 is connected, the LED will be lit for 4 seconds or until PB2 is reconnected.
While it is not its intended purpose and it is not really useful for general purpose, because this requirement is very simple it is possible to us the watchdog timer to implement the desired behaviour as follows:
void fun_red()
{
// Initialise I/O
PORTB.PIN2CTRL = PORT_PULLUPEN_bm ;
PORTB.DIR = PIN0_bm | PIN3_bm ;
// Green on
PORTB.OUTSET = PIN0_bm ;
// Red off
PORTB.OUTCLR = PIN3_bm ;
// Enable watchdog
wdt_enable(WDTO_4S);
for(;;)
{
// Maintain watchdog while waiting for
// PB2 to be connected (to GND)
while( (PORTB.IN & PIN2_bm) == 0 )
{
wdt_reset() ;
}
// Red on
PORTB.OUTSET = PIN3_bm ;
// Maintain watchdog while waiting for
// PB2 to be disconnected (from GND)
while( (PORTB.IN & PIN2_bm) != 0)
{
wdt_reset() ;
}
// Red off
PORTB.OUTCLR = PIN3_bm ;
// Wait for PB2 to be reconnected (to GND)
// without maintaining watchdog. Will reset after 4 seconds
// if not reconnected.
while( (PORTB.IN & PIN2_bm) != 0)
{
// do nothing
}
}
}
Here after PB2 is disconnected, the watchdog is not maintained, so that after 4 seconds a reset will occur and it with restart the program and wait for PB2 to be connected. I think I should class such code as a "dirty-trick", not something to be considered normal or particularly useful.
I want to implement long-press button to turn a device on.
I use external interrupt button to launch the timer on press, and stop and reset it on release of the button. If you hold the button enough (1 sec) it will call a Timer_Update event and turn on LED.
However, when I load my code to the Discovery and press reset, the first press of the user button lights the LED immediately as if the interrupt is generated at the very first launch of the Timer. Then it works properly - changes LED state if you hold the button for >= 1sec.
Project is generated via CubeMX
This is button interrupt handler
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
static uint8_t is_pressed = 0;
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
/* USER CODE BEGIN EXTI0_IRQn 1 */
if (!is_pressed) {
HAL_TIM_Base_Start_IT(&htim7);
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
is_pressed = 1;
}
else {
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
HAL_TIM_Base_Stop_IT(&htim7);
__HAL_TIM_SET_COUNTER(&htim7, 0);
is_pressed = 0;
}
/* USER CODE END EXTI0_IRQn 1 */
}
This is Timer interrupt handler
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_14);
HAL_TIM_Base_Stop_IT(htim);
__HAL_TIM_SET_COUNTER(htim, 0);
}
The trigger event for the Timer in CubeMX is set as "Update Event"
Well it is a bug in the generated code. During timer initialization the call TIM_Base_SetConfig is called. This call has as a side effect that update interrupt bit is set in the SR. This means that when interrupt are enable in the HAL_TIM_Base_Start_IT immediately an interrupt is generated. This is what you are experiencing. See also https://www.youtube.com/watch?v=3yvY7pLMHAg 5:40. There also a HAL compatible fix is explained.
I would recommend the following implementation:
Setup EXTI pin for rising and falling edges
Check pin state in interrupt handler(instead of is_pressed variable)
EXTI handler can be implemented like below:
#define BUTTON_GPIO GPIOA
#define BUTTON_PIN GPIO_PIN_0
#define BUTTON_PRESSED_STATE GPIO_PIN_RESET
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
if (HAL_GPIO_ReadPin(BUTTON_GPIO, BUTTON_PIN) == BUTTON_PRESSED_STATE ) {
HAL_TIM_Base_Start_IT(&htim7);
__HAL_TIM_SET_COUNTER(&htim7, 0);
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET);
HAL_TIM_Base_Stop_IT(&htim7);
}
}
I have old programmable timer/ counter (PD71054 - count rate is set to 3Mhz), and now I would like to program a timer in STM32 (STM32F103RET6) to replace PD71054. I need to measure the duration of the square wave (PA0 pin), I found information about on of timer function - capture, but I do not know how to use it. And unfortunately I did't find good examples how to use it (SPL library). I tried to checking the edges of the signal. If a rising edge is detected, TIM5 will be started, if a falling edge is detected TIM5 will be stopped and the counted value will be saved. But I don’t know if this solution is good and how to set an interrupt for both edges of signal and have two different functions to handle for each of the slopes. signal example
int main(void)
{
TIM5_Config();
NVIC_Config ();
//IWDG_ReloadCounter();
RCC_Config();
RCC_APB1PeriphClockCmd(RCC_APB1PeriphClockCmd, ENABLE);
while(1){
}
}
RCC_Config()
{
BKP_DeInit();
// Reset RCC
RCC_DeInit ();
// HSI ON
RCC_HSICmd(ENABLE);
// Wait for HSI
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
void IWDG_Config (void) {
// watchdoga IWGD
IWDG_WriteAccessCmd (IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_4); // 40kHz/4 = 10kHz
IWDG_SetReload(0x28A); // 65ms
IWDG_Enable(); // Start IWDG oraz LSI
}
void TIM5_IRQHandler(void)
{
TIM_Cmd(TIM5, ENABLE);
}
void TIM5_Config (void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
// Ustawienia podstawy czasu TIM5
TIM_TimeBaseStructure.TIM_Period= 0xFFFF; //65535
TIM_TimeBaseStructure.TIM_Prescaler = 23; // fclk = 72MHz/24 =okolo 3MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
// Zrodlo przerwania kanal 1
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM5,ENABLE);
// TIM5_CH1, Rising edge, no filter
TIM_TIxExternalClockConfig(TIM5, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0x00);
TIM5_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM5_ICInitStructure.TIM_ICFilter=0;
TIM5_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
}
void NVIC_Config (void)
{
NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Sorry I dont have time to go into details about TIMER capture methods.I can offer easer way to do this, at least you can try. Set PA0 pin as EXTI on rising, falling edges. So IRQ will be generated on rising and falling edges. Also setup TIM1 or TIM2 , basically 32bit timer with needed precision, just start timer and its counter. So at rising edge, you can easily reset timer TIM1->CNT = 0 it will be your start time when SIGNAL rise. And then when falling edge appear fetch TIM->CNT . Thats all. Just don't forget to control extra flags (own created variables) wich will help to separate rising and falling edges. Also you could even count those pulses in those events, but its not reliable way.
This is only a snippet, abstract, it should help to understand an idea.
void enable_timer(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 48;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0xFFFFFFFF; //32 bit timer , precision 1us
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1, &timerInitStructure);
TIM_Cmd(TIM1, ENABLE);
}
EXTI handler:
void EXTI0_1_IRQHandler (void)
{
if (EXTI_GetITStatus(EXTI_LINE0) != RESET){
EXTI_ClearITPendingBit(EXTI_LINE0); //clear the irq flag
if(rising_edge)
TIM1->CNT = 0;
if(falling_edge)
fetcher = TIM1->CNT; // here you get your pulse duration time in us
}
}
I'm new to PIC programming and I'm using MPLAb. I have a question regarding interrupt..
so What I want to do, when I push a button then I want to turn on LED 0, and if I release the button then turn on LED 1. I thought the code I wrote making sense but it didn't work.
Here is what happens. Let say the initial state of interrupt pin is low (0), when a button is pushed. Then the LED 0 is on, and when I release the button then LED 1 is on. When I push the button again, I expect LED 0 is on, but LED 1 stays on, and never change the state.
I added last line to see the state of interrupt pin, and once the interrupt is high, it never change it to low.. Can you please advise me what is my misunderstanding?
Thanks in advance!
Here is my code:
void interrupt ISR(void)
{
if(INTCONbits.INTF)
{
nextLED = 1;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
else
{
nextLED = 0;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
nextLED = INTCONbits.INTF + 2;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
// Interrupt Enable settings
INTCONbits.INTE = 1;
INTCONbits.TMR0IE = 1; // Enable TMR0 interrupts
INTCONbits.TMR0IF = 0; // Clear TMR0 interrupt flag
INTCONbits.GIE = 1; // Enable global interrupts
You need to reset the interrupt flag in the ISR function or it will just keep triggering. Please read the datasheet, it should mention if this is necessary. So just add INTCONbits.INTF = 0; to the ISR and it should work as expected.
When setting up any peripheral or function of the mcu, you should go through the datasheet and use the description of the registers and what to set them. You'll also need to be careful with analogue ports, which often default to analogue instead of digital, causing interrupt not to fire as expected or causing unexpected interrupts. It's best to first setup the MCU config bits, set the TRIS and analogue selection registers (ANSELx or ANSELAx etc), then the registers for any peripheral you want to use. Then setup the interrupts, always reset all the interrupt flags you're going to use to start with a known state.
You also set TMR0IE = 1, which will do the same thing, trigger an interrupt. If you don't reset the TMR0 flag it will keep triggering, locking up your mcu or slow it down.
I developed an application to generate the pulses(pwm) using timer of lpc1769. The period of pulse is 10milli seconds and pulse width can be varied as required. The pulse width is generated depending on the reference signal which is a square wave of 10milli seconds(with on period of 7.2ms and off period of 2.8ms). whenever there is rising edge of this signal PWM pulse should start. Now this is working fine. To detect the rising edge i used GPIO interrupt with external interrupt3 the ISR is as :
1) if rising edge on GPIO pin(P2.11)
2) Clear the rising edge status on the pin.
3) then set the timer for few milli seconds
and in timer ISR
1) Clear any pending Timer IRQs
2)Make the GPIO pin high on which generating PWM pulse(P2.6)
3) set the timer for few milli seconds and then clear the pin(P2.6)(same timer is used in both the ISRs)
4) Disabling the timer and re enabling the rising edge interrupt on GPIO pin(P2.11), so again serves the ISR of external interrupt3 on rising edge of reference signal and it continues as above.
Now i am getting the problem in the code in developing the application as,
1) if rising edge disable the interrupt and set timer to 8 milli seconds delay.
2) In timer ISR generate 10 pwm cycles after this re enable the external interrupt. (the same timer is used in both ISRs).
3) so my output should be with respect to rising edge of reference signal 8 milli second delay then 10 pwm cycles(all have time period of 10ms) again 8ms delay with respect to rising edge of reference signal and 10 pwm cycles.
But once after 10 cycles when i re enable the external interrupt irrespective of rising edge of reference signal a delay of 8ms is added.
whenever last 10th cycle is complete I am enabling the interrupt again, so from this point only it adding a 8ms delay. My question is if interrupt is enabled for rising edge of reference signal then it should serve ISR for rising edge only. But this is not happening in this case. I am not understanding this behaviour.
/////////////////////////////////////////////////////////////////////////////////////////////////////
This is my code, this is ISR for external interrupt3
void GPIO_IRQ_HANDLER(void)
{
uit32_t i;
if(((Chip_GPIOINT_GetStatusRising(LPC_GPIOINT, GPIO_INTERRUPT1_PORT) >> GPIO_INTERRUPT1_PIN) & 0x01) != 0) /*Group 1*/
{
count1 = 0;
start_timer1((HALF_WAVE_PERIOD - DELAY) * timerTick);
NVIC_ClearPendingIRQ(GPIO_INTERRUPT_NVIC_NAME);
NVIC_DisableIRQ(GPIO_INTERRUPT_NVIC_NAME);
}
}
Timer1 ISR is
void TIMER1_IRQHandler(void)
{
if (Chip_TIMER_MatchPending(LPC_TIMER1, 1) == 0)
{
return;
}
Chip_TIMER_ClearMatch(LPC_TIMER1, 1);
if(count1 > 10)
{
LPC_GPIO1->PIN = (LPC_GPIO1->PIN & ~(1 << 19));
stop_timer1();
}
else
{
switch(state1)
{
case 1:
state1 = 2;
LPC_GPIO1->PIN = (LPC_GPIO1->PIN | (1 << 19));
set_timer1(2000 * timerTick);
break;
case 2:
state1 = 1;
LPC_GPIO1->PIN = (LPC_GPIO1->PIN & ~(1 << 19));
count1++;
set_timer1((HALF_WAVE_PERIOD - DELAY) * timerTick);
break;
default:
break;
}
}
}
where,
HALF_WAVE_PERIOD = 10000 microseconds
DELAY = 2800 microseconds
GPIO_INTERRUPT1_PORT= PORT2
GPIO_INTERRUPT1_PIN = P2.12
GPIO_INTERRUPT_NVIC_NAME = EINT3_IRQn
GPIO_IRQ_HANDLER = EINT3_IRQHandler
and functions start_timer1 is used to initialize the timer1 and set the timer1 for given number of ticks and interrupt on match.
set_timer1 : set timer1 for given ticks and interrupt.
stop_timer1 : disable the timer1 and enables the external interrupt3.