打印

关于51单片机的中断函数调用问题

[复制链接]
9343|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
logokfu|  楼主 | 2012-3-15 22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我一直不理解,我在中断函数里面调用了一个子函数,为什么调用不了呢。如果我把被调用的那个子程序里面的内容直接写到中断函数里面就可以正常执行。有人说是中断函数里面不能写太长的程序,那为什么直接把子程序的内容写到中断程序里面就管用呢。

相关帖子

沙发
ayb_ice| | 2012-3-16 08:33 | 只看该作者
应该是非重入函数的原因

使用特权

评论回复
板凳
logokfu|  楼主 | 2012-3-16 08:52 | 只看该作者
能详细说下吗。我调用的那个子函数内容很简单。
void turn_off()
{
    P2=0xfe;
}

我把P2=0xfe;直接写到外部中断1函数中就可以运行。这个和重入有关系吗。

使用特权

评论回复
地板
原野之狼| | 2012-3-16 09:01 | 只看该作者
1  中断是否会嵌套,如果会,则需要考虑重入的问题。
2  你所说的函数是否会被前台与后台访问,如果会则需要考虑线程安全问题。不过你这里给出的例子不需要考虑这个。

使用特权

评论回复
5
ayb_ice| | 2012-3-16 09:07 | 只看该作者
具体的这个函数没有问题
把全部代码帖上来

使用特权

评论回复
6
mycomputerliu| | 2012-3-16 15:31 | 只看该作者
完全看不明白是什么东东。

使用特权

评论回复
7
gool| | 2012-3-16 17:08 | 只看该作者
不懂啊

使用特权

评论回复
8
logokfu|  楼主 | 2012-3-16 22:13 | 只看该作者
本帖最后由 **kfu 于 2012-3-16 22:21 编辑
具体的这个函数没有问题
把全部代码帖上来
ayb_ice 发表于 2012-3-16 09:07


我的这个是个用串口发指令,控制小车的程序,出问题的就在红色字体的部分,首先说明下,下面的程序是没有问题的,可为正常运行,我的问题就是 当我把红色部分的代码换成对应的函数时候就不管用了。对应的函数就是左转,右转,后退那几个函数。

#include<at89x51.h>
#include<stdio.h>
#define uchar unsigned char

/***************************************************************************
* DIR1 和 PWM1控制左边电机
* DIR2 和 PWM2控制右边电机
* DIR为方向控制(控制正反转),PWM为使能信号(1为运转,0为停止)
* 下面为左边电机的状态表(右边电机也是如此):
—————————————————————————
     DIR1 PWM1  状态   
—————————————————————————
      0    1  正转  
—————————————————————————
      0    0   停  
—————————————————————————
      1    1  反转
—————————————————————————   
      1    0   停  
—————————————————————————
****************************************************************************/
#define DIR1 P2_0
#define PWM1 P2_1
#define DIR2 P2_2
#define PWM2 P2_3
void delayMS(uchar t);//延时
void go_forward(); //前走
void go_back();//后退
void turn_left();//左转
void turn_right();//右转
void stop(); //停

