关于中断号大于31在Keil中编译出错的处理

注:目前Keil各个版本的C51C251编译器均只支持32个中断号(031),经我公司与Keil公司多方协商和探讨,Keil公司答应会在后续某个版本增加我公司对中断号超过32个的需求。但对于目前现有的Keil版本,只能使用本章节的方法进行临时解决。

 

      1. 使用网上流行的中断号拓展工具

热心网友有提供一个简单的拓展工具,可将中断号拓展到254

 

工具界面如下:

点击“打开”按钮,定位到Keil的安装目录后,点击“确定”即可。

由于Keil的版本在不断更新,而早期版本过多,有无法收集齐,这里列举一下已测试通过的C51.EXE版本和C251.EXE版本

已测试通过的C51.EXE版本:

V6.12.0.1

V8.8.0.1

V9.0.0.1

V9.1.0.1

V9.53.0.0

V9.54.0.0

V9.57.0.0

V9.59.0.0

V9.60.0.0

已测试通过的C251.EXE版本:

V5.57.0.0

V5.60.0.0

 

查看C51.EXE版本的方法:

keil中打开一个基于STC8系列或者STC15系列单片机的项目,在Keil软件菜单项“Help”中打开“About uVision...

 

查看C251.EXE版本的方法:

keil中打开一个基于STC32G系列单片机的项目,在Keil软件菜单项“Help”中打开“About uVision...

      1. 使用保留中断号进行中转

KeilC51、C251编译环境下,中断号只支持0~31,即中断向量必须小于0100H

 

下表是STC目前部分系列的中断列表:

中断号

中断向量

中断类型

0

0003 H

INT0

1

000B H

定时器0

2

0013 H

INT1

3

001B H

定时器1

4

0023 H

串口1

5

002B H

ADC

6

0033 H

LVD

7

003B H

PCA

8

0043 H

串口2

9

004B H

SPI

10

0053 H

INT2

11

005B H

INT3

12

0063 H

定时器2

13

006B H

 

14

0073 H

系统内部中断

15

007B H

系统内部中断

16

0083 H

INT4

17

008B H

串口3

18

0093 H

串口4

19

009B H

定时器3

20

00A3 H

定时器4

21

00AB H

比较器

22

00B3 H

波形发生器0

23

00BB H

波形发生器异常0

24

00C3 H

I2C

25

00CB H

USB

26

00D3 H

PWMA

27

00DB H

PWMB

28

00E3 H

波形发生器1

29

00EB H

波形发生器2

30

00F3 H

波形发生器3

31

00FB H

波形发生器4

32

0103 H

波形发生器5

33

010B H

波形发生器异常2

34

0113 H

波形发生器异常4

35

011B H

触摸按键

36

0123 H

RTC

37

012B H

P0口中断

38

0133 H

P1口中断

39

013B H

P2口中断

40

0143 H

P3口中断

41

014B H

P4口中断

42

0153 H

P5口中断

43

015B H

P6口中断

44

0163 H

P7口中断

45

016B H

P8口中断

46

0173 H

P9口中断

 

不难发现,从波形发生器5中断开始,后面所有的中断服务程序,在keil中均会编译出错,如下图所示:

 

处理这种错误有如下三种方法:(均需要借助于汇编代码,优先推荐使用方法1

 

 

方法1:借用13号中断向量

0~31号中断中,第13号是保留中断号,我们可以借用此中断号

操作步骤如下:

1、将我们报错的中断号改为“13”,如下图:

2、新建一个汇编语言文件,比如“isr.asm”,加入到项目,并在地址“0103H”的地方添加一条“LJMP    006BH”,如下图:

3、编译即可通过。

此时经过KeilC51编译器编译后,在006BH处有一条“LJMP    PWM5_ISR”,在0103H处有一条“LJMP    006BH”,如下图:

当发生PWM5中断时,硬件会自动跳转到0103H地址执行“LJMP    006BH”,然后在006BH处再执行“LJMP    PWM5_ISR”即可跳转到真正的中断服务程序,如下图:

中断服务程序执行完成后,再通过RETI指令返回。整个中断响应过程只是多执行了一条LJMP语句而已。

 

 

方法2:与方法1类似,借用用户程序中未使用的0~31的中断号

比如在用户的代码中,没有使用INT0中断,则可将上面的代码作类似与方法1的修改:

 

执行效果与方法1相同,此方法适用于需要重映射多个中断号大于31的情况。

 

 

方法3:将中断服务程序定义成子程序,然后在汇编代码中的中断入口地址中使用LCALL指令执行服务程序

操作步骤如下:

1、首先将中断服务程序去掉“interrupt”属性,定义成普通子程序

2、然后在汇编文件的0103H地址输入如下图所示的代码

3、编译通过后,即可发现在0103H地址的地方即为中断服务程序

此方法不需要重映射中断入口,不过这种方法有一个问题,在汇编文件中具体需要将哪些寄存器压入堆栈,需要用户查看C程序的反汇编代码来确定。一般包括PSWACCBDPLDPH以及R0~R7。除PSW必须压栈外,其他哪些寄存器在用户子程序中有使用,就必须将哪些寄存器压栈。

首页    常见问题    关于中断号大于31在Keil中编译出错的处理