前言
最近在使用STM8S003F这款芯片进行开发时,遇到了无法进入中断的问题,调试了很久才解决,现在将调试过程记录下来,如果可以帮助到大家,深感荣幸。
IAR中使用中断
项目中使用到了外部中断和定时器中断,这里以外部中断为例。以往使用STM8,都是使用IAR for STM8来进行开发,设置外部中断需要下面几个步骤:
- 初始化IO口为中断输入模式
GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_IN_PU_IT);
- 设置中断触发方式(00: Falling edge and low level;01: Rising edge only;10: Falling edge only;11: Rising and falling edge)
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_FALL_ONLY);
- 编写中断服务函数,在 stm8s_it.c 文件中,找到对应的中断处理函数 INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6),在中断处理函数中进行业务逻辑的编写
/** * @brief External Interrupt PORTD Interrupt routine. * @param None * @retval None */ INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) { /* In order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction. */ /******************************** * 这里是外部中断的内容 *******************************/ }
- 在main函数中初始化中断,并使能中断,然后就可以正常使用外部中断了。
EXTI_Init(); //... enableInterrupts();
问题
- 因为某些原因,此次使用了STVD和cosmic编译器的方式进行开发。因为是第一次使用STVD,所以在处理中断的时候,就遇到了无法进入中断的问题。
- 一开始,我按照IAR处理中断的方式,在stm8s_it.c对应的中断处理函数(如上面的INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6))中处理中断,发现外部中断一直都触发不了。最后查找了资料才发现,STVD处理中断的方式和IAR有所不同。
- STVD处理STM8S中断的步骤大致如下:
- 第一、二步与上面IAR相同
- 修改中断向量表,这个中断向量表在 stm8_interrupt_vector.c文件中,使用STM8S新建工程的时候会生成这个文件。如图,这里修改了irq3以及irq6,其中EXTI0_PORTA_Interrupte和EXTI3_PORTD_Interrupt可以根据实际命名,这个名字就是后面使用到的中断服务函数的名字。至于这里的irq3和irq6是怎么来的呢,这个要查看芯片对应的数据手册,后面会讲。
- 编写中断处理函数。中断处理函数可以在stm8_interrupt_vector.c文件中编写,也可以在其他工程文件中编写,比如bsp_key.c文件中。
// @bsp_key.c @far @interrupt void EXTI3_PORTD_Interrupt (void) { //外部中断 中断服务函数(所有GPIOD中断都在这里) if(KEY_Down(KEY1_PORT, KEY1_PIN) == 0) //判断是PORTD的哪一个中断 { //中断处理 } }
在这里有一点需要说明,如果中断处理函数不在stm8_interrupt_vector.c文件中定义,需要在stm8_interrupt_vector.c文件中添加相应的函数声明:
@far @interrupt void EXIT0_PORTA_Interrupt (void); @far @interrupt void EXTI3_PORTD_Interrupt (void); @far @interrupt void TIM2_UPD_Interrupt (void);
然后我们就可以编译项目了,编译的时候会发现提示类似这样的报错:
Running Linker
clnk -l"F:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8\Lib" -o Debug\aif-tester.sm8 -mDebug\aif-tester.map Debug\aif-tester.lkf
#error clnk Debug\aif-tester.lkf:86 Debug\stm8_interrupt_vector.o: symbol f_NonHandledInterrupt multiply defined (Debug\stm8s_it.o)
The command: "clnk -l"F:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8\Lib" -o Debug\aif-tester.sm8 -mDebug\aif-tester.map Debug\aif-tester.lkf " has failed, the returned value is: 1
exit code=1.这是因为stm8_interrupt_vector.c文件重复定义了@far @interrupt void NonHandledInterrupt (void),我们将stm8_interrupt_vector.c中NonHandledInterrupt的定义注释掉,再#include "stm8s_it.h"头文件,最后编译通过。下载程序后,发现中断可以正常触发了。
补充
这里补充一点,前面的irq3以及irq6是怎么来的呢?这个需要查找芯片的Datasheet,里面会有一个Interrupt vector mapping章节,这个就是中断向量表,通过查表我们就可以知道中断对应的中断号。
表格中IRQno. 栏就是中断对应的中断号,也就是我们需要在stm8_interrupt_vector.c文件的struct interrupt_vector const _vectab[]中修改的位置。