IMX6ULL裸机篇--向GPIO驱动添加中断处理函数

一.   GPIO中断

在前几章节试验中我们只是使用到了 GPIO 最基本的输入输出功能,本章我们需要使用
GPIO 的中断功能。接下来,我们可以把按键设置为中断模式。

二.  IMX6ULL-GPIO中断设置

设置按键 KEY0 的中断:

1.  首先设置 GPIO的中断触发方式。

参考IMX6ULL参考手册中,第28章节GPIO部分,即GPIO_ICR1或 GPIO_ICR2寄存器。

触发方式有如下四种:低电平触发,高电平触发,上升沿触发,下降沿触发。

对于设置按键中断实验,根据原理图可知,我们设置KEY0,也就是UART1_CTS这个IO为中断下降沿触发。

另外还有一个GPIOx_EDGE_SEL 寄存器

根据参考手册说明可知,这个寄存器是设置边沿触发的。就是无论上升沿或下降沿都会触发中断。

2. 使能 GPIO对应的中断。

设置GPIO_IMR寄存器。

3. 处理完中断以后,需要清除中断标志位。

清除中断状态寄存器GPIO_ISR寄存器相应的位。GPIO_ISR寄存器相应位写1清零。

4. GIC中断控制器配置

(1)  使能相应的中断ID。

KEY0即为UART1_CTS口,我们需要确认UART1_CTS对应的中断ID。

通过参考手册查询,我们知道UART1_CTS对应于GPIO1_IO18。

通过查参考手册第三章节,我们知道GPIO1_IO18对应的中断ID为67+32 = 99(要加上前面的32个SGI和PPI中断)。

(2)  使能中断优先级。

(3)  注册GPIO1_IO18的中断处理函数。

三.   向GPIO驱动添加中断处理函数

中断处理接口写到 bsp/目录下的 GPIO 的驱动文件 bsp_gpio.c 和 bsp_gpio.h文件。

1.  bsp_gpio.h文件添加中断枚举类型

bsp_gpio.h 文件添加枚举,代码如下:
/*描述中断触发类型*/
typedef enum  _gpio_intertupt_mode{
    kGPIO_NoIntMode = 0U,     //无中断功能
    kGPIO_IntLowLevel = 1U,   //低电平触发
    kGPIO_IntHignLevel = 2U,  //高电平触发
    kGPIO_IntRisingEdge = 3U, //上升沿触发
    kGPIO_IntFallingEdge = 4U,//下降沿触发
    kGPIO_IntRisingOrFallingEdge = 5U  //上升沿/下降沿都可触发
}gpio_interrupt_mode_t;

typedef struct _gpio_pin_config{
    gpio_pin_direction_t direction;
    uint8_t  output_level;
    gpio_interrupt_mode_t interruptMode; //中断触发方式

}gpio_pin_config_t;

2.  bsp_gpio.c 文件添加中断相关

bsp_gpio.c 文件中添加接口如下:

/* 使能指定GPIO中断 */
void gpio_interrupt_enable(GPIO_Type* base, unsigned int pin)
{
    base->IMR |= (1 << pin);
}

/* 禁止GPIO的中断功能 */
void gpio_interrupt_disable(GPIO_Type* base, unsigned int pin)
{
    base->IMR &= ~(1 << pin);
}

/* 设置GPIO的中断配置功能(即GPIO的中断触发方式) */
void gpio_interrupt_config(GPIO_Type* base, unsigned int pin, gpio_interrupt_mode_t trigger_mode)
{
    volatile uint32_t * icr_register = NULL;
    unsigned int pin_Shift = 0;

    base->EDGE_SEL &= ~(1 << pin);
    pin_Shift = pin;

    if(pin < 16)  //判断IO是低16的IO还是高16
    {
        icr_register = &(base->ICR1);
    }
    else
    {
        icr_register = &(base->ICR2);
        pin_Shift -= 16;
    }

    switch (trigger_mode)
    {
    case kGPIO_IntLowLevel:
        *icr_register &= ~(3 << (pin_Shift*2));
        break;
    case kGPIO_IntHignLevel:
        *icr_register &= ~(3 << (pin_Shift*2));
        *icr_register |= (1 << (pin_Shift*2));
        break;    
    case kGPIO_IntRisingEdge:
        *icr_register &= ~(3 << (pin_Shift*2));
        *icr_register |= (2 << (pin_Shift*2));
        break;
    case kGPIO_IntFallingEdge:
        *icr_register &= ~(1 << (pin_Shift*2));
        *icr_register |= (3 << (pin_Shift*2));
        break;
    case kGPIO_IntRisingOrFallingEdge:
        base->EDGE_SEL |= (1 << pin);
        break;        
    default:
        break;
    }
}

/* 清除中断标志位 (写1清零)*/
void gpio_clearintflags(GPIO_Type* base, unsigned int pin)
{
    base->ISR |= (1 << pin);
}

最后,可以将 gpio_interrupt_config(设置 GPIO的中断配置功能)添加到  gpio初始化接口中,添加如下:

//GPIO的初始化
//设置输入IO/输出IO
void gpio_init(GPIO_Type* base, int pin, gpio_pin_config_t* config)
{
    if(kGPIO_DigitalInput == (config->direction))  //输入IO
    {
        base->GDIR &= ~(1 << pin);        
    }
    else  //输出IO
    {
        base->GDIR |= (1 << pin);
        //设置默认电平
        gpio_pin_write(base, pin, config->output_level);
    }

    gpio_interrupt_config(base, pin, config->interruptMode); //中断配置
}

以上就是GPIO的中断功能寄存器的相关配置。中断的使用,需要编写外部中断驱动代码。下一节介绍编写按键中断代码,结合本节代码一起编译运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值