打印

求教PIC18F中断响应时间过长的问题

[复制链接]
6213|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
左撇子|  楼主 | 2008-5-15 12:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,我是PIC初学者,在调试程序时遇到中断时间过长的问题,向大家请教:

单片机为PIC18F2431,晶振20MHz,系统指令周期0.2us。使用官方的C18编译器和Mplab V7.31。
程序定义PWM 62.5us高级中断,Timer5 1ms低级中断,ADC低级中断
在调试时,发现程序入中断和出中断的时候,都花费了大量时间——30us以上!
在软件模拟和硬件调试时,都出同这样的问题。
查看编译后生成的汇编代码,发现在入中断和出中断的时候,有一大段代码,花费了大量时间。不知是什么原因,特向大家请教,谢谢!

1楼贴中断程序,C代码(我自己编写)
2楼贴编译后生成的入中断程序(系统生成)
3楼贴编译后生成的出中断程序(系统生成)
来自 2楼
martin| | 2008-5-16 11:34 | 只看该作者

C18 V3.00中断现场保护问题

还是请仔细看C18的使用指南,有中文版的。看其中的“编译器管理的资源”和中断现场保护相关的内容。
C18在V3.00版本前后做了一个很重要的改变,就是在中断现场保护上。
V3.00之前,编译器对很多资源不进行管理,如PROD,.tmpdata段,.mathdata段等,由使用者根据自己的程序需要用save = 子句来添加中断的现场保护。但是,很多的用户并不清楚中断时那些东西是需要保护的,于是很多用户因为没有保护必要的现场而出现程序的异常。
V3.00之后的版本,走向另一个极端。编译器不管你需不需要,它按最安全的考虑把所有的现场都保护起来,于是就出了楼主的困惑。但是编译器提供了另一个选项,就是nosave = 子句。用户可以根据自己对程序的判断来选择那些是不需要的现场保护。
顺便说一下,楼主的程序,中断里有函数调用,是否必须的呢?如果是必须的,又如果你的函数有中间计算,有返回值,那这个函数就有可能用到PROD,.tmpdata甚至.mathdata,如果真用到了那编译器的保护措施是必要的。何不考虑在中断里设个标志然后到主程序里查询标志后再调用函数呢?还有,编译器可以设定让中断里调用的函数和中断服务函数共用一个.tmpdata段,这样你就可以放心地用nosave.
总而言之,编译器没有犯错误,它只是很保守,它不可能像你想象的那样智能,它需要你告诉它指导它怎么来编译。  

使用特权

评论回复
板凳
左撇子|  楼主 | 2008-5-15 12:11 | 只看该作者

中断程序C代码

这是我的中断C程序:

//------------------高级中断程序-------------------
#pragma code Vector_High=0x08
void Vector_High(void)
{
  _asm goto Handler_High  _endasm
}
#pragma code

#pragma interrupt Handler_High
void Handler_High()
{

//PWM中断
  if (PWM_IF==1)
  {
    PWM_IF=0;
    Interrupt_PWM();
  }

}
//------------------高级中断程序-------------------


//------------------低级中断程序-------------------
#pragma code Vector_Low=0x18
void Vector_Low(void)
{
  _asm goto Handler_Low _endasm
}
#pragma code

#pragma interruptlow Handler_Low
void Handler_Low()
{

//Timer5中断
  if (Timer5_IF==1)
  {
    Timer5_IF=0;
    Interrupt_Timer5();
  }
 
//ADC中断
  if (ADC_IF==1)        
  {
    ADC_IF=0;
    Interrupt_ADC();
  }

}
//------------------低级中断程序-------------------

使用特权

评论回复
地板
左撇子|  楼主 | 2008-5-15 12:12 | 只看该作者

入中断程序,系统生成的,花费了大量CPU时间

