crc.h
#ifndef __CRC_H
#define __CRC_H
#define CRC_LOOKUP_TABLE
#if defined(CRC_LOOKUP_TABLE)
unsigned int CRC16(unsigned char * data, unsigned char dataLength);
#else
unsigned int CRC16(unsigned char *ptr, signed char count);
#endif
#endif
crc.c
#include "crc.h"
#if defined(CRC_LOOKUP_TABLE)
const rom unsigned int CRC16Table[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
unsigned int CRC16(unsigned char * data, unsigned char dataLength)
{
unsigned int crc;
unsigned char i;
crc = 0;
for(i=0;i<dataLength;i++)
{
crc = (crc << 8) ^ CRC16Table[(crc>>8) ^ *data++];
}
return crc;
}
#else
unsigned int CRC16(unsigned char *ptr, signed char count)
{
unsigned int crc;
unsigned char i;
crc = 0;
while(--count >= 0 )
{
crc = crc ^ ((unsigned int) *ptr++ << 8);
for(i = 0; i < 8; i++)
{
if( crc & 0x8000 )
{
crc = (crc << 1) ^ 0x1021;
}
else
{
crc = crc << 1;
}
}
}
return crc;
}
#endif
S.A.
Hocam bu tür tablolarda CRC nasıl hesaplanır diğer formüllü olanda gidecek byte sayısı, crc=65535 bti kaydırma vb. formüle tabi tutularak yapılıyor buda pic için işlem zaman kaybı ve birazda kasma oluyor bence.
Sanki tablolu daha kolay gibi ama nasıl yapılıyor bir anlatırmısınız?
hocam bu nedir?
sanırım haberleşmede kullanılıyor ve verinin size ait olup olmadığını anlıyoruz fakat hesaplaması nasıl hiç anlamadım..
Endüstriyel cihazlarda verilerin doğru gönderilip gönderilmediğini kontrol amacıyla kullanılır.
Bir cihaz verilerini göndermeden önce, göndereceği tüm baytlara CRC16 algoritmasını uygular.
Ve elde ettiği iki baytı gönderdiği verilerin sonuna ekler.
Sizde aldığınız baytlara aynı şekilde CRC16 algoritmasını uygularsınız. Cihazdan gelen CRC16 sonucu ile sizin elde ettiğiniz
sonuç birbirini tutuyorsa aldığınız veriler doğru demektir.CRC16 sıkça kullanılır.
Öğrenmekte fayda vardır.
Merhaba Hocam,
Hocam bu crc16 fonksiyonlarını aşağıdaki kodlara nasıl uygularız, örnek verebilirmisiniz?
Aşağıdaki kodda verici sıcaklığı okuyor ve seri port dan gönderiyor.
Alıcıda kodu alıp if((veri[0]=='&')&&(veri[1]==1)&&(veri[3]=='%')&&(veri[4]=='*') && veri[SerialCounter-1]== '#') bu kısım doğru ise sonucu LCD ye yazıyor ama crc olmadığından bazen saçma değerler yazıyor.
Bu kodlar üzerinden örnek verirseniz sevinirim.
Şimdiden Teşekkür ederim.
Alıcı:
#include <18f452.h>
#device adc=10
#FUSES NOWDT //Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES RESERVED
#use delay(clock=10000000)
#use rs232(baud=2400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include "2x16_4x20_LCD.c"
int SerialCounter =0;
float temp,temp2;
int kontrol=0;
int8 veri[]={0,0,0,0,0,0,0,0,0,0,0};
int16 sunuc=0;
#int_RDA
void RDA_isr(void)
{
char vChar = getc();
if(vChar == '&')
{
SerialCounter = 0;
veri[SerialCounter++] = '&';
}
else
if (veri[0] == '&')
{
veri[SerialCounter++] = vChar;
}
if((veri[0]=='&')&&(veri[1]==1)&&(veri[3]=='%')&&(veri[4]=='*') && veri[SerialCounter-1]== '#')
{
SerialCounter = 0;
Kontrol=1;
}
}
void main()
{
setup_adc(ADC_OFF); // ADC clock frekansı fosc/32
setup_adc_ports(NO_ANALOGS); //RA0/AN0 girişi analog
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL); // Aktif edilen kesmelere izin ver
lcd_init();
delay_ms(500);
lcd_gotoxy(1,1);printf(lcd_putc,"Temp=%3.1f ",temp2);
while(true) // Sonsuz döngü
{
if(Kontrol==1)
{
temp=make32(veri[8],veri[7],veri[6],veri[5]);
temp2=temp/100;
lcd_gotoxy(1,1);printf(lcd_putc,"Temp=%3.1f ",temp2 );
Kontrol=0;
}
}
}
Verici:
#include <18F452.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(clock=10000000)
#use rs232(baud=2400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include "ds18b20.c"
#define Led pin_c0
int SerialCounter =0;
void Uyandir();
int8 Data[]={0,0,0,0,0,0,0,0,0,0,0};
int8 i=0,a=0,b=0;
float temp;
int32 temp2;
int8 sicaklik[4];
int ID=1;
void SORGULA()
{
int v = 0;
data[0]='&';
data[1]=ID;
data[2]='*';
data[3]='%';
Data[4] ='*';
Data[5] =sicaklik[0];
Data[6] =sicaklik[1];
Data[7] =sicaklik[2];
Data[8] =sicaklik[3];
data[9]='#';
data[10]='.';
v = 0;
while (data[v] != '.')
putc(data[v++]);
}
void main()
{
set_tris_a(0x01); // RA0 Giriş olarak yönlendiriliyor
setup_adc(adc_off); // ADC clock frekansı fosc/32
setup_adc_ports(NO_ANALOGS); //RA0/AN0 girişi analog
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
delay_ms(500);
while(TRUE)
{
temp=ds1820_read();
temp = 100*temp;
temp2=temp;
sicaklik[0]=make8(temp2,0);
sicaklik[1]=make8(temp2,1);
sicaklik[2]=make8(temp2,2);
sicaklik[3]=make8(temp2,3);
Delay_ms(100);
sorgula();
Delay_ms(100);
}
}
unsigned char CalculatedCRC(unsigned char *buff, unsigned char num_vals){
unsigned char shift_reg, data_bit, sr_lsb, fb_bit, i, j;
shift_reg = 0;
for (i=0; i < num_vals; i++) // for each byte
{
for(j=0; j < 8; j++) // for each bit
{
data_bit = ( buff >> j ) & 0x01;
sr_lsb = shift_reg & 0x01;
fb_bit = (data_bit ^ sr_lsb) & 0x01;
shift_reg = shift_reg >> 1;
if (fb_bit){
shift_reg = shift_reg ^ 0x8c;
}
}
}
return shift_reg;
}
Hocam bu crc16 yı yukardaki alıcı ve verici kodlarına nasıl uygularız, yukardaki kodlar üzerinden örnek verebilir misiniz?