Реализация CRC8 на AVR микросхеме

Использование CRC8 для микропроцессоров AVR

Есть такая вещь как циклический избыточный код, очень удобная и практичная. Она не шифрует информацию, как я думал раньше, а всего лишь позволяет выявить ошибки при передачи информации, очень полезная вещь, если вы используете проводную систему передачи информации (проводчки всякие, кабели), т.к. при таком способе передачи информации вероятность, что она будет исковеркана велика. В беспроводном варианте, уже в микросхемах модуля реализованы разные протокол для проверки ошибок при передачи и т.п.

Для подключения к AVRке ноутбука я использую модуль на микросхеме cp2102, он шел в комплекте с беспроводным модулем APC220 и служил для подключения одного из модулей к компу. Вообще можно использовать любой абсолютно модуль USB2UART, можно использовать COM порт — тут это не главное.

Сначало начну с кода на С#. Он очень простой, нашёл я его на каком то старом сайте англоязычном и пользуюсь им давненько. В конце я выложу в формате .zip его код.
Данные код позволяет работать со следующими полиномами:
CRC8 = 0xd5,CRC8_CCITT = 0x07,CRC8_DALLAS_MAXIM = 0x31,CRC8_SAE_J1850 = 0x1D,CRC_8_WCDMA = 0x9b.
Для начало работы с кодом нужно правильно указать настройки com порта:
sp.BaudRate = 9600;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.Parity = Parity.None;
sp.PortName = "COM6";
sp.Handshake = Handshake.None;
sp.ReadTimeout = 500;
sp.WriteTimeout = 500;

Я думаю тут все понятно. Самое главное чтобы настроики на AVRке совпадали с этими, тогда все будет гладко.
private void button1_Click(object sender, EventArgs e)
    {
        byte checksum;
        byte t = 255;   
        byte[] testVal = new byte[]{t};
        CRC8Calc crc = new CRC8Calc(CRC8_POLY.CRC8_CCITT);
        checksum = crc.Checksum(testVal);
        byte[] data_send=new byte[]{t, checksum};
        sp.Write(data_send, 0, data_send.Length);
    }

Ключевые строчки. Тут мы формируем нашу передачу данных. Я в примере использовал только одно значение t и его же передавал, т.е. один символ и его контрольная сумма. Использую полином CRC8_CCITT.
Если мы хотим передавать 3 символа, например переменные a,b,c и их crc, то мы просто пишем так:
byte checksum;
        byte a = 255, b = 20, c = 13;   
        byte[] testVal = new byte[]{a,b,c};
        CRC8Calc crc = new CRC8Calc(CRC8_POLY.CRC8_CCITT);
        checksum = crc.Checksum(testVal);
        byte[] data_send=new byte[]{a, b, c, checksum};
        sp.Write(data_send, 0, data_send.Length);

Все мы отправили 3 символа их их сумму. Просто? Я думаю, да!:)

Теперь поработаем с кодом для AVR камня. Я использовал камень atmega8 8Mhz.
Код для него я выложу в конце в .zip формате. Сразу говорю FIFO буфер я взял c сайта chipenable.ru. Он мне очень понравился, чем то похож на код для Arduino для работы с com портом.

Сначала настроим работу USART в камушке
void USART_Init(void)
{
  UBRRH = 0;
  UBRRL = 51; //скорость обмена 9600 бод
  UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN); //разр. прерыв при приеме и передачи, разр приема, разр передачи.
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //размер слова 8 разрядов
}


Теперь перейдем к главному коду. Я писал раньше что я принимаю только 1 символ значения и его crc, так и у меня в коде все.

int main (void)
{
USART_Init();
DDRD=0xff;//используем для светодиода, он у нас один на выводах порта D
PORTD=0x00;
uint8_t count = 0; //счетчик для буфера
unsigned char my_crc;
unsigned char my_buffer[2];
sei();
while(1)
{
	if(USART_GetRxCount()>0) //есть символы?
	{
	my_buffer[count] = USART_GetChar();//складываем
	count++;
	if(count==2){//мы выслали символ и его crc, получается нужно 2 зн-я
	my_crc = crc8(0,my_buffer[0]);
		if(my_crc==my_buffer[1]) PORTD|=(1<<3);
		else
		{
			for(int i = 0; i < 2; i++)
			{
			PORTD^=(1<<3);_delay_ms(100); //моргнули
			}
		}
                USART_FlushRxBuf(); //чистим буфер
	}
	}
	
}
return 0;
}

В проекте есть файл crc8.c он работает с полиномом 0x07. Если вы пересылаете несколько символов и crc, то вместо функции crc8(unsigned char crc, unsigned char data), вы должны использовать crc8_ccitt_block(unsigned char *data, int length).
По-моему все просто, все работает, как часы, сейчас буду с modbus разбираться и если интересно выложу проект.

Я если честно не хотел писать проект этот, но меня смутило что за данную работу некоторые просят, даже требуют 3-4тысячи рублей. За что? Глупо.
Читайте, пользуйтесь на здоровье.
Если найдете ошибки или подскажите где и как переделать код, я буду очень рад :)
Код для AVR — https://www.dropbox.com/s/rp9lzbulqnusppg/CRC8AVR.zip?m
Код для PC — https://www.dropbox.com/s/0bcib6ntpavatd7/crc8_all_poly.zip?m

Комментарии (3)

RSS свернуть / развернуть
+
0
Сделал сам — молодец!
Действительно щас так тяжело найти кодеров под мк?
А ты не думал с компа структуру слать?
Типа:
struct data
{
int left_speed, right_speed;
int light_intensity;
};

data d = {0,0,0};
d.left_speed = 100;
и тд…
Получается гибко и понятно. И сделать так, чтобы любого размера можно было структуру послать.
Спасибо за материал, пригодится!
avatar

spirit

  • 3 марта 2013, 16:57
+
0
Хотя если тебе надо один байт отправить, то… Ну как идея для модернизации сойдет :)
avatar

spirit

  • 3 марта 2013, 16:59
+
0
Да пока не думал:) Но задумался, на днях напишу, мне сейчас интересно Modbus подключить. И хочу написать код для Qt C++ для CRC8, а то я вообще не нашёл его в интернете.
avatar

easytech

  • 3 марта 2013, 17:43

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.