369:               #pragma interrupt Handler_High
370:               void Handler_High()
  0038    CFDA     MOVFF 0xfda, 0xfe4
  003A    FFE4     NOP
  003C    CFE2     MOVFF 0xfe2, 0xfda
  003E    FFDA     NOP
  0040    CFE9     MOVFF 0xfe9, 0xfe4
  0042    FFE4     NOP
  0044    CFEA     MOVFF 0xfea, 0xfe4
  0046    FFE4     NOP
  0048    CFF6     MOVFF 0xff6, 0xfe4
  004A    FFE4     NOP
  004C    CFF7     MOVFF 0xff7, 0xfe4
  004E    FFE4     NOP
  0050    CFF5     MOVFF 0xff5, 0xfe4
  0052    FFE4     NOP
  0054    CFF3     MOVFF 0xff3, 0xfe4
  0056    FFE4     NOP
  0058    CFF4     MOVFF 0xff4, 0xfe4
  005A    FFE4     NOP
  005C    CFFA     MOVFF 0xffa, 0xfe4
  005E    FFE4     NOP
  0060    EE00     LFSR 0, 0x18
  0062    F018     NOP
  0064    0E14     MOVLW 0x14
  0066    04E8     DECF 0xfe8, W, ACCESS
  0068    E303     BNC 0x70
  006A    CFEE     MOVFF 0xfee, 0xfe4
  006C    FFE4     NOP
  006E    D7FB     BRA 0x66
  0070    EE00     LFSR 0, 0
  0072    F000     NOP
  0074    0E18     MOVLW 0x18
  0076    04E8     DECF 0xfe8, W, ACCESS
  0078    E303     BNC 0x80
  007A    CFEE     MOVFF 0xfee, 0xfe4
  007C    FFE4     NOP
  007E    D7FB     BRA 0x76
  0080    52E6     MOVF 0xfe6, F, ACCESS

使用特权

评论回复
5
左撇子|  楼主 | 2008-5-15 12:13 | 只看该作者

出中断程序,系统生成的,花费了大量CPU时间

389:               }
  00A0    52E5     MOVF 0xfe5, F, ACCESS
  00A2    EE00     LFSR 0, 0x17
  00A4    F017     NOP
  00A6    0E18     MOVLW 0x18
  00A8    04E8     DECF 0xfe8, W, ACCESS
  00AA    E303     BNC 0xb2
  00AC    CFE5     MOVFF 0xfe5, 0xfed
  00AE    FFED     NOP
  00B0    D7FB     BRA 0xa8
  00B2    EE00     LFSR 0, 0x2b
  00B4    F02B     NOP
  00B6    0E14     MOVLW 0x14
  00B8    04E8     DECF 0xfe8, W, ACCESS
  00BA    E303     BNC 0xc2
  00BC    CFE5     MOVFF 0xfe5, 0xfed
  00BE    FFED     NOP
  00C0    D7FB     BRA 0xb8
  00C2    CFE5     MOVFF 0xfe5, 0xffa
  00C4    FFFA     NOP
  00C6    CFE5     MOVFF 0xfe5, 0xff4
  00C8    FFF4     NOP
  00CA    CFE5     MOVFF 0xfe5, 0xff3
  00CC    FFF3     NOP
  00CE    CFE5     MOVFF 0xfe5, 0xff5
  00D0    FFF5     NOP
  00D2    CFE5     MOVFF 0xfe5, 0xff7
  00D4    FFF7     NOP
  00D6    CFE5     MOVFF 0xfe5, 0xff6
  00D8    FFF6     NOP
  00DA    CFE5     MOVFF 0xfe5, 0xfea
  00DC    FFEA     NOP
  00DE    CFE5     MOVFF 0xfe5, 0xfe9
  00E0    FFE9     NOP
  00E2    CFE5     MOVFF 0xfe5, 0xfda
  00E4    FFDA     NOP
  00E6    0011     RETFIE 0x1

使用特权

评论回复
6
左撇子|  楼主 | 2008-5-15 12:19 | 只看该作者

PIC18F 中断问题

仅仅是入中断和出中断,就花费了大量的CPU开销,让我的62.5us的PWM中断没法进行。一跳入中断,就花费30us,当执行到“ if (PWM_IF==1)”这句时,已经差不多到60us时间了,再出中断,一来一回,就是100us以上。这还不考虑执行“Interrupt_Timer5();”的花费呢。

