Я написал код для PIC16F1947 на C. Я использую следующее:
- MPLAB IDE 8.73
- HI-TECH C Компилятор 9.81
Часть кода связана с данными, поступающими с ПК. Конкретный пакет, который я посылаю с ПК, составляет 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
- 8-битное целое число без знака для PIC16F.
Последний байт пакета, то есть индекс 324, является контрольной суммой пакета. Это сумма индексов с 1 по 323, включая 1 и 323. Код ПК (в C #), который вычисляет эту контрольную сумму, выглядит следующим образом:
allCertPages[324] = 0;
for (int i = 1; i <= 323; i++)
{
allCertPages[324] += allCertPages[i];
}
allCertPages
является byte[]
.
Микро должен проверить, что контрольная сумма действительно является значением, переданным с ПК. Вот код подтверждения, который я написал для 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);
выполняется, и ПК считает, что что-то не так), но ноль в младший байт 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
Вот скриншот, сделанный во время отладки. Пожалуйста, проверьте окно Watch справа и подсказку для 324-го элемента.
param0
должно быть 1
param1 & 0xFF
должно быть 0
_command_mgr_buff[324]
должно быть 0 (подсказка показывает 0x0F ?? !!)