搜索
bottom↓
回复: 12

分享PIC18单片机的低优先级中断的中断现场保护的恶心之处

[复制链接]

出0入0汤圆

发表于 2014-11-6 14:34:38 | 显示全部楼层 |阅读模式
本帖最后由 heqiaosheng 于 2014-11-6 14:34 编辑

因为是初次使用PIC18f25k80单片机,所以对应它的中断保护没什么了解,只知道有两个优先级,然后项目中使用到的外设比较多,中断也比较多,所以就将中断分成高优先级和低优先级。

然后诡异的事就发生了,程序经常性的跑飞,大概纠结了一个月,那时我都怀疑我的编程能力了,最终找到了问题,我草,PIC18的低优先级中断竟然不保护现场!!!

希望以后用到此系类的同志们能注意到这个问题,强烈推荐只使用高优先级中断。虽然网上有中断保护的汇编代码,但是我没有用,我觉得高优先级中断就够了,那个恶心的低优先级中断就让它长眠吧!!!

图片来源:MPLAB C18 C 编译器入门 [06版].pdf 的102页。已经上传过了,要下载的请打开此链接 http://www.amobbs.com/thread-5603111-1-1.html






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-11-6 15:16:35 | 显示全部楼层
楼主从哪里搞到这么高级版本的中文版?自从有一次中文版把寄存器翻译错了,让我多调了3天,再也不敢用中文翻译的文档了。

出0入0汤圆

 楼主| 发表于 2014-11-6 15:43:02 | 显示全部楼层
tangkuan660 发表于 2014-11-6 15:16
楼主从哪里搞到这么高级版本的中文版?自从有一次中文版把寄存器翻译错了,让我多调了3天,再也不敢用中文 ...

PIC的中文文档比较丰富,以上文档是编译器安装时的自带的参考文档。

出0入0汤圆

发表于 2014-11-6 16:31:36 | 显示全部楼层
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1 #pragma code InterruptVectorLow = 0x18 //用#pragma伪指令定义一个名字叫InterruptVectorLow的段,并把这个段放到0x18地址起始的代码空间
void InterruptVectorLow (void)  //低优先级中断向量函数
{
  _asm  
  goto InterruptHandlerLow   //内嵌汇编指令
  _endasm
}
#pragma code     //这里不是多余的,它是告诉连接器回到默认的代码段,如果不加的话,连接器就会傻傻地把后面的代码紧跟着上面的代码一直放下去。而LKR文件里定义了向量区最多到0x29地址,所以如果没加此行通常会报错

#pragma interruptlow InterruptHandlerLow  //这里使用interruptlow这个关键词来声明InterruptHandlerLow这个函数是低优先级中断服务函数,用了关键词后,这个函数将会由编译器自动产生基本的现场保护,并且这个函数的返回将是使用RETFIE返回的。


void InterruptHandlerLow (void)
{
      /* 低优先级服务函数的代码写在这里*/
}

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1 #pragma code InterruptVectorHigh = 0x08 //用#pragma伪指令定义一个名字叫InterruptVectorHigh的段,并把这个段放到0x08地址起始的代码空间
void InterruptVectorHigh (void) //高优先级中断向量函数
{
  _asm
  goto InterruptHandlerHigh //内嵌汇编指令
  _endasm
}
#pragma code  //回到默认代码段,原因同上
#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh (void)
{
/* 高优先级服务函数的代码写在这里*/

  if (INTCONbits.TMR0IF)
  {//check for TMR0 overflow
        INTCONbits.TMR0IF = 0;            //clear interrupt flag
       ;
     ;
  }
}

网上找到的,楼主可以验证是否有用

出5入14汤圆

发表于 2014-11-6 17:01:23 | 显示全部楼层
虽然也用 PIC18 ,但从没使用过中断嵌套,所以没遇到楼主的问题,但对楼主的问题我有疑问:
1、PIC16 级别的单片机,你说的那些寄存器也都不是由CPU自动保存的,也需要代码来保存,照你这么说,PIC16 的中断都别用了?
2、一直以为除非你用汇编,用 C 的话应该不需要你考虑中断现场保护的事情吧,C 编译器不是都帮你做到了么?(C编译器应该对此有明确的说明,如果需要你自己用代码保护现场,也应该会有明确的说明的吧)

