【发布时间】:2011-12-22 08:45:19
【问题描述】:
我正在为嵌入式设备开发一些固件,该设备使用 16 位 PIC,以 40 MIPS 运行并用 C 语言编程。系统将控制两个步进电机的位置,并始终保持每个电机的步进位置。每个电机的最大位置大约是 125000 步,所以我不能使用 16 位整数来跟踪位置。我必须使用 32 位无符号整数 (DWORD)。电机以每秒 1000 步的速度移动,我设计了固件,以便在 Timer ISR 中处理步数。计时器 ISR 执行以下操作:
1) 将一个电机的当前位置与目标位置进行比较,如果它们相同,则将 isMoving 标志设置为 false 并返回。如果它们不同,则将 isMoving 标志设置为 true。
2) 如果目标位置大于当前位置,向前移动一步,然后增加当前位置。
3) 如果目标位置小于当前位置,则向后移动一步,然后递减当前位置。
代码如下:
void _ISR _NOPSV _T4Interrupt(void)
{
static char StepperIndex1 = 'A';
if(Device1.statusStr.CurrentPosition == Device1.statusStr.TargetPosition)
{
Device1.statusStr.IsMoving = 0;
// Do Nothing
}
else if (Device1.statusStr.CurrentPosition > Device1.statusStr.TargetPosition)
{
switch (StepperIndex1) // MOVE OUT
{
case 'A':
SetMotor1PosB();
StepperIndex1 = 'B';
break;
case 'B':
SetMotor1PosC();
StepperIndex1 = 'C';
break;
case 'C':
SetMotor1PosD();
StepperIndex1 = 'D';
break;
case 'D':
default:
SetMotor1PosA();
StepperIndex1 = 'A';
break;
}
Device1.statusStr.CurrentPosition--;
Device1.statusStr.IsMoving = 1;
}
else
{
switch (StepperIndex1) // MOVE IN
{
case 'A':
SetMotor1PosD();
StepperIndex1 = 'D';
break;
case 'B':
SetMotor1PosA();
StepperIndex1 = 'A';
break;
case 'C':
SetMotor1PosB();
StepperIndex1 = 'B';
break;
case 'D':
default:
SetMotor1PosC();
StepperIndex1 = 'C';
break;
}
Device1.statusStr.CurrentPosition++;
Device1.statusStr.IsMoving = 1;
}
_T4IF = 0; // Clear the Timer 4 Interrupt Flag.
}
目标位置在收到移动请求时在主程序循环中设置。 SetMotorPos 行只是用于打开/关闭特定端口引脚的宏。
我的问题是:有什么办法可以提高这段代码的效率吗?如果位置是 16 位整数,则代码功能正常,但作为 32 位整数,处理过多。该设备必须毫不犹豫地与 PC 通信,并且正如所写的那样,性能会受到明显影响。我真的只需要 18 位数学,但我不知道这样做的简单方法!任何建设性的意见/建议将不胜感激。
【问题讨论】:
-
设备是PIC24HJ128GP204,以防有人感兴趣。
-
编译器生成什么?您正在使用哪些优化标志?
-
只要你只是加减 32 位值,而不是乘法或除法(尤其是不除法),对性能的影响应该很小。在别处寻找您的延迟,它们不是由 32 位加法/增量引起的。
-
@Ben Voigt:将 32 位数字与 16 位数字相减的指令有什么区别?会是两倍吗?
-
取决于指令集是否提供“带进位加法”和相应的“借位减法”指令。如果是这样,它只是一个 add 和 add-with-carry 或一个 sub 和一个 sub-with-borrow ,分别(2条指令)。如果没有,必须模拟借位,这将是一个多一点。另一件事是编译器可能做得很糟糕。即便如此,您的 switch 块似乎更有可能比增量/减量更昂贵。
标签: c performance 32-bit pic 16-bit