一个极其奇特的编译器问题

问题描述 投票:0回答:1

我已经用 C 语言编写了 PIC16F1947 的代码。我使用以下代码:

  • MPLAB IDE 8.73
  • 高科技C编译器9.81

部分代码处理来自PC的数据。我从 PC 发送的特定数据包是 325 字节。该数据包如下所示:

data:  0, 64, 1, 0, 255, 255, 255, ... (all 255) ..., 255,   1
index: 0   1  2  3    4    5    6                     323  324

数据包的内容显示为 8 位十进制值(8 位无符号整数)。微控制器将其存储在

unsigned char
:

数组中
unsigned char _command_mgr_buff[330];

unsigned char
是 PIC16F 的 8 位无符号整数。

数据包的最后一个字节,即索引324,是数据包的校验和。它是索引 1 到 323 的总和,包括 1 和 323。计算此校验和的 PC 代码(C# 中)如下:

allCertPages[324] = 0;
for (int i = 1; i <= 323; i++)
{
    allCertPages[324] += allCertPages[i];
}

allCertPages
byte[]

微控制器必须验证校验和确实是从 PC 传递的值。这是我为 PIC16F 编写的验证代码,包括一些调试信息:

param0 = _command_mgr_buff[324]; // param0 is unsigned int, 16 bit
param1 = _command_mgr_buff[324]; // param1 is unsigned int, 16 bit

// Checksum verification
for (var = 1; var <= 323; var++) // var is unsigned int, 16 bit
{
    _command_mgr_buff[324] -= _command_mgr_buff[var];
    param1 -= _command_mgr_buff[var];
}

if (!_command_mgr_buff[324])
{
    send_status(CS_BAD_PARAM);
}

想法是从校验和中减去 [1, 323] 范围内的所有值。如果最终值为 0,则校验和正确。否则,如果相减后发现

_command_mgr_buff[324]
非零,则校验和不正确。

在调试模式(以及发布模式)下执行代码后,我在

_command_mgr_buff[324]
中得到非零值(因此
send_status(CS_BAD_PARAM);
被执行并且PC认为有问题),但低字节为零
param1

这怎么可能?!

如果您感兴趣,这里是为非零检查生成的程序集:

  8780                           ;mgr_command.c: 1230: if (!_command_mgr_buff[324])
  8781  0E89  30EA                  movlw   low(8870+0144h)
  8782  0E8A  00D3                  movwf   (??_command_mgr_run+0)^080h+0
  8783  0E8B  3023                  movlw   high(8870+0144h)
  8784  0E8C  00D4                  movwf   (??_command_mgr_run+0)^080h+0+1
  8785  0E8D  0853                  movf    0+(??_command_mgr_run+0)^080h+0,w
  8786  0E8E  0086                  movwf   fsr1l
  8787  0E8F  0854                  movf    1+(??_command_mgr_run+0)^080h+0,w
  8788  0E90  0087                  movwf   fsr1h
  8789                           
  8790  0E91  0881                  movf    indf1,f
  8791  0E92  1D03                  skipz
  8792  0E93  2E95                  goto    u10101
  8793  0E94  2E96                  goto    u10100
  8794  0E95                     u10101:
  8795  0E95  2E9B                  goto    l55070
  8796  0E96                     u10100:
  8797                              line    1232
  8798                              
  8799  0E96                     l55068:    
  8800                           ;mgr_command.c: 1231: {
  8801                           ;mgr_command.c: 1232: send_status(0x11);
  8802  0E96  3011                  movlw   (011h)
  8803  0E97  31B6  2693  3188      fcall   _send_status
  8804                              line    1233
  8805                           ;mgr_command.c: 1233: }
  8806  0E9A  2FE3                  goto    l45048
  8807                              line    1234

这是调试时的截图。请检查右侧的“监视”窗口和第 324 个元素的工具提示。

  • param0
    应该是 1
  • param1 & 0xFF
    应该是 0
  • _command_mgr_buff[324]
    应为 0(工具提示显示 0x0F??!!)

PIC16F Debug

c embedded microcontroller
1个回答
8
投票

如果您的代码如您所说,那么这里的主要问题是您的测试本身:

if (!_command_mgr_buff[324])
{
    send_status(CS_BAD_PARAM);
}

如果结果是您想要的(即零),则您正在发送信号...

这是我不喜欢对非布尔值进行布尔测试的原因之一。 布尔变量的名称通常会提示您正确读取它们捕获的条件,例如

if (isLoaded)
if (!anyErrors)
...但这不适用于数字。 因此,更容易确保您已经获得了想要写出来的语义:

if (_command_mgr_buff[324] != 0) 
{
    send_status(CS_BAD_PARAM);
}

至于为什么你的调试器给你 0x0F...无法帮助你...我的观点是你处于零分支。您可以尝试一个干净的构建,看看它是否仍然这样说。 (程序的调试符号可能已过时或其他什么?)

© www.soinside.com 2019 - 2024. All rights reserved.