Добрый вечер.
У меня такая проблема пытаюсь заставить мк работать по 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);
}
Функция возвращает только младший байт контрольной суммы.
Как получить старший байт ??????????????????????
Подскажите пожалуйста
Помогите разобраться с crc ccitt
- Реклама
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: Помогите разобраться с crc ccitt
Тут нужно посмотреть, что означает "unsigned short" в сандартной библиотеке Вашего компилятора, возможно это 8-битное число. Это самая распространенная проблема портирования кода - у каждого компилятора свои понятия размерности данных. Я всегда использую определения для переменных вида uint8_t, uint16_t, int8_t итд, чтоб избежать подобных проблем. Попробуйте заменить "unsigned short" на "uint16_t" и может все станет ок? Не забудьте добавить #include <stdint.h> - там содержатся описания этих типов.
Все будет только лучше, в крайнем случае - хуже.
Re: Помогите разобраться с crc ccitt
я использую 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); // форматирование строки
#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
У меня нет CV, поэтому могу помочь только теоретически.
Вы уверены, что у CV int имеет размерность 16 бит, а не 8? Я уже на подобные грабли наступал раньше.
Опишите функцию как uint16_t calcrc(uint8_t *ptr, int16_t count) - так все предельно однозначно.
Вы уверены, что у CV int имеет размерность 16 бит, а не 8? Я уже на подобные грабли наступал раньше.
Опишите функцию как uint16_t calcrc(uint8_t *ptr, int16_t count) - так все предельно однозначно.
Все будет только лучше, в крайнем случае - хуже.
-
qwerky
- Мучитель микросхем
- Сообщения: 487
- Зарегистрирован: Пт июн 12, 2009 19:17:35
- Контактная информация:
Re: Помогите разобраться с crc ccitt
Вот пример рабочего кода:
Код: Выделить всё
// 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);
}
- Реклама
Re: Помогите разобраться с crc ccitt
Огроменное СПАСИБО !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
надо было еще
unsigned char k;
unsigned int crc;
сделать
int16_t k;
int16_t crc;
и все заработало
правда начало идет старший бит а потом младший но это не существенно главное что считает
еще раз БОЛЬШОЕ СПАСИБО.
надо было еще
unsigned char k;
unsigned int crc;
сделать
int16_t k;
int16_t crc;
и все заработало
правда начало идет старший бит а потом младший но это не существенно главное что считает
еще раз БОЛЬШОЕ СПАСИБО.
Re: Помогите разобраться с crc ccitt
Предлагаю табличную реализацию. Идея не моя, нашел на просторах. Работает быстрее чем програмная.
- Вложения
-
- crc16st.h
- (2.58 КБ) 676 скачиваний
Учиться, учиться, ...