出0入0汤圆

 楼主| 发表于 2014-11-7 16:43:24 | 显示全部楼层
yklstudent 发表于 2014-11-6 16:31
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1  ...

我就是这样写的。

//=============================================================================
//【函数功能】中断处理子函数
//【参数说明】无
//【创建时间】
//【修改时间】
//=============================================================================

//----------------------------------------------------------------------------
// Low priority interrupt vector

#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
{
  _asm
    goto InterruptHandlerLow //jump to interrupt routine
  _endasm
}

//----------------------------------------------------------------------------
// Low priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerLow

void InterruptHandlerLow(void)// 低优先级中断处理(只保存PC)
{
       
}

//----------------------------------------------------------------------------
// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
  _asm
    goto InterruptHandlerHigh //jump to interrupt routine
  _endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

// 注意此中断处理函数需要在开头声明
void InterruptHandlerHigh(void)// 高优先级中断处理(自动保存PC、WREG、BSR和STAUTS寄存器)
{
        u8 i = 0;
       
        if(INTCONbits.TMR0IF == 1)
        {
                ;
        }
       
        if(INTCONbits.RBIF == 1)// PB电平中断
        {
                INTCONbits.RBIF = 0;
               
                ;
        }

        if(PIR1bits.TMR1IF == 1)// Timer1中断处理
        {                        
                ;
        }

        if(PIR1bits.RC1IF == 1)// 串口接收中断
        {
                i = RCREG1;//  清除标志
        }

        if(PIR5bits.RXB0IF == 1)// CAN接收中断
        {   
                PIR5bits.RXB0IF = 0;// 清接收中断标志
        }
}

出0入0汤圆

发表于 2014-11-7 16:48:25 | 显示全部楼层
heqiaosheng 发表于 2014-11-7 16:43
我就是这样写的。

//=============================================================================

这样写,还是有问题?
幸好一开始我就一直用的高中断,低中断一直没去用过

出0入0汤圆

发表于 2014-11-7 21:32:17 | 显示全部楼层
那个仅是说明PIC18芯片高低中断发生时,芯片自身的现场保护吧,如果用C18编译器,编译器会自动处理这些,

你发的MC18用户指南中也对中断进行了说明啊,编译器会按照关键字进行对应的处理的
“interruptpragma伪指令将函数声明为高优先级的中断服务程序;interruptlowpragma伪指令将函数声明为低优先级的中断服务程序”
“高优先级中断使用影子寄存器保存和恢复最小现场,而低优先级中断则使用软件堆栈保存和恢复最小现场”

还是多找找程序中是否有其它问题。

出100入101汤圆

发表于 2014-11-7 21:57:35 | 显示全部楼层
关注一下!

出0入0汤圆

发表于 2014-11-8 10:17:46 | 显示全部楼层
tdh03z 发表于 2014-11-7 21:32
那个仅是说明PIC18芯片高低中断发生时,芯片自身的现场保护吧,如果用C18编译器,编译器会自动处理这些,

...

8楼正解,我用PICC18 PRO编译器,不用自己保存现场,一直正常工作。

出0入0汤圆

发表于 2014-11-8 12:37:18 | 显示全部楼层
用pic18f25k22,XC8编译的,重要中断放高优先级的,次要的比如串口(这个项目不需要通信)就放低优先级的,做过各种干扰实验了,还没有出现过跑飞的现象。

出0入0汤圆

发表于 2014-11-10 16:38:43 | 显示全部楼层
用XC8吧,现在正版打折。

出0入0汤圆

发表于 2014-11-13 10:09:41 | 显示全部楼层
遇见过,该中断的没进去...郁闷很久
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-5 10:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表