微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 硬件电路设计 > TI模拟硬件电路设计 > 再提PWM中断和SCI中断冲突问题,看看这样的程序到底有什么问题啊(附程序)?

再提PWM中断和SCI中断冲突问题,看看这样的程序到底有什么问题啊(附程序)?

时间:10-02 整理:3721RD 点击:
再次请教各位大侠,我在dsp2407 C环境编程中的运行PWM中断和SCI中断时出现冲突问题,我把程序看了很久,实在是没辙了;
情况说明: 1. pwm用的是T3下溢中断,cpu频率40M.波特率9600。
2. SCI是用串口调试助手调试。
3.上面2个中断单个运行都是很正常。
4.运行PWM中断和SCI中断时没有多久就出现其中一个中断死了的现象,一般约通讯8

mlwang_km 大哥,
我看到很多程序都是在返回中断处加开总中断啊,我把程序作了小修改还是不行啊,不过这次运行次数最长有154次,并且有时候出现在通讯中断死了一会后又自动进入中断的现象,真是烦死人啊!

/****************************************************************************
/*****************SVPWM interupt program using T3UPINT***********************
/****************************************************************************/
void interrupt PWMINT()
{
//IFR=IFR|0x0002;//clear the int2 flag
PBDATDIR|=0x0fe80;//测试中断时间
switch(PIVR)
{
case 0x0031:
{
//测试入中断次数
gg++;
if(gg>=10000)
gg=0;
//测试入中断次数
T3CNT=0x0000; //定时器3的计数器重新赋0
EVBIFRA=EVBIFRA&0x0200; break;
}
default:break;
}
PBDATDIR=PBDATDIR&0x0fef7f;//测试中断时间
//enable();
IFR=IFR|0x0002;//clear the int2 flag
return;
}
void interrupt SCIINT()
{
PBDATDIR|=0x0fe02;//测试中断时间
switch(PIVR)
{
case 6:
{
//SCIRXINT();
scir[bagpointer]=SCIRXBUF;
bagpointer++;//接受数据指针
if(bagpointer>=9)
bagpointer=0;
//测试入中断次数
ss++;
if(ss>=10000)
ss=0;
//测试入中断次数
break;
}
default: break;
}
IFR=0x0010; //清除IFR中相应的中断标志
PBDATDIR=PBDATDIR&0x0fefd;//测试中断时间
//enable();
return;

}

程序上看不出啥问题。
你所说的“运行xix 次“是什么意思?连续接受多少字节才算一次?”通讯中断死了“又是什么情况?用DEBUG看到程序跑飞了吗?还是仅仅收不到信息?

谢谢大哥在百忙回答我的问题!
我是PC每秒发一个字节,波特率为9600b/s,一共通讯了154次,也就是运行了154秒,最后SCI中断再也不响应了(用示波器看到SCI中断中操作的I/O跳变波形没有了,再看看接收计数器的值也不增加了), 通过试验发现同时运行pwm和sci时,多是SCI中断没有响应了。还想请问大哥怎么用DEBUG看到程序跑飞了?

     运行中显示 CPU 寄存器的值,随时看看 PC (指令计数器)的值是否正常(应该在主程序的死循环内),或者觉得不对劲时通过DEBUG  HALT 停止连续运行,单指令走几步,如果完全在正确的路线循环,说明没有跑飞,仅仅是没有中断。如果地址乱套,跑到自己的程序代码之外,那当然是跑飞了。

     还有有个办法。板上总会有个接在某输出腿上的发光二极管的吧?正好定时器也有。在定时器中断中,令一标识按一定频率翻转。主程序反正闲着无事,让它随时判此标志,开,关发光二级管。这样只要一看到发光二极管停止闪烁,就知道程序跑飞了。

我看此坛上还有好几位网友提到中断冲突问题,到底是真的有冲突,还是大家处理上还有什么疏忽,对我们每个想用2407 A 的人,是一件大事,不能不密切关注。
问题是中断是突然发生的事件,不易模拟测试,难矣哉!

不应该用 |
假设同时来了INT2和5中断,标志都出现了,优先级的关系进了2,*IFR = *IFR | 0x?后,结果有1的位都清了,就把中断5也清了,应该用=0x?

不应清中断标志,好像其他的中断都没有这样的现象阿!

