版权声明 · 版权所有
本文 © AUTHOR_NAME year。保留所有权利。
许可:LICENSE_NAME
本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
作者说明 · 学习记录
本站作为作者的学习记录站,不保证文章内容严谨或完全正确。
作者:GoDm@
用途:本文为作者的学习记录与实践笔记,用于记录学习过程、思考与示例代码(如有)。
欢迎朋友指正文章中的错误,联系邮箱:god_mao@foxmail.com
版权信息
:::warning
本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
:::
C语言下中断模块
核心思路:
每个中断对象包含:1个中断处理函数和需要传入的参数——一个函数指针+一个未定义类型指针。所以将中断对象打包成一个结构体:
1 2 3 4 5 6 7 8
| typedef void (*sys_irq_handler_t)(unsigned int id, void *para);
typedef struct _sys_irq_handle{ sys_irq_handler_t irqHandler; void* usrPara; }sys_irq_handle_t;
|
指定一个默认中断处理函数:
1 2 3 4
| static void default_irqHandler(unsigned int id, void *para){ while(1); }
|
将所有中断对象归入一个表中,按中断id索引:
1 2
| #define NUM_OF_IT_VECTORS 160 static sys_irq_handle_t irqTable[NUM_OF_IT_VECTORS];
|
后续可能涉及到中断嵌套,因此定义一个中断嵌套计数器:
1
| static unsigned int irqNesting;
|
初始化中断对象表:
1 2 3 4 5 6 7 8 9
| static void sys_iqrTable_init(void){ unsigned char i = 0; irqNesting = 0; for(i = 0; i< NUM_OF_IT_VECTORS; i++){ irqTable[i].irqHandler = default_irqHandler; irqTable[i].usrPara = NULL; } }
|
在上一节中,我们实现了当进入中断时跳入一个名为system_irqhandler
的函数处理中断。因此我们需要定义该函数:
1 2 3 4 5 6 7 8 9 10 11 12
|
void system_irqhandler(unsigned int gicciar){ uint32_t id = gicciar & 0x3ff; if(id == 1023 || id >= NUM_OF_IT_VECTORS) return; irqNesting++; irqTable[id].irqHandler(id, irqTable[id].usrPara); irqNesting--; }
|
我们不可能只用默认中断处理函数,肯定要自己自定义,自定义完处理函数后,将该函数注册给中断对象,因此我们需要一个用于注册的函数:
1 2 3 4 5 6 7 8
|
void register_irqHandler(IRQn_Type irq_id, sys_irq_handler_t handler, void *para){ irqTable[irq_id].irqHandler = handler; irqTable[irq_id].usrPara = para; }
|
配置gpio外部中断
通过原理图可知,应配置为上升沿触发。
配置GPIO_ICR寄存器
寄存器用于指定触发方式——上升沿触发。
我的开发板应指定GOIO5_ICR1_icr1 为 10。
配置GPIO_IMR寄存器
该寄存器用于使能中断。
我的开发板应指定GPIO5_IMR_imr1 为 1——UNMASKED
中断后清除中断标志位
参考手册中指出,处理完中断后,需清除GPIO_ISR寄存器的相应位。
需要注意的是通过对该位写1清除。
GIC 配置
just like NVIC… you must know cubemx right?
使能相应的中断ID
GPIO5_1对应的中断id为74

但是注意这段话:

告诉我们前面还有32个中断接到了CPU的接口 所以中断ID为 74+32 = 106。
配置中断优先级
注册中断处理函数