请问我的问题出在哪?谢谢

使用特权

评论回复
7
machunshui| | 2008-5-15 15:26 | 只看该作者

楼主肯定是数错了

楼主肯定是数错了.
请看:

58:                #pragma code high_vector=0x08
59:                void interrupt_at_high_vector(void)
60:                {
61:                  _asm GOTO high_isr _endasm
  0008    EF2F     GOTO 0x5e/////////////////////开始
  000A    F000     NOP
62:                }
  000C    0012     RETURN 0
63:                #pragma code 
64:                
65:                #pragma interrupt high_isr
66:                void high_isr (void)
  005E    CFDA     MOVFF 0xfda, 0xfe4
  0060    FFE4     NOP
  0062    CFE2     MOVFF 0xfe2, 0xfda
  0064    FFDA     NOP
  0066    CFE9     MOVFF 0xfe9, 0xfe4
  0068    FFE4     NOP
  006A    CFEA     MOVFF 0xfea, 0xfe4
  006C    FFE4     NOP
  006E    52E6     MOVF 0xfe6, F, ACCESS
  0070    CFD9     MOVFF 0xfd9, 0xfe6
  0072    FFE6     NOP
  0074    CFE1     MOVFF 0xfe1, 0xfd9
  0076    FFD9     NOP
  0078    0E02     MOVLW 0x2
  007A    26E1     ADDWF 0xfe1, F, ACCESS
