Jump to content

    
Sign in to follow this  
6Ф3П

Вычисление CRC

Recommended Posts

Здравствуйте. Буду признателен если спасёте от инвалидности по мозгу.

Среда WinAVR. Вычисляю CRC32 как описано тут http://ru.wikipedia.org/wiki/Crc#CRC-32

// ===================================================
unsigned long CRC32Table[256]  = {0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, итд}
int main(void)
{
  unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int len = 9;
  volatile long crc = 0xFFFFFFFF;
  while (len--)
  {
    crc = (crc >> 8) ^ (CRC32Table[(crc ^ a[9 - len]) & 0xFF]);
  }
  crc = crc ^ 0xFFFFFFFF;

В результате CRC == 0xE1042295 (Эмуляция в AVR студии)

 

Теперь то же самое на Delphi

// ====================================================
procedure TForm1.Button1Click(Sender: TObject);
const
tbl: array [0..255] of integer = ($00000000, $77073096, $EE0E612C, $990951BA, ...);
arr: array [0..8] of byte = (1,2,3,4,5,6,7,8,9);
var
  crc, len: integer;
begin
  len := 9;
  crc := $FFFFFFFF;
  while len > 0 do begin
    crc := (crc shr 8) xor tbl[(crc xor arr[9 - len]) and $FF];
    Dec(len);
  end;
  crc := crc xor $FFFFFFFF;
  label1.Caption := inttostr(crc);
end;

Здесь CRC = $40EFAB9E;

 

Кто виноват, а главное, что делать.

Забыл сказать - с вероятностью 99,9(9) правильный результат в Delphi т. к.

этот алгоритм был использован в старых проектах.

Share this post


Link to post
Share on other sites
Кто виноват, а главное, что делать.

Нулевой байт в C-варианте игнорируется, т.к. len на первом проходе уже равна 8. Плюс считается один байт за границами массива a[].

Исправить можно многими способами. Самый простой и корявый - заменить 9 на 8.

Share this post


Link to post
Share on other sites

Спасибо. Косячок подправил но всё равно что то не то

    for (int i = 0; i < 9; i++)
    {
        crc = (crc >> 8) ^ (CRC32Table[(crc ^ a[i]) & 0xFF]);
    }
    crc = crc ^ 0xFFFFFFFF;

Теперь CRC = 0x15E95EF1

p.s. Если глупости спрашиваю прошу прощения, я с С не очень, а WinAVR второй день юзаю.

Share this post


Link to post
Share on other sites

По поводу volatile совершенно согласен.

Проблема в том что я в студии не могу посмотреть знач. переменной. Объясните пожалуйста в чём дело.

//  ================================================================
long CalculateCRC32Block(unsigned char* buf, unsigned int len)
{
   unsigned long crc = 0xFFFFFFFF;
   while (len--)
   {
        crc = (crc >> 8) ^ pgm_read_dword(&(CRC32Table[(crc ^ *buf++) & 0xFF]));    
   }
   return crc ^ 0xFFFFFFFF;
}

 

Если так

//  ================================================================
int main(void)
{
   unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   volatile unsigned long crc = CalculateCRC32Block(a, 9);

то значение переменной crc в студии не видно

 

Так тоже не видно

//  ================================================================
int main(void)
{
   unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   unsigned long crc = 0;
   crc = CalculateCRC32Block(a, 9);

 

И только так я могу его посмотреть

//  ================================================================
int main(void)
{
  unsigned char a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  volatile unsigned long crc = 0;
  crc = CalculateCRC32Block(a, 9);

 

Может лучше использовать какую-нибудь другую программу для отладки?

Или руки кривые?

Share this post


Link to post
Share on other sites
....

Может лучше использовать какую-нибудь другую программу для отладки?

Или руки кривые?

Не надо =)

Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.

Share this post


Link to post
Share on other sites
Не надо =)

Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.

Ну а map-файл или как он там в GCC называется глянуть можно и ручками посмотреть содержимое нужного

регистра?

 

Share this post


Link to post
Share on other sites

ps

Кто виноват, а главное, что делать.

Забыл сказать - с вероятностью 99,9(9) правильный результат в Delphi т. к.

этот алгоритм был использован в старых проектах.

когда сомневаешься - какой алгоритм считает правильно, а какой нет, см он-лайн калькулятор црц http://www.lammertbies.nl/comm/info/crc-calculation.html

 

строка "01 02 03 04 05 06 07 08 09" и тип данных hex. результат: CRC-32 0x40EFAB9E

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this