打印
[STC单片机]

可以在子函数中调用中断函数吗?

[复制链接]
8159|40
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cellagent|  楼主 | 2013-10-23 09:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
如题。单片机采用查询方式从串口接收一个字符,不同的字符执行不同的中断。我知道中断是不能主动调用的,只能由系统调用,所以设想是所用的中断设置一个启动标志,单片机接收到不同的字符时将对应的启动标志置1,然后系统调用该中断。请问这样可取吗?或者有什么好的方式?

相关帖子

沙发
dirtwillfly| | 2013-10-23 09:29 | 只看该作者
没见过这样用的。

使用特权

评论回复
板凳
cellagent|  楼主 | 2013-10-23 09:32 | 只看该作者
dirtwillfly 发表于 2013-10-23 09:29
没见过这样用的。

谢谢你的回复,请问你的经验是怎样的?

使用特权

评论回复
地板
NE5532| | 2013-10-23 09:34 | 只看该作者
cellagent 发表于 2013-10-23 09:32
谢谢你的回复,请问你的经验是怎样的?

小心内外兼用,造成函数重入的问题,结果就是当机或者数据破坏。中断内外实在要处理相同的事情,应该用标志来进行临界资源保护,也可以通过标志传递到主循环里来做。

使用特权

评论回复
5
cellagent|  楼主 | 2013-10-23 09:37 | 只看该作者
NE5532 发表于 2013-10-23 09:34
小心内外兼用,造成函数重入的问题,结果就是当机或者数据破坏。中断内外实在要处理相同的事情,应该用标 ...

小白,老实说你这段话我需要好好去理解。

使用特权

评论回复
6
ayb_ice| | 2013-10-23 09:40 | 只看该作者
中断是硬件行为,不要去人为调用,可以设定中断标志触发中断

使用特权

评论回复
7
dirtwillfly| | 2013-10-23 09:55 | 只看该作者
一般情况是,用串口中断负责接收字符。然后再主程序中判断字符,并根据不同的字符调用子函数

使用特权

评论回复
8
cellagent|  楼主 | 2013-10-23 10:05 | 只看该作者
ayb_ice 发表于 2013-10-23 09:40
中断是硬件行为,不要去人为调用,可以设定中断标志触发中断

谢谢你的回复,我也是这么想的。我的用途是单片机A从串口接收到字符'a'时发送一段方波,单片机B测量其中一段高定平的宽度在a~b范围内时led闪烁。串口与发送方波都需要用到定时器。
void InitUart()           //串口初始化
{
      SCON = 0x5a;                        //8 bit data ,no parity bit
      TMOD = 0x20;                        //T0 as 8-bit auto reload
      TH1 = TL1 = -(FOSC/12/32/BAUD);    //Set Uart baudrate
      TR1 = 1;
}

void initTX()   //方波发送程序初始化
{  
//TX=1;        
TMOD=0x01;        //定时器T0工作于方式1,16位计数器
TH0=0x00;
TL0=0x00;
ET0=1;                //定时器0中断允许
EA=1;               
}
这样初始化会互相影响吗?反正B的led不闪。后来我用delay函数替换定时器,在proteus中产生了近似的波形,并且仿真中B的led闪,但是实物中B的led仍旧不闪。delay函数是纯粹的子函数,那为什么B的led不闪呢?是不是因为delay和中间的指令导致总延时变化而改变了波形,于是与范围a~b不匹配呢?


使用特权

评论回复
9
cellagent|  楼主 | 2013-10-23 10:13 | 只看该作者
dirtwillfly 发表于 2013-10-23 09:55
一般情况是,用串口中断负责接收字符。然后再主程序中判断字符,并根据不同的字符调用子函数 ...

我之前就是按照你说的“用串口中断负责接收字符。然后再主程序中判断字符,并根据不同的字符调用子函数”,对于子函数又涉及到中断的情况,例如子函数测外部脉冲的宽度,这属于中断嵌套了,我尝试过,看不到效果又嫌麻烦,后来把串口接收字符改为查询方式。单片机同一时间只能干一件事,不同指令下任务的跳转用查询方式显得麻烦又呆滞,总觉得中断方式不甚了解、很复杂,纠结啊!

使用特权

评论回复
10
ayb_ice| | 2013-10-23 10:21 | 只看该作者
这种要求对51MCU没有什么难度的

