中断通常被用来执行一些紧急任务,在单片机的应用开发中至关重要。
那通常中断应该如何使用以及中断是怎么被一步一步的响应的呢?本文以AT32的USART1接收数据缓冲器满中断为例,进行一个简单的说明
中断应用三要素
1)外设中断使能
通过调用usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE);来完成
2)NVIC中断使能
nvic_irq_enable(USART1_IRQn, 0, 0);
注意要进行NVIC分组配置:nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
3)中断服务函数
void USART1_IRQHandler(void)
{
if(usart_flag_get(USART1, USART_RDBF_FLAG) != RESET)
{
/* clear rdbf flag */
usart1_index = usart_data_receive(USART1);
/* toggle LED*/
at32_led_toggle(LED4);
}
}
中断响应步骤
A.当USART1接收到一笔数据后,其会立即置位接收数据缓冲器满标志(RDBF)
B.由于使能了USART1的接收数据缓冲器满中断,故RDBF标志的置位会同步置位USART1对应的NVIC pending位
C.由于使能了USART1的NVIC中断,故其pending位的置位就会跟随指令跳转,将会实际跳转到中断函数内执行
D.代码实际跳转到中断函数内后,硬件会自动清除USART1对应的NVIC pending位
E.中断函数内通过usart_data_receive命令读USART1数据寄存器来清除RDBF标志
F.退出中断服务函数,等待下一次标志置位响应中断
注意事项:
1)中断函数内的if(usart_flag_get(USART1, USART_RDBF_FLAG) != RESET)用以区分同一中断向量下的不同中断源,通常不可少。比如USART1的中断源除RDBF外,还有包括TDBE、IDLEF等;
2)如果中断函数内不执行清中断标志的动作的话,那在退出中断函数时,因中断标志保持置位,其又会重复从中断响应步骤中的B处开始执行;
3)中断标志的清除需要时间,为避免标志未被真正清除就退出中断服务函数,进而引发中断连续响应的问题,通常清标志命令不在中断函数的末尾执行;
4)如果需要实时的响应中断,代码必须确保未执行__disable_irq();命令(此为内核指令)
5)如果不期望中断函数被实时响应,比如低功耗唤醒状态下期望待时钟恢复后再响应中断时,就可以在进低功耗前调用__disable_irq();禁止中断的实时响应(此时中断会被记录挂起),并在之后期望中断响应的时刻执行__enable_irq();(此时之前挂起的中断会被立即响应)
|