Можно вычисление crc рассредоточить по времени уменьшив обшее разовое время на его вычисление . Причем для большинства случаев crc проверка возможна ва самом теле прерывания.
Если готовый код по полиному то что внизу :
Код
ui16 ms_crc16(ui8 *msg_p, ui8 length)
{
ui16 crc;
ui8 msg_ptr, cnt;
crc = 0xffff;
for (msg_ptr = 0; msg_ptr < length; msg_ptr++)
{
crc = crc ^ msg_p[msg_ptr];
for (cnt = 0; cnt < 8; cnt++)
{
if ( crc & 0x0001 == 1 )
{
crc >>= 1;
crc = crc ^ 0xa001; // Reversed 0x8005 polynom
}
else
crc >>= 1;
}
}
return crc;
}
С самымм первым байтом начинаем инициализацию :
Код
rx_crc = 0xffff; // init crc field
производим вычисление промежуточного значения для каждого принятого байта по вызову из тела прерывания
приема:
Код
rx_crc = rx_crc ^ byte; // Calculate crc for one byte
for (cnt = 0; cnt < 8; cnt++) //
{ //
if ( rx_crc & 0x0001 == 1 ) //
{ //
rx_crc >>= 1; //
rx_crc = rx_crc ^ 0xa001; // 0x8005 polynom
} //
else //
rx_crc >>= 1; //
} //
теперь если мы априорно не знаем длину всего pdu заранее нам придется все время держать в памяти три последние значения crc - tak chto po таймауту в режиме rtu выбрать самый старый crc (вычисленный без двух байтов полей crc) .
Конечно на больших скоростях не потянет - но на малых даст вам возможность сэкономить 512 байтов на таблицу
Можно конечно еще поллингом на приеме при записи байта в буфер уарта сделать это не из обработчика прерывания а из основной программы - по идее скорость приема можно увеличить