void main(void)
{
uchar xdata rcvdata[1];
    EA=1;   //开启总中断

SCON = 0x50; //串口方式1,允许接收
TMOD=0X21;
TH1 = 0xFD; //11.0592MHZ 9600 波特率
TL1 = 0xFD;
TR1 = 1; //启动定时器1
EX0=1;    //开启外部中断 0,即P32引脚
IT0=0;         //设置成 低电平触发方式,IT0=1为下降沿触发
   
    PWM1=0;//防止小车上电就开始跑
    PWM2=0;
while(1)
{
  rcvdata[0]=0;
  if(RI)
  {
   rcvdata[0]=SBUF;//把接收到的数据保存
   RI=0;
   SBUF=rcvdata[0];
   if(SBUF=='1')
    go_forward();
   if(SBUF=='2')
    go_back();
   if(SBUF=='3')
    turn_left();
   if(SBUF=='4')
    turn_right();
   if(SBUF=='5')
    stop();
   //把收到的数据通过串口发送出去
   while(!TI);
   TI=0;
  }
}
}
/***************************************************************************
*外部中断 0  C51中断号1    0的优先级最高,关键字"interrupt" , 这是C语言的中断函数表示法
*本中断的响应是P32引脚有低电平触发
****************************************************************************/
void int_0() interrupt 0
{
   // 后退防止碰住障碍物
DIR1=1;
  PWM1=1;
  DIR2=1;
  PWM2=1;

delayMS(1000);
//左转        
  DIR1=1;
  PWM1=1;
  DIR2=0;
  PWM2=1;

delayMS(1000);
//继续向前走
DIR1=0;
  PWM1=1;
  DIR2=0;
  PWM2=1;
delayMS(1000);
   
  
}
void go_forward() //前走
{
DIR1=0;
PWM1=1;
DIR2=0;
PWM2=1;
printf("go_forward");
}
void go_back()//后退
{
DIR1=1;
  PWM1=1;
  DIR2=1;
  PWM2=1;
printf("go_back");
}
void turn_left()//左转
{
  DIR1=1;
  PWM1=1;
  DIR2=0;
  PWM2=1;
  printf("turn_left");
}
void turn_right()//右转
{
  DIR1=0;
  PWM1=1;
  DIR2=1;
  PWM2=1;
  printf("turn_right");
}
void stop()//停
{  
  DIR1=0;
  PWM1=0;
  DIR2=0;
  PWM2=0;
printf("stop");   
}
void delayMS(uchar t)//延时
{
uchar i;
while(t--)
for(i=0;i<120;i++);
}

使用特权

评论回复
9
ayb_ice| | 2012-3-17 08:25 | 只看该作者
哪里一样嘛
不要用printf

使用特权

评论回复
10
logokfu|  楼主 | 2012-3-18 00:40 | 只看该作者
9# ayb_ice

1)我试过了,就是你说的原因。
2)我想知道为什么在中断函数里面不能调用带printf的函数呢

使用特权

评论回复
11
Cortex-M0| | 2012-3-18 04:50 | 只看该作者
9# ayb_ice  

1)我试过了,就是你说的原因。
2)我想知道为什么在中断函数里面不能调用带printf的函数呢
**kfu 发表于 2012-3-18 00:40



printf是非重入函数,不能在中断中嵌套使用。

使用特权

评论回复
12
logokfu|  楼主 | 2012-3-18 20:47 | 只看该作者
12# taishandadi

什么意思,怎么搞

使用特权

评论回复
13
ayb_ice| | 2012-3-19 08:33 | 只看该作者
printf函数不是重入函数
即使是重入函数,在中断中使用也是不明智的
因为这个函数很大,执行时间长。。。

使用特权

评论回复
14
qqfishboy| | 2012-3-19 11:14 | 只看该作者
printf没用~我的程序 多一个printf 就不行  有时候少一个也不行 最后干脆都不用了~直接用
void Uart0_SendString(unsigned char *ptr)
{
        while(*ptr)
        {
                Uart0_SendChar(*ptr++);  // ·¢ËÍÊý¾Ý
        }
}

void Uart0_Send232(int S)
{   
        Uart0_SendChar('0'+S/1000);
        Uart0_SendChar('0'+(S/100)%10);
        Uart0_SendChar('0'+(S/10)%10);
        Uart0_SendChar('0'+S%10);
}

使用特权

评论回复
15
xlsbz| | 2012-4-28 09:10 | 只看该作者
我目前知道的有

(1)我认为我水平一般  所以不敢用  那个reentrant
(2)某个中断里面调用的某个函数 只让这个中断调用 不要在别的地方调用。否则 即便我疏忽了 ,我用的keil会给提示

(3)printf 这个函数 我还不太会用,也不想用,因为printf 这个函数参数个数不一定,我不喜欢用参数个数不一定的函数。  我一般自己写自己的print打印 。

(4)甚至memcpy 和 memcmp我都自己写   可以上网查查 这类函数没有检测覆盖   微软自己都承认这点


希望我说的有帮助  也可能答非所问了

使用特权

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

本版积分规则

76

主题

2646

帖子

7

粉丝