[学习笔记]

AutoChip AC7811 之GPIO中断

[复制链接]
1520|20
手机看帖
扫描二维码
随时随地手机跟帖
xiaoqi000|  楼主 | 2022-7-31 23:11 | 显示全部楼层 |阅读模式
AC, IO, gp, ip, pi
1 中断流向图 3234762e69bac94da2.png
图 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,也就不能触发中断函数了。


使用特权

评论回复

相关帖子

xiaoqi000|  楼主 | 2022-7-31 23:12 | 显示全部楼层
2 中断的配置
◎ 将相应的GPIO引脚设置成输入;

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

◎ 使能NVIC 中断号的中断;

◎ 使能中断屏蔽寄存器;

◎ 编写中断服务函数;

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:13 | 显示全部楼层
中断服务函数的编写
中断服务函数采用的是回调的形式,也就是上层按照底层的接口形式,编写服务函数,然后以函数指针的方式传递到底层,从而实现上层向底层的传递(依赖倒置)。

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口的程序,所以变量名字可能不太理解,这个跟实际项目有关,请忽略),然后清除中断挂起标志。

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:14 | 显示全部楼层
这里着重介绍下,这种回调机制,因为这可以很好的实现底层与上层隔离。首先我们可以从数据手册上可以看到虽然外部GPIO中断线有16个,但是,中断入口只有7个,如下图所示。
6147662e69c345025e.png

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:14 | 显示全部楼层
因此可以设置一个函数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为例。

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

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:21 | 显示全部楼层
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;

}

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:21 | 显示全部楼层
总结下这种程序的调用方式:
2357962e69e08d5fe6.png

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:22 | 显示全部楼层
GPIO唤醒与中断的差别之处
在调试程序的时候发现,在MCU没有睡眠时,如果开启GPIO中断,中断挂起标志位是会置1的,但是如果在MCU睡眠之后,通过配置的中断IO口来唤醒,发现中断标志位不会置1,但是此时还是可以唤醒的。因此如果是唤醒判断的话,需要额外的添加一个条件,才能清除的知道中断进去的原因是什么。

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:23 | 显示全部楼层
另外本程序因为LIN的引脚与另外一个唤醒引脚共用同个中断入口,因此后面不得将LIN总线的普通IO口唤醒更改了LIN的模块唤醒。其中LIN模块自带模块的唤醒状态机。在MCU没有睡眠时,唤醒LIN会让LIN模块的唤醒标志位置1,但是当MCU睡眠后,LIN总线的唤醒,能够让MCU唤醒但是不会置为LIN模块的唤醒标志的。

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:26 | 显示全部楼层
输出时IO口上下拉电阻配置
常规的理解端口的配置大概分为,浮空输入,上拉输入,下拉输入,推挽输出,开楼输出。但是在输出的时候配置成上下拉回是什么状态呢?可以明确的是,配置成输出,端口的上下拉电阻还是可以配置的(该单片机)。

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:26 | 显示全部楼层
可以看手册中的描述如下:
7845362e69f16bcefe.png

使用特权

评论回复
xiaoqi000|  楼主 | 2022-7-31 23:27 | 显示全部楼层
所有GPIO 引脚都具有弱内部上拉和下拉电阻,可以激活或不激活,具体取决于GPIOx_PU 和GPIOx_PD 寄存器中的值。因此与输入输出无关,都可以配置上下拉电阻,因此在功耗调试的时候需要留意。不要认为无影响,随便配置上下拉。

使用特权

评论回复
tpgf| | 2022-8-2 16:45 | 显示全部楼层
可以判定到具体引脚号吗

使用特权

评论回复
coshi| | 2022-8-2 16:58 | 显示全部楼层
中断还可以再详细划分等级吗

使用特权

评论回复
qcliu| | 2022-8-2 17:10 | 显示全部楼层
上下拉电阻跟其本身模式无关

使用特权

评论回复
drer| | 2022-8-2 17:19 | 显示全部楼层
可以自行更改中断向量号吗

使用特权

评论回复
kxsi| | 2022-8-2 17:30 | 显示全部楼层
仅适用于当前型号单片机

使用特权

评论回复
wiba| | 2022-8-2 17:45 | 显示全部楼层
其实对其他型号单片机来说也极具参考性

使用特权

评论回复
chenjun89| | 2022-8-3 08:26 | 显示全部楼层
最常规的使用方法

使用特权

评论回复
不迁就| | 2022-8-10 13:08 | 显示全部楼层
void EXTI10_15_IRQnCallBack(uint32_t gpioNum)
{
           if ((gpioNum == K6_PIN) && (K6_IN == 0))//中断进入后,判断K6引脚电平,如果为0,说明K6按下
        {
                        //t++;
                LED3 =!LED3 ;
        }
   
}
void EXIT_Init(void)
{
  /* init gpio as output mode */
  GPIO_SetDir(K6_PIN, 1);
        GPIO_SetDir(K7_PIN, 1);       
  //KEY_Init();

       
GPIO_EnableGPIOExtInt(K6_PIN,EXTI_Trigger_Falling);
GPIO_EnableGPIOExtInt(K7_PIN,EXTI_Trigger_Falling);
       
GPIO_SetEventCallback(K6_PIN, EXTI10_15_IRQnCallBack);//设置中断回调函数
GPIO_SetEventCallback(K7_PIN, EXTI10_15_IRQnCallBack);//设置中断回调函数       
                 LED2 = 1;
          LED3 = 1;
}
       




各位大佬,为什么进不了中断呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

628

帖子

0

粉丝