函数调用没有返回正确的位置

时间:2017-04-25 17:29:15

标签: c pic

努力应该是一个简单的函数调用和返回(PIC micro,XC16编译器)。返回似乎转到错误的位置,好像程序计数器没有正确存储其值。可能是我手指麻烦。

确定开关状态的功能(如果开关保持闭合,继续输出顺序,否则等待),而不是最好的编程,我知道。

void check()               //check the switch status to continue or stop sequence
{
  if (PORTFbits.RF2==0)    //If the switch is closed then start time check
  {
    __delay_ms(500);
    if (PORTFbits.RF2==0)  //If the switch is still closed after 0.5s then resume sequence
    {
      return ;
    }
  }                         
  check();                 // otherwise loop, wait for next switch close
}

在主函数序列中的一些输出(在while循环中) -

LATDbits.LATD0 = 1;
SaveD = LATD;                 // Save the status of the outputs
check();                      // Check the switch status
__delay_ms(500);
LATD = 0;
LATDbits.LATD1 = 1;
SaveD = LATD;
check();
__delay_ms(500);
LATD = 0;
LATDbits.LATD2 = 1;
check();

正在调用check()函数,但返回返回main中的第一条指令,而不是在函数调用后执行下一条指令。

我在做些傻事吗?

此致 活性

1 个答案:

答案 0 :(得分:1)

你的问题源于这样一个事实,即你的筹码可能会溢出。

考虑你的代码:

void check()               //check the switch status to continue or stop sequence
{
  if (PORTFbits.RF2==0)    //If the switch is closed then start time check
  {
    __delay_ms(500);
    if (PORTFbits.RF2==0)  //If the switch is still closed after 0.5s then resume sequence
    {
      return ;
    }
  }                         
  check();                 // otherwise loop, wait for next switch close
}

如果PORTFbits.RF2 != 0您将立即转到check()的下一个电话。

这意味着在一个或两个指令中,您正在递归(当一个函数调用自身时,名为递归 - 该函数是一个递归函数,它< em> recurses 本身等等。)

因此,在很短的时间内,您可以对check()函数进行数十,数百或数千次调用。

这些调用中的每一个都将调用的返回地址推送到堆栈,从而消耗堆栈空间。最终,正如一些评论者指出的那样,你要么完全崩溃机器,要么强制重置。如您所见,强制重置将重新启动main中的代码。

如上所述,在关闭开关之前,您的代码不会从最外面的check()调用返回。假设这就是你想要的,这里有一些可能有用的代码:

void wait_for_switch()
{
     while (1) {
         if (PORTFbits.RF2 == 0) {  /* Switch is closed. */
             __delay_ms(500);       /* Debounce interval. */
             if (PORTFbits.RF2 == 0) return; /* Still closed? Done! */
         }
         else {
             /* Wait for switch to close. */
             __delay_ms(100);
         }
     }
  }

<强>更新

听说您的编译器没有重新加载交换机位,这让我想到了这个替代方案。我怀疑第一次读取函数中的位是有效的,所以让我们把端口读入函数:

int read_portfbits_rf2() {
    return PORTFbits.RF2;
}

void wait_for_switch()
{
     while (1) {
         if (read_portfbits_rf2() == 0) {  /* Switch is closed. */
             __delay_ms(500);       /* Debounce interval. */
             if (read_portfbits_rf2() == 0) return; /* Still closed? Done! */
         }
         else {
             /* Wait for switch to close. */
             __delay_ms(100);
         }
     }
  }