реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Вычисление CRC, Среда WinAVR
6Ф3П
сообщение Dec 10 2011, 15:42
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 10-12-11
Пользователь №: 68 775



Здравствуйте. Буду признателен если спасёте от инвалидности по мозгу.
Среда 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 т. к.
этот алгоритм был использован в старых проектах.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 10 2011, 16:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(6Ф3П @ Dec 10 2011, 19:42) *
Кто виноват, а главное, что делать.

Нулевой байт в C-варианте игнорируется, т.к. len на первом проходе уже равна 8. Плюс считается один байт за границами массива a[].
Исправить можно многими способами. Самый простой и корявый - заменить 9 на 8.
Go to the top of the page
 
+Quote Post
Konst_777
сообщение Dec 10 2011, 16:24
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 549
Регистрация: 1-06-05
Пользователь №: 5 644



Разберитесь, когда выполняется декремент len в программе на C и когда в программе на Delphi cool.gif

Пока отвечал, Вам уже ответил уважаемый aaarrr.
Go to the top of the page
 
+Quote Post
6Ф3П
сообщение Dec 10 2011, 16:45
Сообщение #4





Группа: Новичок
Сообщений: 6
Регистрация: 10-12-11
Пользователь №: 68 775



Спасибо. Косячок подправил но всё равно что то не то
Код
    for (int i = 0; i < 9; i++)
    {
        crc = (crc >> 8) ^ (CRC32Table[(crc ^ a[i]) & 0xFF]);
    }
    crc = crc ^ 0xFFFFFFFF;

Теперь CRC = 0x15E95EF1
p.s. Если глупости спрашиваю прошу прощения, я с С не очень, а WinAVR второй день юзаю.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 10 2011, 17:10
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Еще crc должен быть unsigned, иначе >> даст расширение знака.
Go to the top of the page
 
+Quote Post
6Ф3П
сообщение Dec 10 2011, 17:22
Сообщение #6





Группа: Новичок
Сообщений: 6
Регистрация: 10-12-11
Пользователь №: 68 775



В ТОЧКУ!!!!!
volatile unsigned long crc = 0xFFFFFFFF;
aaarrr большое спасибо!!!
Теперь CRC как положено 0x40EFAB9E;


Сообщение отредактировал 6Ф3П - Dec 10 2011, 17:23
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 10 2011, 17:31
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(6Ф3П @ Dec 10 2011, 21:22) *
В ТОЧКУ!!!!!

Ну и последний штрих: volatile ему быть совсем не обязательно.
Go to the top of the page
 
+Quote Post
6Ф3П
сообщение Dec 11 2011, 06:57
Сообщение #8





Группа: Новичок
Сообщений: 6
Регистрация: 10-12-11
Пользователь №: 68 775



По поводу 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);


Может лучше использовать какую-нибудь другую программу для отладки?
Или руки кривые?
Go to the top of the page
 
+Quote Post
Petka
сообщение Dec 11 2011, 07:40
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(6Ф3П @ Dec 11 2011, 10:57) *
....
Может лучше использовать какую-нибудь другую программу для отладки?
Или руки кривые?

Не надо =)
Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.
Go to the top of the page
 
+Quote Post
6Ф3П
сообщение Dec 11 2011, 08:02
Сообщение #10





Группа: Новичок
Сообщений: 6
Регистрация: 10-12-11
Пользователь №: 68 775



Спасибо, понял.
Go to the top of the page
 
+Quote Post
WHALE
сообщение Dec 11 2011, 09:06
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Цитата(Petka @ Dec 11 2011, 11:40) *
Не надо =)
Всё просто. Скорее всего компилятор разместил переменную crc в регистре. А если переменная в регистре зачастую GNU отладчик её значение получить не может. volatile заставляет компилятор не оптимизировать обращение к crc и как следствие размещает её в доступной отладчику ram.

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


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 14 2011, 09:21
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



ps
Цитата(6Ф3П @ Dec 10 2011, 21:42) *
Кто виноват, а главное, что делать.
Забыл сказать - с вероятностью 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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 14:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.03606 секунд с 7
ELECTRONIX ©2004-2016