CPU 中断标志 IFR 通常不需要在中断服务程序中清除,是在CPU响应中断时自动清除的。只有“当通过INTR指令来请求中断且相应的IFR 位被置为1 是,CPU不会自动清除该位,该位必须由软件来清除。”
中断服务中清除 IFR 如果操作不当,确实会有 LZP 指出的问题。

但是PWM中断却要清阿,不清就只能进入一次!并且CAP中断也要软件清中断阿!难道sci有什么特殊点?请大家发表高见啊!

要清的是外设中断标志,如:
EVBIFRA=EVBIFRA&0x0200;
而不是CPU中断标志 IFR , 各种中断都是一样的。
“当一个可屏蔽中断被响应时,只有IFR位被清除。相应的外设控制寄存器中的标志不会清除”< ...DSP CPU与外设> p 55

PWM 中断(实际是定时器中断吧?),再加 SCI ,ADC中断,有这么三个中断源的测试程序我做过,并不清 IFR,好像没啥问题。当然由于 SCI 接收代码不是非常多,我现在也还不敢肯定就完全可靠了。因此也才特别关注各位实验的情况

理解,谢谢,那刘和平的书(北航版)就是错误的啦!

&nbsp;&nbsp;我没看过刘和平的书。只看过清华大学出版社的 ..DSP 指令和编程工具,间或参考一下原文(清华的几本书,实际就是 TI 公司文档的译文,翻译质量参差不齐)。这一点上讲得还是清楚的。

串口用int5 :
*IFR = 0x0010;
// AD中断服务子程序:
*IFR = 0x0001; //清除IFR中相应的中断标志
//EVA中断:
*EVAIFRA = iflg; // 清除所有中断标志 ,不必开中断
*IFR=0x0002;

不清的话,就会频繁进中断,这是我在AD中断试出的,本来我打算用定时器1周期中断标志自动启动,定时器1周期250us,但AD中断里没写*IFR = 0x0001; 结果20usAD就中断一次了,所以,中断程序里要清

我又回过头查看了一下我的测试程序,也用到AD,除了初始化时*IFR= 0FFFF 外,中断服务中根本不清 IFR ,好像没啥异常呀。
这是一个问题,多留意留意吧。

我又再次翻阅了TI公司文档:
SPRA 755 A Getting Started in C and Assemble
SPRU 357 B System and Peripherals
中的程序例,这些程序当然比较简单,只有一个中断源。中断服务程序中都不写 IFR。

我现在就是没有清IFR,运行很好的啊!

&nbsp; &nbsp;&nbsp; &nbsp;可能这里面真还有啥问题。咱们多留意吧,有啥情况望及时交流!

2407中用了刘和平书中的有关SCI的例子,就是不能进中断,IFR也只是在初始化中清的,有人说SCI中断本身就有问题,建议用查询法,是这样吗?请各位指点一下吧

SCI_FLAG .usect \".data0\",1 ;SCI标志寄存器
TXD_PTR .usect \".data0\",8 ;发送的数据存放区
RXD_PTR .usect \".data0\",8 ;接收到的数据存放区
.include \"F2407REGS.H\" ;引用头部文件
.def _c_int0
;(1)建立中断向量表
.sect \".vectors\" ;定义主向量段
RSVECT B _c_int0 ;PM 0 复位向量
INT1 B GISR1 ;PM 2 中断优先级1
INT2 B PHANTOM ;PM 4 中断优先级2
INT3 B PHANTOM ;PM 6 中断优先级3
INT4 B PHANTOM ;PM 8 中断优先级4
INT5 B PHANTOM ;PM A 中断优先级5
INT6 B PHANTOM ;PM C 中断优先级6
RESERVED B PHANTOM ;PM E (保留位)
SW_INT8 B PHANTOM ;PM 10 用户定义软件中断 …
SW_INT31 B PHANTOM ;PM 3E 用户定义软件中断
;中断子向量入口定义pvecs
.sect \".pvecs\" ;定义子向量段
PVECTORS B PHANTOM ;保留向量地址偏移量0000h
B PHANTOM ;保留向量地址偏移量0001h

B PHANTOM ;保留向量地址偏移量0005h
B SCI_RX_ISR ;保留向量地址偏移量0006h SCI接收中断
B PHANTOM ;保留向量地址偏移量0007h

