AutoChip AC7811 之GPIO中断

1 中断流向图

图 1 GPIO外部中断

如上图所示,【1】代表的是外部的GPIO引脚,可以看出,GPIO_PORTx_PINy,中PIN号相同的引脚共用一组中断线(如图中所示的【3】)。【2】代表选择该组的那个引脚作为中断引脚,因此,GPIO_PORTx_PINy 中同个PIN号种只能有一个PORT能够产生中断。例如,PA0和PB0,PCO,PD0等只能有一个能配置成中断,如果程序中配置了PA0,然后又配置PB0那么只有PB0能够产生中断。【4】为中断屏蔽寄存器,如果屏蔽了该中断,也不能使得【5】PR中断挂起寄存器置1,也就不能触发中断函数了。

2 中断的配置

◎ 将相应的GPIO引脚设置成输入;

◎ 将设置中断触发的边沿方式,有上升沿触发,下降沿触发和上下边沿触发三种方式;

◎ 使能NVIC 中断号的中断;

◎ 使能中断屏蔽寄存器;

◎ 编写中断服务函数;

3 中断服务函数的编写

中断服务函数采用的是回调的形式,也就是上层按照底层的接口形式,编写服务函数,然后以函数指针的方式传递到底层,从而实现上层向底层的传递(依赖倒置)。

GPIO_SetEventCallback(GPIO_PD4,GPIO_PIN4_EventCallback);

void GPIO_PIN4_EventCallback(uint32_t gpioNum)//PD4:LIN;lin,PC4:IGN2

{

gLINWakeSignal = 1;//record interrupt Reason

if(GPIO_PD4 == gpioNum)

{

gLINWakeSignal = 1; /*【疑问1】这里是有疑问的,后面讲*/

}

else

{

;

}

GPIO_ClearPendingExtInt(GPIO_PC4);//clear interrupt flag

}

这个函数中,首先将将标志置1(因为这是一个将LIN的引脚转换为普通IO口的程序,所以变量名字可能不太理解,这个跟实际项目有关,请忽略),然后清除中断挂起标志。

这里着重介绍下,这种回调机制,因为这可以很好的实现底层与上层隔离。首先我们可以从数据手册上可以看到虽然外部GPIO中断线有16个,但是,中断入口只有7个,如下图所示。

因此可以设置一个函数7个大小的函数指针数组。

如:

typedef void (*GPIO_EventCallback)(uint32_t gpioNum);

#define GPIO_INT_NUM    7

GPIO_EventCallback g_gpioCallbackArray[GPIO_INT_NUM] = {(GPIO_EventCallback)NULL};

在每个真正的中断入口函数中,来执行这个回调函数(gpioCallbackArray[X])。以EXTI0_IRQHandler为例。

如下,其他中断入口类同。

void EXTI0_IRQHandler(void)

{

    uint32_t tmpGPIONum = GPIO_GetPendingExtIntGPIONum(0);

    if (g_gpioCallbackArray[0])

    {

        g_gpioCallbackArray[0](tmpGPIONum);

    }

    GPIO_ClearPendingExtInt(tmpGPIONum);

}

而gpioCallbackArray[X]中的内容,便是由配置注册而来。如下的注册函数。

int32_t GPIO_SetEventCallback(uint32_t gpioNum, const GPIO_EventCallback callback)

{

    uint8_t callbackIndex = 0;

    uint32_t tmpGPIOGroupInternalNum = gpioNum % GPIO_ONE_GROUP_NUM;

    if (gpioNum > MAX_PIN_NUM)

    {

        return -1;

    }

    /* set gpio callback function pointer */

    if (tmpGPIOGroupInternalNum > 9u)

    {

        callbackIndex = 6;

    }

    else if (tmpGPIOGroupInternalNum > 4u)

    {

        callbackIndex = 5;

    }

    else

    {

        callbackIndex = tmpGPIOGroupInternalNum;

    }

    g_gpioCallbackArray[callbackIndex] = callback;

    return 0;

}

总结下这种程序的调用方式:

4 GPIO唤醒与中断的差别之处

在调试程序的时候发现,在MCU没有睡眠时,如果开启GPIO中断,中断挂起标志位是会置1的,但是如果在MCU睡眠之后,通过配置的中断IO口来唤醒,发现中断标志位不会置1,但是此时还是可以唤醒的。因此如果是唤醒判断的话,需要额外的添加一个条件,才能清除的知道中断进去的原因是什么。

另外本程序因为LIN的引脚与另外一个唤醒引脚共用同个中断入口,因此后面不得将LIN总线的普通IO口唤醒更改了LIN的模块唤醒。其中LIN模块自带模块的唤醒状态机。在MCU没有睡眠时,唤醒LIN会让LIN模块的唤醒标志位置1,但是当MCU睡眠后,LIN总线的唤醒,能够让MCU唤醒但是不会置为LIN模块的唤醒标志的。

5 输出时IO口上下拉电阻配置

常规的理解端口的配置大概分为,浮空输入,上拉输入,下拉输入,推挽输出,开楼输出。但是在输出的时候配置成上下拉回是什么状态呢?可以明确的是,配置成输出,端口的上下拉电阻还是可以配置的(该单片机)。

可以看手册中的描述如下:

所有GPIO 引脚都具有弱内部上拉和下拉电阻,可以激活或不激活,具体取决于GPIOx_PU 和GPIOx_PD 寄存器中的值。因此与输入输出无关,都可以配置上下拉电阻,因此在功耗调试的时候需要留意。不要认为无影响,随便配置上下拉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值