CRC16

Başlatan mihri, 07 Şubat 2013, 17:38:50

mihri

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
"Eppur si muove!"

Murat Mert

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?
mert07

kantirici


Mr.Java

sanırım haberleşmede kullanılıyor ve verinin size ait olup olmadığını anlıyoruz fakat hesaplaması nasıl hiç anlamadım..

Salih

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.

thenorthstar

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);
    }
}

haydarpasamikro

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;
}
Mikro Dünyası.Haydarpaşa Teknik ve Endüstri Meslek Lisesi Mikrodenetleyici Atl. Şefi

thenorthstar

 Hocam bu crc16 yı yukardaki alıcı ve verici kodlarına nasıl uygularız, yukardaki kodlar üzerinden örnek verebilir misiniz?