题
我想我可能是具有堆栈溢出问题,或者在我的嵌入式固件代码类似的东西。我是一个新的程序员,从来没有处理有所谓,所以我不知道这是发生了什么或没有。
在固件控制与具有磁铁周围均匀地间隔开并且所述板具有一个霍尔效应传感器,其感测当磁铁是在它的车轮的装置。我的固件操作步进,并且还计算步数,同时监测传感器磁体以便检测如果车轮已经停滞。
我使用在我的芯片(8位,8057 acrh。),以组输出端口来控制电机和用于失速检测定时器中断。失速检测代码看起来像这样...
// Enter ISR
// Change the ports to the appropriate value for the next step
// ...
StallDetector++; // Increment the stall detector
if(PosSensor != LastPosMagState)
{
StallDetector = 0;
LastPosMagState = PosSensor;
}
else
{
if (PosSensor == ON)
{
if (StallDetector > (MagnetSize + 10))
{
HandleStallEvent();
}
}
else if (PosSensor == OFF)
{
if (StallDetector > (GapSize + 10))
{
HandleStallEvent();
}
}
}
此代码被称为每次ISR被触发的时间。 PosSensor是磁传感器。 MagnetSize是步进步骤,它需要获得通过磁场的数量。 GapSize是两个磁体之间的步数。所以我想,如果检测车轮被卡住或者与传感器在磁铁或没有结束的磁铁。
这很长一段时间的伟大工程,但随后一段时间后会发生在第停机事件,因为“StallDetector>(MagnetSize + 10)”,但是当我看到StallDetector的价值是始终围绕220!这是没有意义的,因为MagnetSize始终围绕35所以停机事件应该已经在触发像46,但不知它得到了所有的方式,以220?我不设置在我的代码失速检测其他地方的价值。
你对我怎么能追查这个问题的根源有什么建议?
在ISR看起来像这样
void Timer3_ISR(void) interrupt 14
{
OperateStepper(); // This is the function shown above
TMR3CN &= ~0x80; // Clear Timer3 interrupt flag
}
HandleStallEvent
只设置了几个变量恢复到默认值,以便它可以尝试的又一举措...
#pragma save
#pragma nooverlay
void HandleStallEvent()
{
///*
PulseMotor = 0; //Stop the wheel from moving
SetMotorPower(0); //Set motor power low
MotorSpeed = LOW_SPEED;
SetSpeedHz();
ERROR_STATE = 2;
DEVICE_IS_HOMED = FALSE;
DEVICE_IS_HOMING = FALSE;
DEVICE_IS_MOVING = FALSE;
HOMING_STATE = 0;
MOVING_STATE = 0;
CURRENT_POSITION = 0;
StallDetector = 0;
return;
//*/
}
#pragma restore
解决方案
时PosSensor挥发性?也就是说,你更新PosSensor的地方,或者是直接读取GPIO?
我认为GapSize相当大(> 220?)这听起来像你对我可能有一个竞争条件。
// PosSensor == OFF, LastPosMagState == OFF
if(PosSensor != LastPosMagState)
{
StallDetector = 0;
LastPosMagState = PosSensor;
}
else
{
// Race Condition: PosSensor turns ON here
// while LastPosMagState still == OFF
if (PosSensor == ON)
{
if (StallDetector > (MagnetSize + 10))
{
HandleStallEvent();
}
}
else if (PosSensor == OFF)
{
if (StallDetector > (GapSize + 10))
{
HandleStallEvent();
}
}
}
您应该缓存PosSensor的值一次,做StallDetector ++之后,使事件代码中PosSensor变化,你不开始测试新的价值。
其他提示
这绝对不是堆栈溢出。如果你吹堆栈(溢出的话)你的应用程序只会崩溃。这听起来更像是我们用来调用内存跺脚在我的C ++天。你可能不被访问的存储器位置的StallDetector值通过单独StallDetector变量占用。有可能是代码“跺脚”这个特定存储器位置错误的另一部分。
不幸的是,这种问题是非常难以追查。关于你唯一可以做的就是分离系统(从执行删除)你的代码块,直到你缩小并找到了这个错误。
你有你的系统上筑巢的ISR?可能是沿着启动ISR和增加你的计数线的东西,然后打断它,做一遍。这样做足够的时间和你的中断堆栈会发生溢出。它也可以解释这样的高计数器变量以及
不HandleStallEvent()
“看”的ISR内StallDetector
或者它触发主循环的东西吗?如果它是在主循环,你清除中断位?
或者,你从外面ISR调试看着StallDetector
?然后,重新触发中断的每一次使用正确的值,但执行的次数太多了,你只能看到最后,膨胀的价值。
在第二思想,更可能不必清除中断生成寄存器,而是中断引脚其余由传感器断言。您需要忽略所述中断之后它是由具有原始ISR禁止本身和并重新安装在其中处理1-> 0的转变的第二ISR第一处理直到行取消断言,例如
您也许这时也需要,如果你把它添加防抖动硬件或进行调整。
检查您的参数类型。如果你不是调用者预期的方式不同定义的参数,然后调用你的方法可能会覆盖的空间变量存储在(例如,如果你写的函数期待一个int,但长期是推到堆栈。)
您可以看到什么额外的选项你的调试器支持。在Visual Studio中,例如,可以设置一个“数据断点”,在这里打破当存储器位置的变化(或者被设置为一个特定值,或超过阈值,...)。
如果这样的事情是在你的情况有可能,你可以看到数据发生变化,如果有别人写入内存错误。