TM4C的每个IO口都可以分别配置外部中断,每组IO口对应一个中断服务函数,例如PA0-PA7对应同一个中断服务函数,每个IO口可以配置为边沿触发或状态触发,TM4C的每个中断都可以配置优先级,它的优先级共有8个为0-7。
/* 声明中断服务函数,TM4C的中断服务函数名可以自己定义的 */
void vGPIO_PortFIntHandler(void);
void vGPIO_Config(void)
{
/* 使能GPIOF */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
/* PF1设为输出模式,输出低电平 */
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
/* PF4方向为输入 */
GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_DIR_MODE_IN);
/* 配置为上拉模式 */
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
/* 注册GPIOF的中断服务函数 */
GPIOIntRegister(GPIO_PORTF_BASE, vGPIO_PortFIntHandler);
/* 设置PF4为下降沿触发 */
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
/* 使能PF4中断 */
GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
/* 使能GPIOF中断 */
IntEnable(INT_GPIOF);
/* 设置中断优先级,TM4C123G的中断优先级有8个 */
IntPrioritySet(INT_GPIOF, 0);
/* 清除PF4中断标志位 */
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
}
/* GPIOF中断服务函数 */
void vGPIO_PortFIntHandler(void)
{
/* 根据当前状态,反转电平 */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) == 0) ? GPIO_PIN_1 : 0);
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
}
这里面有两个函数,一个是IO口的配置函数,一个是中断服务函数。IO口配置函数里有一部分上一个教程讲了这里就不说了,只说跟外部中断有关的部分。
先看第一个函数GPIOIntRegister(GPIO_PORTF_BASE, vGPIO_PortFIntHandler);
这个函数是用来注册中断服务函数的,TM4C的中断跟别的一些单片机比,它的中断服务函数名不是固定的,可以自己定义,这里定义为void vGPIO_PortFIntHandler(void)
,通过这个函数来注册。
接下来就是外部中断的模式配置GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
这里把PF4配置为下降沿触发的中断。它还有多个参数可选,可以配置为上升沿,下降沿,高电平,低电平触发等,可以去看手册进一步了解。
/* 使能PF4中断 */
GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
/* 使能GPIOF中断 */
IntEnable(INT_GPIOF);
这两个函数是用于中断使能的,要使能这个IO口的中断,也要使能这一组的中断。还有一个函数也要写
/* 使能总中断 */
IntMasterEnable();
这个函数用来使能总中断,这里没写在初始化函数里而是写在来所有初始化的后面。这三个使能一个都不能少,否则中断就不能触发。
/* 设置中断优先级,TM4C123G的中断优先级有8个 */
IntPrioritySet(INT_GPIOF, 0);
这个函数用来配置中断的优先级,TM4C123G的中断优先级有8个,0-7。
/* 清除PF4中断标志位 */
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
然后就是清除中断标志位,因为不清除的话无法再次触发中断,这里清除一下防止意外。
/* GPIOF中断服务函数 */
void vGPIO_PortFIntHandler(void)
{
/* 根据当前状态,反转电平 */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) == 0) ? GPIO_PIN_1 : 0);
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
}
中断服务函数就是执行了一个翻转IO口的操作跟上一节教程比这里用了一个简便的方法,因为IO口的输入输出寄存器是一个,这里直接读取这个IO口的状态然后根据状态写入数据。
中断服务函数里一定要清除中断标志位,否则无法触发下一次中断。