我们在 8051 汇编中的固件项目遇到问题。它用于嵌入式系统,现在需要适应硬件的变化。它包含一个子例程,该子例程从移位寄存器中顺序读取位并将它们放入固定长度的数据段中。然后,这些位将用作计算的基础,计算过于复杂,无法在本文中描述。由于硬件的变化,我们不再按顺序获取这些位。顺序已颠倒,每八个块都按照复杂的逻辑进行排列。我们在适应装配体中的新位顺序时遇到了问题。
如果在 C: 中实现,原始子例程大致如下所示:
char TimeBuffer[LEN];
char DataBuffer[LEN];
for (int i = 0; i < LEN; i++)
{
if (TimeBuffer[i] != 0)
{
DataBuffer[i] == GPIO_Read();
}
}
在 C: 中重新实现如下所示:
char TimeBuffer[LEN];
char DataBuffer[LEN];
int NewIndex;
for (int i = 0; i < LEN; i++)
{
NewIndex = GetNewIndex(i);
if (TimeBuffer[NewIndex] != 0)
{
DataBuffer[NewIndex] == GPIO_Read();
}
}
我们的问题围绕着指针算术。旧的实现只是使用语句
INC DPTR
在每个循环周期后移动到两个数据段中的下一个字节。新的实现要求我们在每个循环周期开始时重新初始化两个数据段的 DPTR。此重新初始化包括首先调用计算新索引的子例程。然后这个新索引被添加到两个数据段的起始地址。
我们已经实现了这个新解决方案,它在 Keil uVision 2 中没有给我们带来任何错误或警告。但是它没有给我们带来预期的结果。由于我们无法在 IDE 中调试项目,因此只能编译新版本的固件,然后看看它在嵌入式设备上运行时会做什么。
我们尝试的最后一件事是删除为我们提供新索引的子例程的 CALL,因为我们想排除该子例程作为故障点。我们现在向指针添加一个值,而不是新索引,该值在每个循环周期后简单地增加。我们期望看到的结果是,它的行为就像原始实现一样。然而,它的行为方式与仍然具有子例程调用并使用其结果的版本相同。
我们现在怀疑我们将索引添加到指针的方式存在一些根本性错误。我们已经仔细检查了两次和三次,但找不到错误。这是我们想寻求帮助的地方。这些是 8051 组件中原始版本的相关部分:
MOV DPS,#1
MOV DPTR,#DataBuffer
MOV DPS,#0
mov dptr,#TimeBuffer
mov R0,LEN
readD:
MOV C,P1.1 ; read data pin of shift register
JNC shiftD
MOV DPS,#0
movx a,@dptr
JNZ shiftD
MOV DPS,#1
movx a,@dptr
INC ACC
MOVX @DPTR,A
shiftD:setb P1.0 ; clock pin high of shift register
clr P1.0 ; clock pin low of shift register
MOV DPS,#0
inc dptr
MOV DPS,#1
INC DPTR
djnz R0,readD
这就是我们最近所做的更改的样子:
;MOV DPS,#1
;MOV DPTR,#DataBuffer
;MOV DPS,#0
;mov dptr,#TimeBuffer
mov R0,LEN
mov R1,#0h
leseD:
MOV R7,REG1
MOV DPS,#1
MOV DPTR,#DataBuffer
MOV A,DPL
ADD A,R7
MOV DPL,A
MOV A,DPH
ADDC A,#0h
MOV DPH,A
MOV DPS,#0
mov dptr,#TimeBuffer
MOV A,DPL
ADD A,R7
MOV DPL,A
MOV A,DPH
ADDC A,#0h
MOV DPH,A
MOV C,P1.1 ; read data pin of shift register
JNC shiftD
MOV DPS,#0
movx a,@dptr
JNZ shiftD
MOV DPS,#1
movx a,@dptr
INC ACC
MOVX @DPTR,A
shiftD:setb P1.0 ; clock pin high of shift register
clr P1.0 ; clock pin low of shift register
;MOV DPS,#0
;inc dptr
;MOV DPS,#1
;INC DPTR
inc R1
djnz R0,readD
您能否指出您在计算指针的部分或其他地方发现的任何错误?
同时我们自己找到了解决方案。由于平台限制,我们公司没有人知道这种实施方式是不可能的。事实证明,虽然您可以通过将新值移入 DPS 来切换 DPTR 所指的数据段,但 DPL 和 DPH 不受此影响,并且始终指向第一个数据段。因此,我们总是在不知不觉中写入 TimeBuffer。在我们通过嵌入式设备上的串行端口将指针的值发送到终端仿真器后,我们发现了这一点。
无论如何感谢您的支持!