Don*_*alo 2 c compiler-construction embedded microcontroller
我在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
Run Code Online (Sandbox Code Playgroud)
数据包的内容显示为8位十进制值(8位无符号整数).微商店将其存储在以下阵列中unsigned char
:
unsigned char _command_mgr_buff[330];
Run Code Online (Sandbox Code Playgroud)
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];
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是从校验和中减去[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
Run Code Online (Sandbox Code Playgroud)
这是调试期间截图.请检查右侧的Watch窗口和第324个元素的工具提示.
param0
应该是1param1 & 0xFF
应该是0_command_mgr_buff[324]
应为0(工具提示显示0x0F ?? !!)如果您的代码与您说的一样,那么这里的主要问题是您的测试本身:
if (!_command_mgr_buff[324])
{
send_status(CS_BAD_PARAM);
}
Run Code Online (Sandbox Code Playgroud)
如果结果是您想要的(即零),您将发送信号...
这是我不喜欢非布尔值的布尔测试的原因之一.布尔变量通常具有一些名称,可以让您读取它们正确捕获的条件,例如if (isLoaded)
或if (!anyErrors)
......并且这些名称不适用于数字.所以更容易确保你已经得到了你想要写出来的语义:
if (_command_mgr_buff[324] != 0)
{
send_status(CS_BAD_PARAM);
}
Run Code Online (Sandbox Code Playgroud)
至于为什么你的调试器给你0x0F ...无法帮助你...我的观点只是你在零分支.您可以尝试一个干净的构建,看看它是否仍然这样说.(程序的调试符号可能已过时或其他什么?)