【国产高性能运动控制MCU 先楫HPM5361】IO中断 寄存器编程测试
[复制链接]
前言
IO中断也是比较多使用的资源,这一篇继续测试IO外部中断的代码编写,为了简单还是直接基于寄存器操作。
IO中断
参考手册《23.2.2 GPIO 中断》
可以通过 GPIO 控制器的 IE 寄存器打开 GPIO 中断,IE 寄存器内的对应位置 1 就可以使能对应 IO 的中 断。
可以通过 GPIO 控制器的 TP 寄存器来指定中断的类型,对应位置 1,表示中断由边沿触发,对应位置 0,表示中断由电平触发。
可以通过 GPIO 控制器的 PL 寄存器来指定中断的极性,对应位置 1,表示中断由下降沿或者低电平触 发,对应位置 0,表示中断由上升沿或高电平触发。
GPIO 控制器支持在检测到上升沿或下降沿生成中断,也支持双沿或单沿触发模式。
GPIO 支持生成异步中断,异步中断允许在系统时钟异常时生成中断。
用户可以通过 GPIO 控制器的 IF 寄存器来查询中断的状态,对应标志位置 1,表示对应 IO 有中断待处理。对 标志位写 1,可以清除这个标志位。
寄存器见23.3章节
根据寄存器描述很容易写出相关代码
详见注释
使能中断并设置回调函数
static void(*int_cb)(void*) = 0;
static void port_set_int(uint8_t enable, void(*cb)(void*))
{
int_cb = cb;
if(enable != 0)
{
HPM_GPIO0->PL[GPIO_DI_GPIOA].SET = (1u << 26); /* 低电平或者下降沿中断 */
HPM_GPIO0->TP[GPIO_DI_GPIOA].SET = (1u << 26); /* 边沿中断 */
HPM_GPIO0->IF[GPIO_DI_GPIOA].VALUE = (1u << 26); /* 写1清除标志 */
HPM_GPIO0->IE[GPIO_DI_GPIOA].SET = (1u << 26); /* 写1使能中断 */
}
else
{
HPM_GPIO0->IE[GPIO_DI_GPIOA].CLEAR = (1u << 26); /* 写1不使能中断 */
}
}
中断回调中清除标志,并调用用户设置的回调函数
static void port_int_cb(void)
{
HPM_GPIO0->IF[GPIO_DI_GPIOA].VALUE = (1u << 26); /* 写1清除标志 */
if(int_cb)
{
int_cb(&uart_rx_dev);
}
}
初始化引脚配置中断
static void port_rx_init(void)
{
HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_GPIO_A_26;
HPM_GPIO0->OE[GPIO_DI_GPIOA].CLEAR = 1u << 26;
install_isr(IRQn_GPIO0_A,(uint32_t)port_int_cb);
intc_m_enable_irq(IRQn_GPIO0_A);
}
中断
中断相关操作接口位于hpm_interrupt.h
其中install_isr用于注册中断回调函数,即对应的数组__vector_table
intc_m_enable_irq用于使能中断,其他接口参考h文件。
其中中断号在hpm_soc.h中定义,比如定时器0即IRQn_GPIO0_A。
使能定时器中断两句搞定
install_isr(IRQn_GPIO0_A,(uint32_t)port_int_cb);
intc_m_enable_irq(IRQn_GPIO0_A);
中断处理过程
trap_entry->
case IRQ_M_EXT:
调用之前注册的回调函数
((isr_func_t) __vector_table[irq_index])();
测试
调试模式,拉低PA26,在中断回调中打断点即可看到是否产生了对应的中断。
或者中断回调中翻转PA27用示波器查看波形。
总结
可以看到IO中断操作比较简单,直接寄存器操作也很快捷。
|