使用特权

评论回复
11
dirtwillfly| | 2013-10-23 10:26 | 只看该作者
cellagent 发表于 2013-10-23 10:13
我之前就是按照你说的“用串口中断负责接收字符。然后再主程序中判断字符,并根据不同的字符调用子函数” ...

接收到字符后,使能相应的中断就行啊。而且定时器也不是只有一个

使用特权

评论回复
12
speme| | 2013-10-23 10:48 | 只看该作者
本帖最后由 speme 于 2013-10-23 10:49 编辑

感觉有点系统的样子。
但这么个搞法有个问题,中断A时,B又中断了。
想了下,应该不会,触发中断是查询产生的。

使用特权

评论回复
13
giant0113| | 2013-10-23 10:59 | 只看该作者
支持

使用特权

评论回复
14
shujie418| | 2013-10-23 11:08 | 只看该作者
支持下

使用特权

评论回复
15
w522930954| | 2013-10-23 11:15 | 只看该作者
越搞越复杂,想多了。。

使用特权

评论回复
16
江枫渔火| | 2013-10-23 12:17 | 只看该作者
可以调用中断函数。跟普通函数一样处理就行了。

使用特权

评论回复
17
JasonWangSE| | 2013-10-23 13:19 | 只看该作者
应该是可以的吧,将单片机A的timer0和timer1都初始化好,方波发生器用timer0,初始化时处于关闭状态;串口用timer1做波特率发生器。串口用中断模式,在中断处理中,判断如果收到的字符为'a',则开启timer0。关键是看单片机B检测高电平你是用什么方法处理了。比如将送出的方波信号接外部中断INT0,反向后接INT1,外部中断沿触发。在B中INT1的中服用来开启定时器,INT0的中服用来关闭定时器并检查是否在a~b之间,如果是开始闪烁LED的处理,如果不是清零定时器等待下一个高电平。我觉得LED不闪烁可能是单片机B对电平的检测问题,也可能是LED闪烁程序的问,可以在判断a~b成立后输出个电平试试看。

使用特权

评论回复
18
cellagent|  楼主 | 2013-10-23 14:50 | 只看该作者
发一个子函数开启中断的测试程序,可用。
#include <stc12c5a60s2.h>
#include <intrins.h>
#define   FOSC    11059200L
#define   BAUD    9600

sbit start = P2^1;        //用线连至P3.2
BYTE command;
BYTE led = 0xfe;         //用于P1口led的显示

void InitUart()
{
          SCON = 0x5a;                        //8 bit data ,no parity bit
      TMOD = 0x20;                        //T0 as 8-bit auto reload
      TH1 = TL1 = -(FOSC/12/32/BAUD);    //Set Uart baudrate
          TR1 = 1;
}

void RecvData(void)          //查询方式接收命令
{
while(!RI);
        RI=0;
command =SBUF;
}

void SendData(BYTE d)                  //发送一个字节的数据,形参d即为待发送数据。
{
while(!TI);
        TI=0;
SBUF=d; //将数据写入到串口缓冲
}
void myEXO() interrupt 0 using 1
{
//led = led >>1;         //有可能太快,眼睛看不到效果
//P1 = led;
SendData('& ');
EA = 0;
}

void main()
{
IT0 = 0;  //低电平触发外部中断0
EX0 =1;
//EA = 1;
//start = 0;
InitUart();
while(1)
{
RecvData();
if(command == 'a')
        {
        SendData('a');
        EA = 1;
        }
if(command == 'b')
        {
        SendData('b');
        }
}
}
测试结果如图。


使用特权

评论回复
19
一切会如旧| | 2013-10-23 15:15 | 只看该作者
cellagent 发表于 2013-10-23 10:13
我之前就是按照你说的“用串口中断负责接收字符。然后再主程序中判断字符,并根据不同的字符调用子函数” ...

子函数涉及到中断,但这个时候串口中断函数已经结束了啊,何来的中断嵌套

使用特权

评论回复
20
gchy23| | 2013-10-23 15:29 | 只看该作者
我看糊涂了,单片机A:接收数据,发送方波
单片机B:接收方波,发送方波(LED)。不就是实现这两个功能吗?怎么大家搞那么复杂,还是我的理解有误?

使用特权

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

本版积分规则

19

主题

171

帖子

3

粉丝