67:                {
68:                
69:                uint8 temp;
70:                uint8 tempSSPSTAT;
71:                
72:                if(INTCONbits.TMR0IF == 1)//结束,执行中断代码
  007C    A4F2     BTFSS 0xff2, 0x2, ACCESS
  007E    D016     BRA 0xac




从开始到结束,执行中断代码,共18个指令周期,18×0.2=3.6us

哪里来楼主说得几十us?????????????????

使用特权

评论回复
8
machunshui| | 2008-5-15 15:28 | 只看该作者

即使是楼主自己的编译的例子,也仅仅是几个us

即使是楼主自己的编译的例子,也仅仅是几个us,

楼主大概是把每个指令周期算成1us了吧????????

使用特权

评论回复
9
左撇子|  楼主 | 2008-5-15 16:05 | 只看该作者

系统成生的汇编程序里有"BRA"命令

汇编代码里有BNC、BRA、DECF指令,来回循环。时间耗在这里了!
比如:
  0076    04E8     DECF 0xfe8, W, ACCESS
  0078    E303     BNC 0x80
  007A    CFEE     MOVFF 0xfee, 0xfe4
  007C    FFE4     NOP
  007E    D7FB     BRA 0x76

使用特权

评论回复
10
martin| | 2008-5-15 18:04 | 只看该作者

re

看看C18使用说明书里的关于“编译器管理的资源”,以及NOSAVE,tempdata,mathdata等关键词。

使用特权

评论回复
11
machunshui| | 2008-5-15 21:31 | 只看该作者

楼主用的是哪个版本的编译器?

楼主用的是哪个版本的编译器?

你说的循环代码应该不是进出中断的一部分吧??
应该是你自己的代码吧?????????

看看我的C18 3.16生成的代码,没有循环的代码的部分
58:                #pragma code high_vector=0x08
59:                void interrupt_at_high_vector(void)
60:                {
61:                  _asm GOTO high_isr _endasm
  0008    EF2F     GOTO 0x5e
  000A    F000     NOP
62:                }
  000C    0012     RETURN 0
63:                #pragma code 
64:                
65:                #pragma interrupt high_isr
66:                void high_isr (void)
  005E    CFDA     MOVFF 0xfda, 0xfe4
  0060    FFE4     NOP
  0062    CFE2     MOVFF 0xfe2, 0xfda
  0064    FFDA     NOP
  0066    CFE9     MOVFF 0xfe9, 0xfe4
  0068    FFE4     NOP
  006A    CFEA     MOVFF 0xfea, 0xfe4
  006C    FFE4     NOP
  006E    52E6     MOVF 0xfe6, F, ACCESS
  0070    CFD9     MOVFF 0xfd9, 0xfe6
  0072    FFE6     NOP
  0074    CFE1     MOVFF 0xfe1, 0xfd9
  0076    FFD9     NOP
  0078    0E02     MOVLW 0x2
  007A    26E1     ADDWF 0xfe1, F, ACCESS
67:                {
68:                
69:                uint8 temp;
70:                uint8 tempSSPSTAT;
71:                
72:                if(INTCONbits.TMR0IF == 1)//定时10ms
  007C    A4F2     BTFSS 0xff2, 0x2, ACCESS
  007E    D011     BRA 0xa2
73:                {
74:                
75:                bShowLED = 1;
  0080    0100     MOVLB 0
  0082    0E01     MOVLW 0x1
  0084    6F96     MOVWF 0x96, BANKED
76:                /*if(bShowLED != 1)
77:                {
78:                if(ShowLEDTimer0 < 1)
79:                ShowLEDTimer0++;
80:                else
81:                {
82:                ShowLEDTimer0 = 0;
83:                bShowLED = 1;
84:                }
85:                }*/
86:                
87:                if(bKeyDelay)
  0086    519B     MOVF 0x9b, W, BANKED
  0088    E007     BZ 0x98
88:                {
89:                if(KeyDelayTimer0 < 1)
  008A    0E01     MOVLW 0x1
  008C    5D9D     SUBWF 0x9d, W, BANKED
  008E    E202     BC 0x94
90:                KeyDelayTimer0++;
  0090    2B9D     INCF 0x9d, F, BANKED
91:                else
  0092    D002     BRA 0x98
92:                {
93:                bKeyDelay = 0;
  0094    6B9B     CLRF 0x9b, BANKED
94:                KeyDelayTimer0 = 0;
  0096    6B9D     CLRF 0x9d, BANKED
95:                }
96:                }
97:                
98:                TMR0H = 0xE5;
  0098    0EE5     MOVLW 0xe5
  009A    6ED7     MOVWF 0xfd7, ACCESS
99:                TMR0L = 0x01;
  009C    0E01     MOVLW 0x1
  009E    6ED6     MOVWF 0xfd6, ACCESS
100:               
101:               INTCONbits.TMR0IF = 0;
  00A0    94F2     BCF 0xff2, 0x2, ACCESS
102:               }

使用特权

评论回复
12
左撇子|  楼主 | 2008-5-16 08:29 | 只看该作者

C18 V3.0

TO 9楼:
看了一下编译器管理的资源,还是不太明白什么意思。能请你点明一下么?谢谢
我个人理解的是如果没有用“save"命令,它只保护基本现场。


TO 10楼:
我用的是C18 V3.0正版编译器。官方下载的V3.16有时间限制,所以没用。

使用特权

评论回复
13
machunshui| | 2008-5-16 10:29 | 只看该作者

看来还是你自己的程序部分有循环

看来还是你自己的程序部分有循环

使用特权

评论回复
14
hotpower| | 2008-5-16 12:33 | 只看该作者

学习学习~~~可惜没机会用过18系列

使用特权

评论回复
15
左撇子|  楼主 | 2008-5-16 13:35 | 只看该作者

问题解决了

问题解决了,谢谢楼上几位朋友!

我把中断程序中的子程序"Interrupt_PWM()" "Interrupt_Int012()"删掉,直接把子程序代码复制到中断程序里,就可以了。

所以,我想这个问题出在函数嵌套上。我之所以在中断里嵌套子函数,是看了另一个C30的中断程序,里面可是子函数套子函数。
另外,我还发现在中断程序里定义局部变量,也会出现类似情况。改为全局变量就没问题了。

再次谢谢

使用特权

评论回复
16
陈双君| | 2008-9-19 17:14 | 只看该作者

搞一现场保护专用子函数得了。

搞一现场保护专用子函数得了。这样更放心。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

33

帖子

1

粉丝