Помогите разобраться с crc ccitt

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
mas_43
Родился
Сообщения: 6
Зарегистрирован: Сб авг 30, 2008 10:41:49
Контактная информация:

Помогите разобраться с crc ccitt

Сообщение mas_43 »

Добрый вечер.
У меня такая проблема пытаюсь заставить мк работать по rs 485, есть определенный протокол
в отправляемом пакете надо посчитать контрольную сумму. Для подсчёта контрольной суммы используется 16-ти битная циклическая контрольная сумма стандарта CRC_CCITT ( полином $1021 , x^16 + x^15 + x^2 + 1)

Пример отсылаемого пакета
2D старт бит
0F адрес
67 …..
07……
01……
6D младший байт контрольной суммы
6A старший байт контрольной суммы


Вот функция подсчета crc которую я использую


int calcrc(unsigned char *ptr, int count) //Функция подсчета crc
{unsigned short crc;
unsigned char i;

crc = 0;

while (--count >= 0)
{
crc = crc ^ (unsigned short)*ptr++ << 8;
i = 8;
do
{
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
} while(--i);
}
return (crc);
}
Функция возвращает только младший байт контрольной суммы.
Как получить старший байт ??????????????????????
Подскажите пожалуйста
Реклама
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Re: Помогите разобраться с crc ccitt

Сообщение coredumped »

Тут нужно посмотреть, что означает "unsigned short" в сандартной библиотеке Вашего компилятора, возможно это 8-битное число. Это самая распространенная проблема портирования кода - у каждого компилятора свои понятия размерности данных. Я всегда использую определения для переменных вида uint8_t, uint16_t, int8_t итд, чтоб избежать подобных проблем. Попробуйте заменить "unsigned short" на "uint16_t" и может все станет ок? Не забудьте добавить #include <stdint.h> - там содержатся описания этих типов.
Все будет только лучше, в крайнем случае - хуже.
Реклама
mas_43
Родился
Сообщения: 6
Зарегистрирован: Сб авг 30, 2008 10:41:49
Контактная информация:

Re: Помогите разобраться с crc ccitt

Сообщение mas_43 »

я использую code vision c uint16_t не чего не изменилось вот текст программы

#include <mega32.h>
#include <delay.h>
#include <stdio.h>
#include <stdint.h>
#asm
.equ __lcd_port=0x1B ;PORTA
#endasm
#include <lcd.h>
#define buffer_size 30 //размер буфера


unsigned char buffer[buffer_size]; //сам буфер
unsigned char buffer_count; //количество байт в буфере
unsigned char start = 0x2d;
unsigned char adress = 0x0f;
unsigned char indx = 0x67;
unsigned char dlina = 0x07;
unsigned char comanda = 0x01;
unsigned char k;
unsigned char t=0;
unsigned int crc;
//int *ptn=&buffer[buffer_size];


void add_to_buffer(char c) //ф-ия добавление байта в буфер
{
buffer[buffer_count]=c; //добавляем
if (buffer_count<buffer_size) //проверям не вылезло ли за размер
buffer_count++; //если нет то увеличиваем
c=0;
};




char transmit_buffer() //отсылаем буфер
{
char k;
k=0;
while ((buffer_count--)!=0) //цикл отсылки
putchar(buffer[k++]); //непосредственно отправка в ком порт ну или замени на свой UDR + задержка или проверка готовности
};


void form_comand (void)
{
add_to_buffer(start);
add_to_buffer(adress);
add_to_buffer(indx);
add_to_buffer(dlina);
add_to_buffer(comanda);

}










int calcrc(unsigned char *ptr, int count) //Функция подсчета crc
{
uint16_t crc;
unsigned char i;

crc = 0;

while (--count >= 0)
{
crc = crc ^ (uint16_t)*ptr++ << 8;
i = 8;
do
{
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
} while(--i);
}
return (crc);
}












