我在 Keil uVision IDE 中使用 Tiva C 系列开发板。我基本上是在尝试使用中断来执行以下操作:
如果未按下开关 1 和开关 2:闪烁红色 LED。 如果按下开关 1,则进入中断程序并闪烁绿色 LED。
松开开关 1 后,重新进入 main 以继续闪烁红色 LED。
中断服务程序在下降沿触发时进入。我知道我需要以某种方式在上升沿触发时返回到 main,但我不确定如何执行此操作。
我已尽我所能发表评论,所以这是我目前所拥有的:
#include <stdint.h>
#include <stdbool.h>
#include "Final Project.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "inc/tm4c123gh6pm.h" // manually added by the programmer
#include "driverlib/interrupt.h" // manually added by the programmer
// Interrupt handler
void GPIOPortF_Handler(void)
{
// acknowledge flag for PF0
GPIO_PORTF_ICR_R |= 0x01;
// Switch 1 is pressed
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4)==0x00)
{
// turn off red LED
GPIO_PORTF_DATA_R &= ~0x02;
// turn off blue LED
GPIO_PORTF_DATA_R &= ~0x04;
// while switch 1 is pressed
while(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4)==0x00)
{
// Turn on green LED
GPIO_PORTF_DATA_R |= 0x08;
// Delay
SysCtlDelay(16000000/3/2);
// Turn off green LED
GPIO_PORTF_DATA_R &= ~0x08;
// Delay
SysCtlDelay(16000000/3/2);
}
}
}
void Interrupt_Init(void)
{
NVIC_EN0_R |= 0x40000000; // enable interrupt 30 in NVIC (GPIOF)
NVIC_PRI7_R &= ~0x00E00000; // configure GPIOF interru
GPIO_PORTF_IM_R |= 0x01; // arm interrupt on PF0
GPIO_PORTF_IS_R &= ~0x01; // PF0 is edge-sensitive
GPIO_PORTF_IBE_R |= 0x01; // PF0 both edges trigger
//GPIO_PORTF_IEV_R &= ~0x01; // PF0 falling edge event
//IntGlobalEnable(); // Globally enable interrupt (without PinMux)
IntMasterEnable(); // Globally enable interrupt (with PinMux)
}
void
PortFunctionInit(void)
{
// Enable Peripheral Clocks
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
// Enable pin PD1 for GPIOInput
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_1);
// Enable pin PD0 for GPIOOutput
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0);
// Enable pin PF2 for GPIOOutput
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
// Enable pin PF3 for GPIOOutput
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
// Enable pin PF0 for GPIOInput
GPIO_PORTF_PUR_R |= 0x01;
// Enable pin PF4 for GPIOInput
GPIO_PORTF_PUR_R |= 0x10;
//First open the lock and select the bits we want to modify in the GPIO commit register.
HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x1;
//Now modify the configuration of the pins that we unlocked.
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0);
// Enable pin PF1 for GPIOOutput
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
// Enable pin PF4 for GPIOInput
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
}
int main(void)
{
// Iinitialize the GPIO ports
PortFunctionInit();
// Configure the GPIOF interrupt
Interrupt_Init();
// Loop forever.
while(1)
{
// Turn on red lED
GPIO_PORTF_DATA_R |= 0x02;
// Delay
SysCtlDelay(16000000/3/2);
// Turn off red lED
GPIO_PORTF_DATA_R &= ~0x02;
// Delay
SysCtlDelay(16000000/3/2);
}
}
最佳答案
在中断处理程序
GPIOPortF_Handler
中使用延迟函数是一个非常糟糕的主意。在等待用户输入的中断处理程序中还有一个 while 循环。
上面的问题是中断有一段时间不会退出。一个好的设计确保中断上下文只运行很短的时间然后退出。这允许注册其他中断。
我建议您在中断处理程序中设置一个 volatile 标志,并在main
中检查该标志。您可以根据此标志采取适当的操作。
下面是一个简单的例子。
void GPIOPortF_Handler(void)
{
GPIO_PORTF_ICR_R |= 0x01;
flags = 1;
}
在主函数中,
int main(void)
{
while(1)
{
if(flags==1)
{
GPIO_PORTF_DATA_R |= 0x02;
SysCtlDelay(16000000/4);
GPIO_PORTF_DATA_R &= ~0x02;
SysCtlDelay(16000000/4);
}
else
{
// Turn on red lED
GPIO_PORTF_DATA_R |= 0x02;
// Delay
SysCtlDelay(16000000/4);
// Turn off red lED
GPIO_PORTF_DATA_R &= ~0x02;
// Delay
SysCtlDelay(16000000/4);
}
/* Check status of switch */
if ( /* enter switch port here */ == 0)
{
GPIO_PORTF_DATA_R &= ~0x02; /* make green LED OFF */
flags = 0;
}
}
}
请注意,此示例确实有一些缺点,并且需要一些时间来检测 key 。基于 SysCtlDelay
的时间,它可能是可以接受的。
关于c - 如何退出中断例程并返回主程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52981174/