为什么在写中断服务函数函数时要写#pragmaCODE

Codewarrior for HCS12的中断服务程序编写说明
10:54:38来源: eefocus
在CW4.6环境下,中断编程主要有两种方式:
第一种是使用&&关键字,&interrupt&关键字是一个非标准ANSI-C的关键字,因此,它不能被所有ANSI-C编译器厂商所支持。同样,对不同的编译器,interrupt&关键字的用法可能会改变。&interrupt&关键字同样会提示编译器下面的函数是一个例程。
例: void interrupt 20 SCI0_ISR(void);
其中,interrupt表示该函数为终端服务程序,后面的20表示中断号20,在这里SCI0的中断向量号就是20.
这种方法写起来非常简单,但是,在S12实际使用中,中断号并没有在手册中给出,通常需要自己在中断向量表中从上往下数出来,或者根据中断向量计算得到,很容易出错。
于是有了第二种方法:
在ISR程序之前,使用符号&#pragma TRAP_PROC&,TRAP_PROC 提示编译器下面的函数是中断服务例程。编译器会用一个特殊的中断返回指令来结束这个函数。
此时,中断函数的书写如下所示:
#pragma TRAP_PROC
void SCI0_ISR(void){
这时候编译器不知道这个ISR指向那个中断向量,我们需要在链接文件即:prm文件中指定之。
使用 VECTOR命令来实现中断向量与ISR程序的连接。
VECTOR 0 _Stap&&&&//这是系统默认prm文件中自带的,即复位后0号中断即复位中断的ISR为_Startup()
我们可以这样写:
VECTOR 20 SCI0_ISR& //指定中断号
VECTOR ADDRESS 0xFFD6 SCI0_ISR&& //直接指定中断向量地址
注:使用#pragma TRAP_PROC与修改prm文件的方法,在中断服务子程序的结尾处必须要手动加入返回主程序的指令,包括取出堆栈、中断返回两个步骤。
在S12单片机中,可以写作
两种方法所写的中断服务子程序必须被放在非分页存储区内,即non_blanked code seg.
其中一种常用的方法是在服务子程序前声明:
//下面代码放在NON_BANKED区
#pragma CODE_SEG NON_BANKED
在中断程序后声明:
//下面内容按默认放置
#pragma CODE_SEG DEFAULT&
关键字:&&&&&&
编辑:什么鱼
引用地址:
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
微信扫一扫加关注 论坛活动 E手掌握
微信扫一扫加关注
芯片资讯 锐利解读
大学堂最新课程
汇总了TI汽车信息娱乐系统方案、优质音频解决方案、汽车娱乐系统和仪表盘参考设计相关的文档、视频等资源
热门资源推荐
频道白皮书
何立民专栏
北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。写中断函数位置的问题 - STM32 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 1549|回复: 7
写中断函数位置的问题
在线时间45 小时
该用户从未签到主题帖子好友
中级会员, 积分 350, 距离下一级还需 150 积分
中级会员, 积分 350, 距离下一级还需 150 积分
以前只用过F103,用的也是标准库,学的时候就被告诉所有中断函数都写在stm32f10x_it.c里。之前论坛里看见有人发了个帖子关于串口环形队列的,就下了程序学习学习,结果这一看程序彻底把我搞蒙了,因为它的串口中断函数根本没写在stm32f10x_it.c里,我一时还没找到具体在哪,以为没有中断函数呢,但一想不可能啊,它介绍的时候就说了用的串口发送中断,过了一段时间才发现在串口配置的.c文件里了。后来,抢到了L476的板子,这一接触到HAL更蒙了,stm32l4xx_it.c里不是没看见中断函数就是用的callback函数。表示变化太大接受不了啊。最后想说一下既然准备了一个写中断函数的.c文件为啥都要写在其他地方呢,多增加看程序的难度啊(至少我看程序的难度增加了)。
在线时间835 小时
ST金币3219
该用户从未签到主题帖子好友
只要接口对,写哪儿都行。有的习惯写到对应的模块驱动中。
1。太多的中断,如果所有的中断都写在it.c文件中,那it.c文件就太大了。
2。当在it.c文件中写中断的时候,免不了与其他的c文件共享变量。如果这样的话,还需要头文件或者extern来处理,太麻烦。
3。如果全写在it.c中的话,读程序也很头疼。看到it.c中的一个中断,还要去翻翻其他的程序看看这个中断中使用的变量,也不利于阅读。
个人推荐还是将中断写在相应的驱动模块中。
在线时间65 小时
该用户从未签到主题帖子好友
高级会员, 积分 724, 距离下一级还需 276 积分
高级会员, 积分 724, 距离下一级还需 276 积分
写在it.c里面也应该没问题的,看个人习惯,楼主可以试下
在线时间45 小时
该用户从未签到主题帖子好友
中级会员, 积分 350, 距离下一级还需 150 积分
中级会员, 积分 350, 距离下一级还需 150 积分
我也感觉应该是写在哪有可以的
在线时间629 小时
ST金币1849
该用户从未签到主题帖子好友
只要接口对,写哪儿都行。有的习惯写到对应的模块驱动中。
在线时间45 小时
该用户从未签到主题帖子好友
中级会员, 积分 350, 距离下一级还需 150 积分
中级会员, 积分 350, 距离下一级还需 150 积分
只要接口对,写哪儿都行。有的习惯写到对应的模块驱动中。
哦,我之前学的时候教我的人告诉我必须写在it.c里面。以为写在其他地方不工作呢
在线时间18 小时
该用户从未签到主题帖子好友
中级会员, 积分 277, 距离下一级还需 223 积分
中级会员, 积分 277, 距离下一级还需 223 积分
这个挺高级呀,哈哈,确实我也没有研究过
在线时间1568 小时
ST金币9631
该用户从未签到主题帖子好友
1。太多的中断,如果所有的中断都写在it.c文件中,那it.c文件就太大了。
2。当在it.c文件中写中断的 ...
写到相应的模块中是极好的解决办法,特别是有共享变量时!
不过现在的HAL都是使用的回调函数的形式,所以处理好回调函数的位置即可。
STM32粉丝勋章Ⅳ
狂欢节专属(智多星)
STM32粉丝勋章Ⅲ
狂欢节专属(分享宝宝)
STM32粉丝勋章Ⅰ
狂欢节专属(微信上墙)
STM32粉丝勋章Ⅱ
狂欢节专属(研讨会问答)
站长推荐 /2
Tel: 3-8064
备案号: 苏ICP备号-2
|||意法半导体STM32/STM8技术社区
Powered by提问:ARM在中断程序中该如何关中断? - 捷配电子市场网
提问:ARM在中断程序中该如何关中断?
作者:linjing 栏目:
提问:ARM在中断程序中该如何关中断?想要在SWI中断中访问管脚,同时FIQ中断中也需要访问这几个管脚,所以想在SWI中断中把FIQ中断禁止,该怎么做比较好?似乎不用先调用关中断例程,返回时再调用开中断例程这么麻烦吧,不知道如下面这么做可不可行?int swi(0) PortAccess( void ){&&&&__asm {&&&&&&&&MSR CPSR_c, Mode_SVC + F_IRQ + I_IRQ&&&&}&&&&...&&// 读写与FIQ有冲突的管脚&&&&// SWI中断返回时是不是会自动将SPSR恢复到SPSR中从而重新恢复中断?}另外,按照ARM的建议,修改CPSR时应该用读-修改-写的方式,可在Keil的启动代码中Starts.s中就是用的立即数修改CPSR的,这么做有没有问题. * - 本贴最后修改时间: 12:09:32 修改者:linjing
作者: computer00 于
18:12:00 发布:
晕~~~那是因为才刚刚启动,所以没必要保留以前的状态信息MSR CPSR, #(Mode_SVC + F_IRQ + I_IRQ)好象这里的CPSR需要指定修改哪个区的吧,光这样好象编译通不过的~~~~~
作者: linjing 于
12:08:00 发布:
见笑了,我刚接触ARM,指令不太熟悉我的意思是不用读-修改-写的方式,而直接用立即数改写CPRS,SWI中断返回时候自动恢复原来的状态,不需要手动恢复,请问二楼,这样可不可行?
作者: computer00 于
13:00:00 发布:
最好不要直接修改,可能会不小心修改了其它标志位读回来,放到一个寄存器,然后再修改某一个位,保留其它位不变,再写回去,也不是很麻烦啊。要不你就把你的FIQ改到IRQ里面,这样就不用担心被打断了~~~~~~~
作者: linjing 于
17:48:00 发布:
回computer00 ,其实我这样做是由具体情况决定的我说的SWI中断访问的管脚实际上是想要模拟8位的外部总线我说的FIQ中断是定时器中断,是我系统中的唯一的中断源,所以想用FIQ可能会简单些,定时中断用于生成系统时基,以及按键定时扫描(按键扫描是通过前面说的模拟8位总线进行的)既然是模拟总线,所以希望能快点最好还是尽量快点,其实如果不追求速度的话,我完全可以将模拟总线包写成普通函数,再写两个SWI中断通过修改SPRS开/关中断,可相对来说那样多出许多指令。(我不喜欢用太高的晶振或者PLL,不希望一味通过提高主频来提速,纯粹个人习惯:)其实如果实际做的话我也考虑过把FIQ改成向量IRQ,但我还是能希望探讨一些细节,也希望藉此来尽快熟悉ARM的体系结构如果按照computer00 的说法,我不用立即数,改成下面的样子,可以吗int swi(0) PortAccess( void ){&&&&__asm {&&&&&&&&MRS R0, CPSR&&&&&&&&ORR R0, RO, #F_IRQ + I_IRQ&&&&&&&&MSR CPSR_c, R0&&&&}&&&&...&&// 模拟总线&&&&// SWI中断返回时是不是会自动将SPSR恢复到SPSR中从而重新恢复中断?}
作者: computer00 于
18:34:00 发布:
这样应该可以的.为什么模拟总线要通过SWI啊? 关中断不如直接关中断控制寄存器来得快吧.这样就不用SWI来搞.
作者: linjing 于
22:02:00 发布:
楼上的意思是不必禁止FIQ位和IRQ位,而是直接关中断控制器?暂时还没看懂的那个中断系统,不过这个办法似乎不错,如果可行的话倒象是更简单,受教了!
作者: computer00 于
10:28:00 发布:
参看我以前写过的代码:如果你只有一个中断,并且以后不会再扩展的话,你可以直接使用VICIntEnClr=0xFFFFFFFF;VICIntEnable= 来控制中断./**********************************************************************************************功能:进入临界段。入口参数:无。返回:无。备注:该函数使用的是将中断分配寄存器清0的方法来关中断。比起用软中断,运行速度要快。&&&&&&如果要开某个中断,则应该先调用一次该函数,然后再修改中断备份变量CopyOfVICIntEnable&&&&&&的值,而不能直接修改VICIntEnable的值。否则会出错。**********************************************************************************************/void OSEnterCritical(void){ if(OSEnCrCount==0)&&&//如果前面未关中断&&{&&&VICIntEnClr=0xFFFFFFFF;&&&&&&&&&&&//将VICIntEnable清除,禁止中断&&} OSEnCrCount++;&&//进入临界段次数加1}//////////////////////////////////End of function///////////////////////////////////////////////**********************************************************************************************功能:退出临界段入口参数:无。返回:无。备注:无。**********************************************************************************************/void OSExitCritical(void){ if(OSEnCrCount&=1)&&//如果进入临界段的次数大于等于1次&&{&&&OSEnCrCount--;&&&&//则次数减1&&&if(OSEnCrCount==0)&&//如果减次数减到0,则要开中断&&&&{&&&&&VICIntEnable=CopyOfVICIntE&&//打开所需要开的中断&&&&}&&}}//////////////////////////////////End of function//////////////////////////////////////////////
作者: linjing 于
11:58:00 发布:
先收藏,再分析,谢谢computer00&
作者: zlgARM 于
17:37:00 发布:
linjing&&&&圈圈的关中断方法也可以。&&&&如果把中断看成是水龙头,那么如果想要关掉屋子里的水龙头,可以有两个办法。&&&&其一:关总阀。所有水龙头都没法再用,修改CPSR来关中断的方法属于此类;&&&&其二:逐个地把所有或部分水龙头关掉,修改VICIntEnClr的方法属此类。&&&&
作者: linjing 于
10:27:00 发布:
用惯了Keil C51,在51中都是用的#pragma disableKeil C51的#pragma disable有一个很重要的特点,进入子程序的时候保存中断允许位EA的状态,退出子程序的时候不是简单的开中断,而是“恢复”原来的中断允许EA的状态,逻辑上完整
作者: 有意思 于
14:42:00 发布:
这样可不可以__inline void enable_IRQ(void){&&&&__asm&&&&{&&&&&&&&MRS r1, CPSR&&&&&&&&BIC r1, r1, #0x80&&&&&&&&MSR CPSR_c, r1&&&&}}__inline void disable_IRQ(void){&&&&__asm&&&&{&&&&&&&&MRS r1, CPSR&&&&&&&&ORR r1, r1, #0x80&&&&&&&&MSR CPSR_c, r1&&&&}}
作者: linjing 于
21:30:00 发布:
百步笑一下五十步:)“有意思”,五十步了吧:)你的办法是可以,但必须放到特权模式下才行,就是前面提到的在用户模式下为什么要用SWI进管态关中断的问题,只有进入管态才能用你的程序。
作者: 有意思 于
22:16:00 发布:
那这样呢Maskmd&&&&&&&EQU&&&&&0x1f&&&&&&&&&&&&&&SVC32md&&&&&&EQU&&&&&0x13I_Bit&&&&&&&&EQU&&&&&0x80FRAME_R0&&&&&EQU&&&&&0X00FRAME_R1&&&&&EQU&&&&&FRAME_R0 + 4FRAME_R2&&&&&EQU&&&&&FRAME_R1 + 4FRAME_R3&&&&&EQU&&&&&FRAME_R2 + 4FRAME_R4&&&&&EQU&&&&&FRAME_R3 + 4FRAME_R5&&&&&EQU&&&&&FRAME_R4 + 4FRAME_R6&&&&&EQU&&&&&FRAME_R5 + 4FRAME_R7&&&&&EQU&&&&&FRAME_R6 + 4FRAME_R8&&&&&EQU&&&&&FRAME_R7 + 4FRAME_R9&&&&&EQU&&&&&FRAME_R8 + 4FRAME_R10&&&&EQU&&&&&FRAME_R9 + 4FRAME_R11&&&&EQU&&&&&FRAME_R10 + 4FRAME_R12&&&&EQU&&&&&FRAME_R11 + 4FRAME_PSR&&&&EQU&&&&&FRAME_12 + 4FRAME_LR&&&&&EQU&&&&&FRAME_PSR + 4FRAME_PC&&&&&EQU&&&&&FRAME_LR + 4FRAME_SIZE&&&EQU&&&&&FRAME_PC + 4IRQ_Entry&&&&SUB&&&&&&r14,r14,#4&&&&STMDB&&&&r13,!{r0-r3,r12,r14}&&&&&服务中断&&&&&BL&&&&&&&read_RescheduleFlag&&&&CMP&&&&&&r0,#0&&&&LDMNEIA&&r13!,{r0-r13,r12,PC}^&&&&MRS&&&&&&r2,spsr&&&&MOV&&&&&&r0,r13&&&&ADD&&&&&&r13,r13,#6*4&&&&MRS&&&&&&r1,cpsr&&&&BIC&&&&&&r1,r1,#Maskmd&&&&ORR&&&&&&r1,r1,SVC32md&&&&MSR&&&&&&cpsr_c,r1&&&&SUB&&&&&&r13,r13,#FRAME_SIZE-FRAME_R4&&&&STMIA&&&&r13,{r4-r11}&&&&LDMIA&&&&r0,{r4-r9}&&&&BIC&&&&&&r1,r1,#I_Bit&&&&MSR&&&&&&cpsr_c,r1&&&&STMDB&&&&r13!,{r4-r7}&&&&STR&&&&&&r2,[r13,#FRAME_PSR]&&&&STR&&&&&&r8,[r13,#FRAME_R12]&&&&STR&&&&&&r9,[r13,#FRAME_PC]&&&&STR&&&&&&r14,[r13,#FRAME_LR]&&&&&&&&&完成中断服务程序&&&&&LDMIA&&&&r13!,{r0-r12,r14}&&&&MSR&&&&&&spsr_cxsf,r14&&&&LDMIA&&&&r13!,{r14,pc}^
作者: linjing 于
22:29:00 发布:
百步只好向五十步说抱歉:(百步最近刚接触ARM,根本看不懂ARM的汇编指令:{自从知道ARM是什么东东之后,说实话,我根本就没打算去抠ARM的汇编,你想啊,现在有谁Windows编程的时候还去管x86的汇编指令的,不过现在看来汇编指令还是要学点的,不过您帖的程序只好懂我能看懂的时候再回了。抱歉抱歉,不过本帖已收藏,回头我会看的
作者: 有意思 于
10:12:00 发布:
你以为是我写的啊,没那本事书上抄地,建议你看本书ARM 嵌入式系统开发 ----软件设计与优化ARM
Devcloper`s Guide:Designing and Optimizing
[美] Andrew N.Sloss[英] Dominic Sysmes[美] Chis Wright 沈建华译北航出的,75块里面详细介绍了可重入中断处理等 * - 本贴最后修改时间: 10:15:42 修改者:有意思 arm嵌入式系统开发:软件设计与优化
作者: linjing 于
17:13:00 发布:
问 computer00我如果令VICProtection=1, 你前面的 进出临界段 的代码还能直接用吗。一般VICProtection的保护功能需要用吗
作者: hotpower 于
18:58:00 发布:
VICProtection只对用户级有作用~~~&
作者: linjing 于
19:47:00 发布:
追问一下,系统中只有一个中断的时候,用FIQ与IRQ会有什么区别?好像FIQ还有几个专用的寄存器,这是已知的不同我的疑问是在只有一个中断源的时候,用FIQ响应和用IRQ开销是不是都一样,包括影响中断的时间,堆栈的占用,等等,还有其他的方面吗??
讨论内容:
Copyright &
www.dzsc.com 浙ICP证030469号2008年6月 C/C++大版内专家分月排行榜第二
2008年9月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。&&|&& &&|&& &&|&&
MPLAB C18学习 简单的Timer0定时器中断程序
11:12:50 && 阅读:3184&&
MPLAB C18学习 简单的Timer0定时器中断程序
注意:本人刚学C18,不能保证程序没有错误!
#include &p18cxxx.h&
#pragma config WDT = OFF
void timer0(void);
#pragma code timer_interrupt = 0x08&&&&& //把GOTO指令放在高优先级中断向量处
void timer_interrupt(void)
&&& _asm&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //通过汇编的GOTO指令跳转到中断服务程序
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//C语言里的goto只在函数内部有效
&&& goto timer0
&&& _endasm
#pragma code&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//切换回普通代码段
volatile unsigned char counter = 0;&&&&&&&&&& //有可能中断函数和普通程序都要用的变量要
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//用volatile声明,以使编译器不对其进行优化
#pragma interrupt timer0
void timer0(void)
&&& INTCONbits.T0IF = 0;&&&&&&&&&&&&&&&&&&&&& //清除T0中断标志,必须操作
&&& TMR0H = 0x3c;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //重置定时器初值,这里也是要先TMR0H再L
&&& TMR0L = 0xb0;
&&& counter++;
void main(void)
&&& //INTCONbits.PEIE = 0;
&&& //RCONbits.IPEN = 1;
&&& INTCONbits.T0IF = 0;&&&&&&& //与INTCONbits.TMR0IF = 0;等价,清除T0中断标志
&&& T0CONbits.T08BIT = 0;&&&&& //设定T0为16位模式
&&& T0CONbits.T0CS = 0;&&&&&&&&&//选择内部指令时钟为时钟源,也是定时器计数器选
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//择位,0即为定时器
&&& T0CONbits.PSA = 1;&&&&&&&&&& //选择不使用分频器
&&& TMR0H = 0x3c;&&&&&&&&&&&&&&&&&& //设定T0的定时初值,这里因为外部时钟设定为
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //4MHz,PIC单片机的机器周期为4个时钟周期,即
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//1&s,定时器定时时间为(0xFFFF-0x3CB0+1)*1&s=
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//50ms
&&& TMR0L = 0xb0;&&&&&&&&&&&&&&&&&&&//注意,必须先定义TMR0H,再定义TMR0L。
&&& INTCONbits.T0IE = 1;&&&&&&& //与INTCONbits.TMR0IE = 1;等价,打开定时器中断
&&& INTCONbits.GIE = 1;&&&&&&&&& //打开全局中断使能
&&& T0CONbits.TMR0ON = 1;&&//打开T0
&&& while(1);
定时器溢出产生中断3次后,运行时间为150.180000ms
关于需要先定义TMR0H再定义TMR0L:
TMR0H只是Timer0高字节的缓存,在写入TMR0L时才会写入。这样是能一次读取Timer0的所有位,防止在读取低字节时高字节有变化。
参考资料:MPLAB C18 C编译器用户指南,PIC18Fxx2数据手册
后参与讨论
阅读:3200
阅读:3209
阅读:4209
阅读:5054

我要回帖

更多关于 中断函数 的文章

 

随机推荐