void main(void)
{
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
ACSR=0x80;
SFIOR=0x00;
lcd_init(16);
lcd_clear(); // очищаем дисплей



while (1)
{
char text[16];
form_comand ();
crc=calcrc(buffer,5);

while ((buffer_count--)!=0)
{
//lcd_gotoxy(t,0);//высчитываем положение курсора

k=crc;
sprintf(text,"%u",k); // форматирование строки
lcd_puts(text);
buffer[t++];

delay_ms(1000);
}
t=0;
delay_ms(2000);
};
}

может это из за того что я значение на lcd вывожу, ошибка при формировании строки ?
k=crc;
sprintf(text,"%u",k); // форматирование строки
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Re: Помогите разобраться с crc ccitt

Сообщение coredumped »

У меня нет CV, поэтому могу помочь только теоретически.
Вы уверены, что у CV int имеет размерность 16 бит, а не 8? Я уже на подобные грабли наступал раньше.
Опишите функцию как uint16_t calcrc(uint8_t *ptr, int16_t count) - так все предельно однозначно.
Все будет только лучше, в крайнем случае - хуже.
Реклама
Эиком - электронные компоненты и радиодетали
qwerky
Мучитель микросхем
Сообщения: 487
Зарегистрирован: Пт июн 12, 2009 19:17:35
Контактная информация:

Re: Помогите разобраться с crc ccitt

Сообщение qwerky »

Вот пример рабочего кода:

Код: Выделить всё

// CRC16 CCIT (''=0x1D0F; 'A'=0x9479; '123456789'=0xE5CC;)
#define CRC16_CCIT_INIT 0xffff
#define CRC16_CCIT_POLY 0x1021
#define inc_crc16_ccit_upd(data, crc_prev) { \
    U8 cnt_bits, flag_xor; \
    for (cnt_bits = 8; cnt_bits; cnt_bits--) { \
        flag_xor = (crc_prev >> 8) & 0x80; \
        crc_prev <<= 1; \
        if (data & 0x80) crc_prev |= 1; \
        if (flag_xor) crc_prev ^= CRC16_CCIT_POLY; \
        data <<= 1; \
    } \
}
U16 crc16_ccit_upd(U8 data, U16 crc_prev);
#define inc_crc16_ccit_augment(crc_prev) { \
    U8 cnt_bits, flag_xor; \
    for (cnt_bits = 16; cnt_bits; cnt_bits--) { \
        flag_xor = (crc_prev >> 8) & 0x80; \
        crc_prev <<= 1; \
        if (flag_xor) crc_prev ^= CRC16_CCIT_POLY; \
    } \
}

/*CRC16 CCIT (right method)*/
U16 crc16_ccit_upd(U8 data, U16 crc_prev) {
    inc_crc16_ccit_upd(data, crc_prev);
    return(crc_prev);
}

U16 crc16_ccit_augment(U16 crc_prev) {
    inc_crc16_ccit_augment(crc_prev);
    return(crc_prev);
}

U16 crc16_ccit_buf(U8 *buf, U16 buf_size, U16 crc_prev) {
    while (buf_size) {
        crc_prev = crc16_ccit_upd(*buf, crc_prev);
        buf++;
        buf_size--;
    }
    return(crc_prev);
}


Реклама
mas_43
Родился
Сообщения: 6
Зарегистрирован: Сб авг 30, 2008 10:41:49
Контактная информация:

Re: Помогите разобраться с crc ccitt

Сообщение mas_43 »

Огроменное СПАСИБО !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

надо было еще

unsigned char k;
unsigned int crc;

сделать

int16_t k;
int16_t crc;

и все заработало

правда начало идет старший бит а потом младший но это не существенно главное что считает
еще раз БОЛЬШОЕ СПАСИБО.
Реклама
Аватара пользователя
ds1307
Грызет канифоль
Сообщения: 260
Зарегистрирован: Чт янв 13, 2011 18:54:29
Откуда: Минск

Re: Помогите разобраться с crc ccitt

Сообщение ds1307 »

Предлагаю табличную реализацию. Идея не моя, нашел на просторах. Работает быстрее чем програмная.
Вложения
crc16st.h
(2.58 КБ) 676 скачиваний
Учиться, учиться, ...
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»