我已经用 C 语言编写了 PIC16F1947 的代码。我使用以下代码:
部分代码处理来自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
应该是 1param1 & 0xFF
应该是 0_command_mgr_buff[324]
应为 0(工具提示显示 0x0F??!!)如果您的代码如您所说,那么这里的主要问题是您的测试本身:
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...无法帮助你...我的观点是你处于零分支。您可以尝试一个干净的构建,看看它是否仍然这样说。 (程序的调试符号可能已过时或其他什么?)