B PHANTOM ;保留向量地址偏移量0041h
;(2)主程序:
.text
_c_int0
SETC INTM
CLRC SXM
CLRC OVM
CLRC CNF
LDP #0E0H
SPLK #81FEH,SCSR1 ;CLKIN=6 M,CLKOUT=24 M
SPLK #0E8h,WDCR ;关看门狗
CALL SCI_INIT ;调串口初始化程序
LDP #5H
SPLK #00H,SCI_FLAG ;清发送软件标志位
TXD_LOOP:
LDP #5H
BIT SCI_FLAG,BIT0
BCND TXD_DATA,TC ;SCI_FLAG.0=1则发送数据
B WAIT
TXD_DATA: ;发送N个数据程序
MAR *,AR0
LAR AR0,#TXD_PTR
ADRK #N+1 ;发送N个数据
MAR *,AR4
LACC *+ ;读数据
CMPR 00
BCND TXD_DATA_END,TC ;判数据发送完?
MAR *,AR2
SACL *,AR4 ;数据送SCITXBUF寄存器
XMIT_RDY:
LDP #DP_PF1
BIT SCICTL2,BIT7
BCND XMIT_RDY,NTC ;判发送器是否空?
B TXD_DATA
TXD_DATA_END:
MAR *, AR4
LAR AR4,#TXD_PTR ;恢复发送的数据指针
LDP #5H
SPLK #00H,SCI_FLAG ;清发送软件标志位
WAIT: NOP
B TXD_LOOP
;(3)串行通信初始化程序:
SCI_INIT:
LDP #0E1H
LACL MCRA
OR #03H
SACL MCRA ;配置串行口引脚为特殊功能:TXD、RXD
LDP #DP_PF1
SPLK #000FH,SCICCR ;地址位唤醒模式,8位数据,
;1位停止位,无奇偶校验
SPLK #0007H,SCICTL1 ;接收、发送、内部时钟使能
;SLEEP=1
SPLK #0002H,SCICTL2 ;接收中断使能
SPLK #0001H,SCIHBAUD
SPLK #0038H,SCILBAUD ;波特率为9600
SPLK #0027H,SCICTL1 ;串口初始化完成
LAR AR1,#SCIRXBUF ;接收缓冲寄存器地址
LAR AR2,#SCITXBUF ;发送缓冲寄存器地址
LAR AR3,#RXD_PTR ;接收的数据指针
LAR AR4,#TXD_PTR ;发送的数据指针
LDP #0
SPLK #0001h,IMR ;允许INT1中断
SPLK #0FFFFh,IFR ;清所有中断标志
CLRC INTM ;开总中断
RET
;(4)中断程序
GISR1: ;优先级INT1中断人口
;保护现场
LDP #0E0H
LACC PIVR,1;读取外设中断向量寄存器(PIVR),并左移一位
ADD #PVECTORS ;加上外设中断人口地址
BACC ;跳到相应的中断服务子程序
SCI_RX_ISR: ;接收中断服务程序
LDP #DP_PF1
MAR *,AR1
BIT SCICTL1,BIT2
BCND RXD_DATA,NTC ;SLEEP=0,接收数据
LACC * ;读入地址
SUB #0AAH
BCND TXD_FLAG,EQ ;接收到的地址为AAH,则发送数据
SUB #0001H
BCND SCI_RX_END,NEQ ;地址错误,退出中断
SPLK #0033H,SCICTL1 ;地址为ABH,则清SLEEP=0
;表示准备接收数据
B SCI_RX_END
TXD_FLAG: ;置发送标志
LDP #5H
SPLK #01H,SCI_FLAG
B SCI_RX_END
RXD_DATA: ;接收N个数据
LACC *,AR3 ;读入数据
SACL *+,AR0 ;保存数据
LAR AR0,#RXD_PTR
ADRK #N
MAR *,AR3
CMPR 00
BCND SCI_RX_END,NTC ;判是否接收完
LAR AR3,#RXD_PTR ;恢复接收的数据指针
SPLK #0037H,SCICTL1 ;置SLEEP=1表示准备接收地址
SCI_RX_END: ;中断返回
;恢复现场
CLRC INTM ;开总中断
RET
;(5)假中断程序
PHANTOM
KICK_DOG ;复位看门狗
RET
END

终于找到原因了,是语句位置的关系,把“SPLK #0002H,SCICTL2 ;接收中断使能”放后面就可以了

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top