Difference between revisions of "EPEVER 485"

From Public Wiki
Jump to navigation Jump to search
Line 263: Line 263:
 
==Code==
 
==Code==
 
<syntaxhighlight lang="C++" line='line'>
 
<syntaxhighlight lang="C++" line='line'>
 +
 
//#include <SoftwareSerial.h>
 
//#include <SoftwareSerial.h>
 
//const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin
 
//const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin
Line 286: Line 287:
 
   delay(1000);
 
   delay(1000);
 
   Serial.println();
 
   Serial.println();
 
 
 
}
 
}
  
Line 296: Line 295:
 
void loop()  
 
void loop()  
 
{
 
{
  int start_register = 0x903D //binary value of register starting location
 
  int num_registers = 0x0003  //Number of registers, only 16-bit for consistency
 
                              //0x007B is the maximum value
 
  
 +
  Response_size=zerothree(Response,0x9013,0x0003 );
 
   
 
   
  Response_size = onezero(Response, start_register, num_registers, arry, LOW);
 
    if(Response_size==0) Serial.println("Received Error from 0x01");
 
 
 
   Serial.print("Size is  : ");
 
   Serial.print("Size is  : ");
 
   Serial.println(Response_size);
 
   Serial.println(Response_size);
Line 320: Line 314:
 
   {}
 
   {}
 
}
 
}
 
+
// Read coils zeroone - Read up to 2000 coils in a call.
 +
// Requires:
 +
//  byte rs[] : Respose[]
 +
//  int start : starting address
 +
//  int num  : Number of coils between 1..0x07D0
 +
//
 
byte zeroone(byte rs[],int start, int num)
 
byte zeroone(byte rs[],int start, int num)
 
{
 
{
   byte rq[8];  //Always 8 bytes
+
   byte rq[8];  //Always 8 bytes for 0x01
  //int addr;
 
  //int len;
 
 
   short c; //CRC value
 
   short c; //CRC value
 
   byte i, j,sz;  //Counters, size
 
   byte i, j,sz;  //Counters, size
  
   if(num==0 || num>0x7d0)
+
  //If there are no parameters selected or too many, then error, quit.
 +
   if(num==0 || num>0x07d0)
 
   {
 
   {
 
     Serial.println("Illegal quantity of inputs");
 
     Serial.println("Illegal quantity of inputs");
Line 338: Line 336:
 
   rq[0]=DEVICE; //Global device IO
 
   rq[0]=DEVICE; //Global device IO
 
   rq[1]=0x01;
 
   rq[1]=0x01;
   rq[3]=byte(start&0x00FF);
+
   rq[3]=byte(start&0x00FF);     //starting LSB address
   rq[2]=byte((start&0xFF00)>>8);
+
   rq[2]=byte((start&0xFF00)>>8);//starting MSB address
   rq[5]=byte(num&0x00FF);
+
   rq[5]=byte(num&0x00FF);       //number of coils LSB
   rq[4]=byte((num&0xFF00)>>8);
+
   rq[4]=byte((num&0xFF00)>>8); //number of coils MSB
 +
 
 +
  c = CRC16(rq,6);  //Calculate CRC
 +
 
 +
  rq[7]=0x00FF & c; //CRC LSB
 +
  rq[6]=c>>8;      //CRC MSB
  
  c = CRC16(rq,6);
 
  rq[7]=0x00FF & c;
 
  rq[6]=c>>8;
 
  
 +
  //Transmit the Request array onto bus.
 
   for(i=0;i<8;i++)
 
   for(i=0;i<8;i++)
 
   {
 
   {
 
     Serial1.write(rq[i]);
 
     Serial1.write(rq[i]);
 
   }
 
   }
   sz = 5+rq[5];
+
 
   //if((rq[5]%8)!=0 && rq[5]>8) sz++; //Refer to *N at top of Page 12
+
  //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic
 +
  //is needed to ensure a fractional byte always rounds upwards to an additioanl byte
 +
   sz=5+num/8;
 +
   if(num%8>0) sz++;
 +
 
 
   if(sz>BUFS)
 
   if(sz>BUFS)
 
   {
 
   {
Line 363: Line 368:
 
     {
 
     {
 
       rs[i]=Serial1.read();
 
       rs[i]=Serial1.read();
       if(i==1 && rs[i]==0x83) sz=5;
+
       if(i==1 && rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.
 
       i++;
 
       i++;
     }
+
     }  
 
+
  }
 +
  if (rs[1]==0x83)
 +
  {
 +
    Serial.println("Remote system threw an error.");
 +
    return 0;
 
   }
 
   }
 
   c=CRC16(rs,sz-2);
 
   c=CRC16(rs,sz-2);
 
   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
 
   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
 
   {
 
   {
     Serial.println("CRC error in 0x01");
+
     Serial.println("CRC error in 'Read Coils' function 0x01");
 
     return 0;
 
     return 0;
 
   }
 
   }
 
 
   return sz;
 
   return sz;
 
}
 
}
  
 
+
// Read discretes zerotwo - Read up to 2000 discrete inputs in a call.
 +
// Requires:
 +
//  byte rs[] : Respose[]
 +
//  int start : starting address
 +
//  int num  : Number of inputs between 1..0x07D0
 +
//
 
byte zerotwo(byte rs[], int start, int num)
 
byte zerotwo(byte rs[], int start, int num)
 
{
 
{
 
   byte rq[8];  //Always 8 bytes
 
   byte rq[8];  //Always 8 bytes
  //int addr;
 
  //int len;
 
 
   short c; //CRC value
 
   short c; //CRC value
 
   byte i, j,sz;  //Counters, size
 
   byte i, j,sz;  //Counters, size
Line 389: Line 400:
 
   rq[0]=DEVICE; //Global device IO
 
   rq[0]=DEVICE; //Global device IO
 
   rq[1]=0x02;
 
   rq[1]=0x02;
   rq[3]=byte(start&0x00FF);
+
   rq[3]=byte(start&0x00FF); //Starting address LSB
   rq[2]=byte((start&0xFF00)>>8);
+
   rq[2]=byte((start&0xFF00)>>8); //Starting address MSB
   rq[5]=byte(num&0x00FF);
+
   rq[5]=byte(num&0x00FF); //Number of bits LSB
   rq[4]=byte((num&0xFF00)>>8);
+
   rq[4]=byte((num&0xFF00)>>8); //Number of bits MSB
  
 
   c = CRC16(rq,6);
 
   c = CRC16(rq,6);
   rq[7]=0x00FF & c;
+
   rq[7]=0x00FF & c; //CRC LSB written
   rq[6]=c>>8;
+
   rq[6]=c>>8;       //CRC MSB written
 +
 
  
 +
  //Deliver request to device
 
   for(i=0;i<8;i++)
 
   for(i=0;i<8;i++)
 
   {
 
   {
 
     Serial1.write(rq[i]);
 
     Serial1.write(rq[i]);
 
   }
 
   }
   sz = 5+rq[5];
+
 
 +
  //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic
 +
  //is needed to ensure a fractional byte always rounds upwards to an additional byte
 +
   sz=5+num/8;
 +
  if(num%8>0) sz++;
 +
 
 
   if(sz>BUFS)
 
   if(sz>BUFS)
 
   {
 
   {
Line 408: Line 426:
 
     return 0;
 
     return 0;
 
   }
 
   }
 +
 
 +
  //Listen for response
 
   for(i=0;i<sz;)
 
   for(i=0;i<sz;)
 
   {
 
   {
   
 
 
     if (Serial1.available())            //Data from the Slave is available
 
     if (Serial1.available())            //Data from the Slave is available
 
     {
 
     {
 
       rs[i]=Serial1.read();
 
       rs[i]=Serial1.read();
 +
      if(i==1 && rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.
 
       i++;
 
       i++;
     }
+
     }  
 +
  }
 +
  if (rs[1]==0x83)
 +
  {
 +
    Serial.println("Remote system threw an error.");
 +
    return 0;
 
   }
 
   }
 +
 +
  //Verify CRC code
 
   c=CRC16(rs,sz-2);
 
   c=CRC16(rs,sz-2);
 
   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
 
   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
Line 426: Line 453:
 
}
 
}
  
 +
// Read Holding Registers zerothree - Read up to 125 registers in a call.
 +
// Requires:
 +
//  byte rs[] : Response[]
 +
//  int start : starting address
 +
//  int num  : Number of inputs between 1..0x0007D
 +
//
 +
//  Note:  Even though the number of inputs will never exceed 8 bits,
 +
//        the standard requires a 16-bit type cast.
 
byte zerothree(byte rs[],int start, int num)
 
byte zerothree(byte rs[],int start, int num)
 
{
 
{
   byte rq[8];  //Always 8 bytes
+
   byte rq[8];
  //int addr;
 
  //int len;
 
 
   short c; //CRC value
 
   short c; //CRC value
 
   byte i, j,sz;  //Counters, size
 
   byte i, j,sz;  //Counters, size
  
   if(num==0 || num>0x7d)
+
   if(num==0 || num>0x007d)
 
   {
 
   {
 
     Serial.println("Illegal quantity of inputs");
 
     Serial.println("Illegal quantity of inputs");
Line 446: Line 479:
 
   rq[2]=byte((start&0xFF00)>>8);
 
   rq[2]=byte((start&0xFF00)>>8);
 
   rq[5]=byte(num&0x00FF);
 
   rq[5]=byte(num&0x00FF);
   rq[4]=byte((num&0xFF00)>>8);
+
   rq[4]=0x00; //The number of registers MSB is always zero
  
 +
  //Calculate and store CRC
 
   c = CRC16(rq,6);
 
   c = CRC16(rq,6);
 
   rq[7]=0x00FF & c;
 
   rq[7]=0x00FF & c;
 
   rq[6]=c>>8;
 
   rq[6]=c>>8;
  
 +
  //Deliver request to device
 
   for(i=0;i<8;i++)
 
   for(i=0;i<8;i++)
 
   {
 
   {
 
     Serial1.write(rq[i]);
 
     Serial1.write(rq[i]);
 
   }
 
   }
   sz = 5+rq[5]*2;
+
   sz = 5+num*2;
 
   if(sz>BUFS)
 
   if(sz>BUFS)
 
   {
 
   {
Line 462: Line 497:
 
     return 0;
 
     return 0;
 
   }
 
   }
 +
  //Listen for Response
 
   for(i=0;i<sz;)
 
   for(i=0;i<sz;)
 
   {
 
   {
Line 469: Line 505:
 
       if(i==1 && rs[i]==0x83) sz=5;
 
       if(i==1 && rs[i]==0x83) sz=5;
 
       i++;
 
       i++;
     }
+
     }  
 
+
  }
 +
  if (rs[1]==0x83)
 +
  {
 +
    Serial.println("Remote system threw an error.");
 +
    return 0;
 
   }
 
   }
 
   c=CRC16(rs,sz-2);
 
   c=CRC16(rs,sz-2);
Line 483: Line 523:
  
  
 +
// Read Input Registers zerofour - Read up to 125 registers in a call.
 +
// Requires:
 +
//  byte rs[] : Response[]
 +
//  int start : starting address
 +
//  int num  : Number of inputs between 1..0x0007D
  
//Assigns rs[] array, returns size or zero for CRC error
 
//This does NOT detect broadcast CRC errors, or any exception
 
//handling at all
 
//
 
//    rs : Response[] array
 
//  start : Starting address
 
//    num : Number of registers requested
 
 
byte zerofour(byte rs[],int start, int num)
 
byte zerofour(byte rs[],int start, int num)
 
{
 
{
Line 498: Line 536:
 
   short c; //CRC value
 
   short c; //CRC value
 
   byte i, j,sz;  //Counters, size
 
   byte i, j,sz;  //Counters, size
 +
 +
  if(num==0 || num>0x007d)
 +
  {
 +
    Serial.println("Illegal quantity of inputs");
 +
    return 0; 
 +
  }
 
    
 
    
 
   rq[0]=DEVICE; //Global device IO
 
   rq[0]=DEVICE; //Global device IO
 
   rq[1]=0x04;
 
   rq[1]=0x04;
   rq[3]=byte(start&0x00FF);
+
   rq[3]=byte(start&0x00FF);   //LSB of starting register
   rq[2]=byte((start&0xFF00)>>8);
+
   rq[2]=byte((start&0xFF00)>>8); //MSB of starting register
 
   rq[5]=byte(num&0x00FF);
 
   rq[5]=byte(num&0x00FF);
   rq[4]=byte((num&0xFF00)>>8);
+
   rq[4]=0x00; //This is always zero for this function
  
   c = CRC16(rq,6);
+
   c = CRC16(rq,6); //Generate CRC
   rq[7]=0x00FF & c;
+
   rq[7]=0x00FF & c; //Write LSB of CRC
   rq[6]=c>>8;
+
   rq[6]=c>>8; //Write MSB of CRC
  
 +
  //Deliver request to device
 
   for(i=0;i<8;i++)
 
   for(i=0;i<8;i++)
 
   {
 
   {
 
     Serial1.write(rq[i]);
 
     Serial1.write(rq[i]);
 
   }
 
   }
   sz = 5+rq[5]*2;
+
   sz = 5+num*2;
 
   if(sz>BUFS)
 
   if(sz>BUFS)
 
   {
 
   {
Line 520: Line 565:
 
     return 0;
 
     return 0;
 
   }
 
   }
 +
  //Listen for Response
 
   for(i=0;i<sz;)
 
   for(i=0;i<sz;)
 
   {
 
   {
   
 
 
     if (Serial1.available())            //Data from the Slave is available
 
     if (Serial1.available())            //Data from the Slave is available
 
     {
 
     {
 
       rs[i]=Serial1.read();
 
       rs[i]=Serial1.read();
 +
      if(i==1 && rs[i]==0x83) sz=5;
 
       i++;
 
       i++;
     }
+
     }  
 +
  }
 +
 
 +
  if (rs[1]==0x83)
 +
  {
 +
    Serial.println("Remote system threw an error.");
 +
    return 0;
 
   }
 
   }
 
   c=CRC16(rs,sz-2);
 
   c=CRC16(rs,sz-2);
Line 538: Line 590:
 
   return sz;
 
   return sz;
 
}
 
}
///////////////
 
  
//rs[] : Response array of bytes of size BUFS
+
// Read Input Registers zerofour - Read up to 125 registers in a call.
//addr : two bytes for address being assigned
+
// Requires:
//set  : Boolean assigned to 'addr'
+
//  byte rs[] : Response[]
//confirmation : set HIGH to deliver command to device.
+
//   int start : starting address
 +
//   int num  : Number of inputs between 1..0x0007D
 
byte zerofive(byte rs[],int addr, bool set, bool confirmation)
 
byte zerofive(byte rs[],int addr, bool set, bool confirmation)
 
{
 
{
Line 605: Line 657:
 
   }
 
   }
 
}
 
}
 +
 +
 
///////////////
 
///////////////
 
byte onezero(byte rs[],int start, int num, byte arr[], bool confirmation)
 
byte onezero(byte rs[],int start, int num, byte arr[], bool confirmation)
 
{
 
{
   byte rq[132];  //This is the size of the maximum possible buffer
+
   byte rq[132];  //Always 8 bytes
 +
  //int addr;
 +
  //int len;
 
   short c; //CRC value
 
   short c; //CRC value
 
   byte i, j,sz;  //Counters, size
 
   byte i, j,sz;  //Counters, size
Line 622: Line 678:
 
   rq[2]=byte((start&0xFF00)>>8);
 
   rq[2]=byte((start&0xFF00)>>8);
 
   rq[5]=byte(num&0x00FF);
 
   rq[5]=byte(num&0x00FF);
   rq[4]=byte((num&0xFF00)>>8);
+
   rq[4]=byte((num&0xFF00)>>8);
 +
  rq[6]=num<<1;
  
  rq[6]=num<<1;  //num<<1 is same as num*2, but faster
 
                //total number of 8-bit bytes
 
 
  //Copies the array in parameter list into the request.
 
  //From o to 2*num bytes
 
 
   for(int i=0;i<(num<<1);i++)
 
   for(int i=0;i<(num<<1);i++)
 
   {
 
   {
Line 634: Line 686:
 
   }
 
   }
  
  //Calculates the CRC
 
 
   c = CRC16(rq,7+(num<<1));
 
   c = CRC16(rq,7+(num<<1));
  //copies the CRC 16 bits into two bytes in the array using bit masking
+
   rq[8+(num<<1)]=0x00FF & c;
  //High byte is stored into [8+2*num]
+
   rq[7+(num<<1)]=c>>8;
  //Low byte is stored into [7+2*num]
 
   rq[8+(num<<1)] = 0x00FF & c; //Erase upper bits, copy only the lower 8 by bitwise AND
 
   rq[7+(num<<1)] = c>>8; //right shift the upper 8 bits into the lower 8 bits, stored into array
 
  
   if(confirmation) //If true, issue the command
+
   if(confirmation)
 
   {
 
   {
 
     for(i=0;i<9+(num<<1);i++)
 
     for(i=0;i<9+(num<<1);i++)
Line 649: Line 697:
 
     }
 
     }
 
   }
 
   }
   else //else do nothing but give the coder access to the Request.
+
   else
 
   {
 
   {
 
     for(i=0;i<9+(num<<1);i++)
 
     for(i=0;i<9+(num<<1);i++)
 
     {
 
     {
       rs[i]=rq[i]; //Request is copied into Response
+
       rs[i]=rq[i];
 
     }
 
     }
 
   }
 
   }
   sz = 9+(num<<1); //Size of the Request
+
   sz = 9+(num<<1);
 
   if(sz>BUFS)
 
   if(sz>BUFS)
 
   {
 
   {
Line 662: Line 710:
 
     return 0;
 
     return 0;
 
   }
 
   }
   if(confirmation) //We are writing to the device
+
   if(confirmation)
 
   {
 
   {
     sz=8; //The Response of 0x10 is always 8 bytes (64 bits long)
+
     sz=8;
     for(i=0;i<sz;) //always 8
+
     for(i=0;i<8;)//always 8
     {
+
     {  
   
 
 
       if (Serial1.available())            //Data from the Slave is available
 
       if (Serial1.available())            //Data from the Slave is available
 
       {
 
       {
Line 674: Line 721:
 
       }
 
       }
 
     }
 
     }
    //Test the CRC values of response on the buffer (sparing the given CRC codes)
+
     c=CRC16(rs,sz-2);
     c=CRC16(rs,sz-2); //Test everything except last two bytes.
+
     if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
     if(c!=short((rs[sz-2]<<8 | rs[sz-1]))) //If either byte of CRC is wrong, then error
 
 
     {
 
     {
 
       Serial.println("CRC error in 0x04");
 
       Serial.println("CRC error in 0x04");
Line 684: Line 730:
 
   return sz;
 
   return sz;
 
}
 
}
 
  
 
short CRC16(byte array[],byte s)
 
short CRC16(byte array[],byte s)
Line 768: Line 813:
 
   return short(uchCRCHi << 8 | uchCRCLo);
 
   return short(uchCRCHi << 8 | uchCRCLo);
 
}
 
}
 +
 +
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 04:00, 19 November 2020

Synopsis

Issues 485 request and display result

Notes

9000-9100 Registers

0xFFFF9000 : 0x00 0xFFFF9001 : 0x70 0xFFFF9002 : 0x00 0xFFFF9003 : 0x86 0xFFFF9004 : 0x68 0xFFFF9005 : 0x5E 0xFFFF9006 : 0x54 0xFFFF9007 : 0x54 0xFFFF9008 : 0xC8 0xFFFF9009 : 0x50 0xFFFF900A : 0x00 0xFFFF900B : 0x00 0xFFFF900C : 0x60 0xFFFF900D : 0xAC 0xFFFF900E : 0x48 0xFFFF900F : 0x00 0xFFFF9010 : 0x64 0xFFFF9011 : 0x00 0xFFFF9012 : Error 0x02 0xFFFF9013 : 0x27 0xFFFF9014 : 0x15 0xFFFF9015 : 0x0B 0xFFFF9016 : 0x1E 0xFFFF9017 : 0x4C 0xFFFF9018 : 0x00 0xFFFF9019 : 0x1C 0xFFFF901A : 0x40 0xFFFF901B : 0x34 0xFFFF901C : 0x4C 0xFFFF901D : 0x02 0xFFFF901E : 0xE8 0xFFFF901F : 0x0A 0xFFFF9020 : 0xB0 0xFFFF9021 : 0x0A 0xFFFF9022 : Error 0x02 0xFFFF9023 : Error 0x02 0xFFFF9024 : Error 0x02 0xFFFF9025 : Error 0x02 0xFFFF9026 : Error 0x02 0xFFFF9027 : Error 0x02 0xFFFF9028 : Error 0x02 0xFFFF9029 : Error 0x02 0xFFFF902A : Error 0x02 0xFFFF902B : Error 0x02 0xFFFF902C : Error 0x02 0xFFFF902D : Error 0x02 0xFFFF902E : Error 0x02 0xFFFF902F : Error 0x02 0xFFFF9030 : Error 0x02 0xFFFF9031 : Error 0x02 0xFFFF9032 : Error 0x02 0xFFFF9033 : Error 0x02 0xFFFF9034 : Error 0x02 0xFFFF9035 : Error 0x02 0xFFFF9036 : Error 0x02 0xFFFF9037 : Error 0x02 0xFFFF9038 : Error 0x02 0xFFFF9039 : Error 0x02 0xFFFF903A : Error 0x02 0xFFFF903B : Error 0x02 0xFFFF903C : Error 0x02 0xFFFF903D : 0x00 0xFFFF903E : 0x00 0xFFFF903F : 0x00 0xFFFF9040 : Error 0x02 0xFFFF9041 : Error 0x02 0xFFFF9042 : 0x00 0xFFFF9043 : 0x00 0xFFFF9044 : 0x13 0xFFFF9045 : 0x00 0xFFFF9046 : 0x00 0xFFFF9047 : 0x06 0xFFFF9048 : 0x00 0xFFFF9049 : 0x00 0xFFFF904A : 0x13 0xFFFF904B : 0x00 0xFFFF904C : 0x00 0xFFFF904D : 0x06 0xFFFF904E : Error 0x02 0xFFFF904F : Error 0x02 0xFFFF9050 : Error 0x02 0xFFFF9051 : Error 0x02 0xFFFF9052 : Error 0x02 0xFFFF9053 : Error 0x02 0xFFFF9054 : Error 0x02 0xFFFF9055 : Error 0x02 0xFFFF9056 : Error 0x02 0xFFFF9057 : Error 0x02 0xFFFF9058 : Error 0x02 0xFFFF9059 : Error 0x02 0xFFFF905A : Error 0x02 0xFFFF905B : Error 0x02 0xFFFF905C : Error 0x02 0xFFFF905D : Error 0x02 0xFFFF905E : Error 0x02 0xFFFF905F : Error 0x02 0xFFFF9060 : Error 0x02 0xFFFF9061 : Error 0x02 0xFFFF9062 : Error 0x02 0xFFFF9063 : 0x1E 0xFFFF9064 : 0x02 0xFFFF9065 : 0x00 0xFFFF9066 : Error 0x02 0xFFFF9067 : 0x02 0xFFFF9068 : Error 0x02 0xFFFF9069 : 0x00 0xFFFF906A : 0x00 0xFFFF906B : 0x78 0xFFFF906C : 0x50 0xFFFF906D : 0x1E 0xFFFF906E : 0x50 0xFFFF906F : 0x28 0xFFFF9070 : 0x00 0xFFFF9071 : Error 0x02 0xFFFF9072 : Error 0x02 0xFFFF9073 : Error 0x02 0xFFFF9074 : Error 0x02 0xFFFF9075 : Error 0x02 0xFFFF9076 : Error 0x02 0xFFFF9077 : Error 0x02 0xFFFF9078 : Error 0x02 0xFFFF9079 : Error 0x02 0xFFFF907A : Error 0x02 0xFFFF907B : Error 0x02 0xFFFF907C : Error 0x02 0xFFFF907D : Error 0x02 0xFFFF907E : Error 0x02 0xFFFF907F : Error 0x02 0xFFFF9080 : Error 0x02 0xFFFF9081 : Error 0x02 0xFFFF9082 : Error 0x02 0xFFFF9083 : Error 0x02 0xFFFF9084 : Error 0x02 0xFFFF9085 : Error 0x02 0xFFFF9086 : Error 0x02 0xFFFF9087 : Error 0x02 0xFFFF9088 : Error 0x02 0xFFFF9089 : Error 0x02 0xFFFF908A : Error 0x02 0xFFFF908B : Error 0x02 0xFFFF908C : Error 0x02 0xFFFF908D : Error 0x02 0xFFFF908E : Error 0x02 0xFFFF908F : Error 0x02 0xFFFF9090 : 0x00 0xFFFF9091 : 0x00 0xFFFF9092 : 0x00 0xFFFF9093 : 0x00 0xFFFF9094 : 0x57 0xFFFF9095 : 0x00 0xFFFF9096 : 0x00 0xFFFF9097 : 0x38 0xFFFF9098 : 0xEE 0xFFFF9099 : Error 0x02 0xFFFF909A : Error 0x02 0xFFFF909B : Error 0x02 0xFFFF909C : Error 0x02 0xFFFF909D : Error 0x02 0xFFFF909E : Error 0x02 0xFFFF909F : Error 0x02 0xFFFF90A0 : 0x00 0xFFFF90A1 : 0x00 0xFFFF90A2 : 0x00 0xFFFF90A3 : 0x00 0xFFFF90A4 : 0x00 0xFFFF90A5 : Error 0x02 0xFFFF90A6 : Error 0x02 0xFFFF90A7 : Error 0x02 0xFFFF90A8 : Error 0x02 0xFFFF90A9 : Error 0x02 0xFFFF90AA : Error 0x02 0xFFFF90AB : Error 0x02 0xFFFF90AC : Error 0x02 0xFFFF90AD : Error 0x02 0xFFFF90AE : Error 0x02 0xFFFF90AF : Error 0x02 0xFFFF90B0 : 0xD2 0xFFFF90B1 : 0x60 0xFFFF90B2 : 0x13 0xFFFF90B3 : 0x7A 0xFFFF90B4 : 0x00 0xFFFF90B5 : 0xA7 0xFFFF90B6 : 0x89 0xFFFF90B7 : 0x35 0xFFFF90B8 : 0x75 0xFFFF90B9 : 0x87 0xFFFF90BA : 0x00 0xFFFF90BB : 0x00 0xFFFF90BC : Error 0x02 0xFFFF90BD : 0x00 0xFFFF90BE : 0x00 0xFFFF90BF : 0xE0 0xFFFF90C0 : Error 0x02 0xFFFF90C1 : Error 0x02 0xFFFF90C2 : Error 0x02 0xFFFF90C3 : Error 0x02 0xFFFF90C4 : Error 0x02 0xFFFF90C5 : Error 0x02 0xFFFF90C6 : Error 0x02 0xFFFF90C7 : Error 0x02 0xFFFF90C8 : Error 0x02 0xFFFF90C9 : Error 0x02 0xFFFF90CA : Error 0x02 0xFFFF90CB : Error 0x02 0xFFFF90CC : Error 0x02 0xFFFF90CD : Error 0x02 0xFFFF90CE : Error 0x02 0xFFFF90CF : Error 0x02 0xFFFF90D0 : Error 0x02 0xFFFF90D1 : Error 0x02 0xFFFF90D2 : Error 0x02 0xFFFF90D3 : Error 0x02 0xFFFF90D4 : Error 0x02 0xFFFF90D5 : Error 0x02 0xFFFF90D6 : Error 0x02 0xFFFF90D7 : Error 0x02 0xFFFF90D8 : Error 0x02 0xFFFF90D9 : Error 0x02 0xFFFF90DA : Error 0x02 0xFFFF90DB : Error 0x02 0xFFFF90DC : Error 0x02 0xFFFF90DD : Error 0x02 0xFFFF90DE : Error 0x02 0xFFFF90DF : Error 0x02 0xFFFF90E0 : Error 0x02 0xFFFF90E1 : Error 0x02 0xFFFF90E2 : Error 0x02 0xFFFF90E3 : Error 0x02 0xFFFF90E4 : Error 0x02 0xFFFF90E5 : Error 0x02 0xFFFF90E6 : Error 0x02 0xFFFF90E7 : Error 0x02 0xFFFF90E8 : Error 0x02 0xFFFF90E9 : Error 0x02 0xFFFF90EA : Error 0x02 0xFFFF90EB : Error 0x02 0xFFFF90EC : Error 0x02 0xFFFF90ED : Error 0x02 0xFFFF90EE : Error 0x02 0xFFFF90EF : Error 0x02 0xFFFF90F0 : Error 0x02 0xFFFF90F1 : Error 0x02 0xFFFF90F2 : Error 0x02 0xFFFF90F3 : Error 0x02 0xFFFF90F4 : Error 0x02 0xFFFF90F5 : Error 0x02 0xFFFF90F6 : Error 0x02 0xFFFF90F7 : Error 0x02 0xFFFF90F8 : Error 0x02 0xFFFF90F9 : Error 0x02 0xFFFF90FA : Error 0x02 0xFFFF90FB : Error 0x02 0xFFFF90FC : Error 0x02 0xFFFF90FD : Error 0x02 0xFFFF90FE : Error 0x02 0xFFFF90FF : Error 0x02

Code

  1 //#include <SoftwareSerial.h>
  2 //const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin
  3 //const int SSERIAL_TX_PIN = 11;  //Soft Serial Transmit pin
  4 
  5 // Create Soft Serial Port object and define pins to use
  6 //SoftwareSerial RS485Serial(SSERIAL_RX_PIN, SSERIAL_TX_PIN); // RX, TX
  7 
  8 #define DEVICE 0x01
  9 #define BUFS 64   //Buffer size
 10 short crc;
 11 byte arry[6] = {0x00, 0x02, 0x02, 0x00, 0x02, 0x00};
 12 byte Response[BUFS];
 13 byte Response_size;
 14 byte countdown = 2;
 15 //===============================================================================
 16 //  Initialization
 17 //===============================================================================
 18 void setup()
 19 {
 20   Serial.begin(115200);           // Start the built-in serial port   
 21   Serial1.begin(115200);   // Start the RS485 soft serial port 
 22   delay(1000);
 23   Serial.println();
 24 }
 25 
 26 
 27 //===============================================================================
 28 //  Main
 29 //===============================================================================
 30 void loop() 
 31 {
 32 
 33   Response_size=zerothree(Response,0x9013,0x0003 ); 
 34  
 35   Serial.print("Size is  : ");
 36   Serial.println(Response_size);
 37 
 38   Serial.print("Response string is : ");
 39   for(byte i=0;i<Response_size;i++)
 40   {
 41     Serial.print("0x");
 42     if(Response[i]<16) Serial.print("0");
 43     Serial.print(Response[i],HEX);
 44     Serial.print(" ");
 45   }
 46   Serial.println();
 47 
 48   while(1)
 49   {}
 50 }
 51 // Read coils zeroone - Read up to 2000 coils in a call.
 52 // Requires:
 53 //   byte rs[] : Respose[]
 54 //   int start : starting address
 55 //   int num   : Number of coils between 1..0x07D0
 56 //
 57 byte zeroone(byte rs[],int start, int num)
 58 {
 59   byte rq[8];  //Always 8 bytes for 0x01
 60   short c; //CRC value
 61   byte i, j,sz;  //Counters, size
 62 
 63   //If there are no parameters selected or too many, then error, quit.
 64   if(num==0 || num>0x07d0)
 65   {
 66     Serial.println("Illegal quantity of inputs");
 67     return 0;  
 68   }
 69 
 70   
 71   rq[0]=DEVICE; //Global device IO
 72   rq[1]=0x01;
 73   rq[3]=byte(start&0x00FF);     //starting LSB address
 74   rq[2]=byte((start&0xFF00)>>8);//starting MSB address
 75   rq[5]=byte(num&0x00FF);       //number of coils LSB
 76   rq[4]=byte((num&0xFF00)>>8);  //number of coils MSB
 77 
 78   c = CRC16(rq,6);  //Calculate CRC
 79   
 80   rq[7]=0x00FF & c; //CRC LSB
 81   rq[6]=c>>8;       //CRC MSB
 82 
 83 
 84   //Transmit the Request array onto bus.
 85   for(i=0;i<8;i++)
 86   {
 87     Serial1.write(rq[i]);
 88   }
 89 
 90   //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic
 91   //is needed to ensure a fractional byte always rounds upwards to an additioanl byte
 92   sz=5+num/8;
 93   if(num%8>0) sz++;
 94   
 95   if(sz>BUFS)
 96   {
 97     Serial.println("Buffer overflow prevented in 0x01.  Recompile with BUFS to a higher value");
 98     return 0;
 99   }
100   for(i=0;i<sz;)
101   {
102     if (Serial1.available())            //Data from the Slave is available
103     {
104       rs[i]=Serial1.read();
105       if(i==1 && rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.
106       i++;
107     }   
108   }
109   if (rs[1]==0x83)
110   {
111     Serial.println("Remote system threw an error.");
112     return 0;
113   }
114   c=CRC16(rs,sz-2);
115   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
116   {
117     Serial.println("CRC error in 'Read Coils' function 0x01");
118     return 0;
119   }
120   return sz;
121 }
122 
123 // Read discretes zerotwo - Read up to 2000 discrete inputs in a call.
124 // Requires:
125 //   byte rs[] : Respose[]
126 //   int start : starting address
127 //   int num   : Number of inputs between 1..0x07D0
128 //
129 byte zerotwo(byte rs[], int start, int num)
130 {
131   byte rq[8];  //Always 8 bytes
132   short c; //CRC value
133   byte i, j,sz;  //Counters, size
134   
135   rq[0]=DEVICE; //Global device IO
136   rq[1]=0x02;
137   rq[3]=byte(start&0x00FF);  //Starting address LSB
138   rq[2]=byte((start&0xFF00)>>8);  //Starting address MSB
139   rq[5]=byte(num&0x00FF);  //Number of bits LSB
140   rq[4]=byte((num&0xFF00)>>8); //Number of bits MSB
141 
142   c = CRC16(rq,6);
143   rq[7]=0x00FF & c;  //CRC LSB written 
144   rq[6]=c>>8;       //CRC MSB written
145 
146 
147   //Deliver request to device
148   for(i=0;i<8;i++)
149   {
150     Serial1.write(rq[i]);
151   }
152 
153   //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic
154   //is needed to ensure a fractional byte always rounds upwards to an additional byte
155   sz=5+num/8;
156   if(num%8>0) sz++;
157   
158   if(sz>BUFS)
159   {
160     Serial.println("Buffer overflow prevented in 0x02.  Recompile with BUFS to a higher value");
161     return 0;
162   }
163   
164   //Listen for response
165   for(i=0;i<sz;)
166   {
167     if (Serial1.available())            //Data from the Slave is available
168     {
169       rs[i]=Serial1.read();
170       if(i==1 && rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.
171       i++;
172     }   
173   }
174   if (rs[1]==0x83)
175   {
176     Serial.println("Remote system threw an error.");
177     return 0;
178   }
179 
180   //Verify CRC code
181   c=CRC16(rs,sz-2);
182   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
183   {
184     Serial.println("CRC error in 0x02");
185     return 0;
186   }
187   return sz;
188 }
189 
190 // Read Holding Registers zerothree - Read up to 125 registers in a call.
191 // Requires:
192 //   byte rs[] : Response[]
193 //   int start : starting address
194 //   int num   : Number of inputs between 1..0x0007D
195 //
196 //  Note:  Even though the number of inputs will never exceed 8 bits,
197 //         the standard requires a 16-bit type cast.
198 byte zerothree(byte rs[],int start, int num)
199 {
200   byte rq[8];
201   short c; //CRC value
202   byte i, j,sz;  //Counters, size
203 
204   if(num==0 || num>0x007d)
205   {
206     Serial.println("Illegal quantity of inputs");
207     return 0;  
208   }
209 
210   
211   rq[0]=DEVICE; //Global device IO
212   rq[1]=0x03;
213   rq[3]=byte(start&0x00FF);
214   rq[2]=byte((start&0xFF00)>>8);
215   rq[5]=byte(num&0x00FF);
216   rq[4]=0x00;  //The number of registers MSB is always zero
217 
218   //Calculate and store CRC
219   c = CRC16(rq,6);
220   rq[7]=0x00FF & c;
221   rq[6]=c>>8;
222 
223   //Deliver request to device
224   for(i=0;i<8;i++)
225   {
226     Serial1.write(rq[i]);
227   }
228   sz = 5+num*2;
229   if(sz>BUFS)
230   {
231     Serial.println("Buffer overflow prevented in 0x03.  Recompile with BUFS to a higher value");
232     return 0;
233   }
234   //Listen for Response
235   for(i=0;i<sz;)
236   {
237     if (Serial1.available())            //Data from the Slave is available
238     {
239       rs[i]=Serial1.read();
240       if(i==1 && rs[i]==0x83) sz=5;
241       i++;
242     }   
243   }
244   if (rs[1]==0x83)
245   {
246     Serial.println("Remote system threw an error.");
247     return 0;
248   }
249   c=CRC16(rs,sz-2);
250   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
251   {
252     Serial.println("CRC error in 0x03");
253     return 0;
254   }
255 
256   return sz;
257 }
258 
259 
260 // Read Input Registers zerofour - Read up to 125 registers in a call.
261 // Requires:
262 //   byte rs[] : Response[]
263 //   int start : starting address
264 //   int num   : Number of inputs between 1..0x0007D
265 
266 byte zerofour(byte rs[],int start, int num)
267 {
268   byte rq[8];  //Always 8 bytes
269   //int addr;
270   //int len;
271   short c; //CRC value
272   byte i, j,sz;  //Counters, size
273 
274   if(num==0 || num>0x007d)
275   {
276     Serial.println("Illegal quantity of inputs");
277     return 0;  
278   }
279   
280   rq[0]=DEVICE; //Global device IO
281   rq[1]=0x04;
282   rq[3]=byte(start&0x00FF);   //LSB of starting register
283   rq[2]=byte((start&0xFF00)>>8);  //MSB of starting register
284   rq[5]=byte(num&0x00FF);
285   rq[4]=0x00;  //This is always zero for this function
286 
287   c = CRC16(rq,6);  //Generate CRC
288   rq[7]=0x00FF & c;  //Write LSB of CRC
289   rq[6]=c>>8; //Write MSB of CRC
290 
291   //Deliver request to device
292   for(i=0;i<8;i++)
293   {
294     Serial1.write(rq[i]);
295   }
296   sz = 5+num*2;
297   if(sz>BUFS)
298   {
299     Serial.println("Buffer overflow prevented in 0x04.  Recompile with BUFS to a higher value");
300     return 0;
301   }
302   //Listen for Response
303   for(i=0;i<sz;)
304   {
305     if (Serial1.available())            //Data from the Slave is available
306     {
307       rs[i]=Serial1.read();
308       if(i==1 && rs[i]==0x83) sz=5;
309       i++;
310     }   
311   }
312   
313   if (rs[1]==0x83)
314   {
315     Serial.println("Remote system threw an error.");
316     return 0;
317   }
318   c=CRC16(rs,sz-2);
319   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
320   {
321     Serial.println("CRC error in 0x04");
322     return 0;
323   }
324 
325   return sz;
326 }
327 
328 // Read Input Registers zerofour - Read up to 125 registers in a call.
329 // Requires:
330 //   byte rs[] : Response[]
331 //   int start : starting address
332 //   int num   : Number of inputs between 1..0x0007D
333 byte zerofive(byte rs[],int addr, bool set, bool confirmation)
334 {
335   byte rq[8];  //Always 8 bytes
336   //int addr;
337   //int len;
338   short c; //CRC value
339   byte i, j,sz;  //Counters, size
340 
341   
342   rq[0]=DEVICE; //Global device IO
343   rq[1]=0x05;
344   rq[3]=byte(addr&0x00FF);
345   rq[2]=byte((addr&0xFF00)>>8);
346   rq[4]=0x00;  
347   if(set) rq[5]=0xFF;
348   else rq[5]=0x00;
349 
350 
351   c = CRC16(rq,6);
352   rq[7]=0x00FF & c;
353   rq[6]=c>>8;
354   if(confirmation)
355   {
356     for(i=0;i<8;i++)
357     {
358       Serial1.write(rq[i]);
359     }
360   }
361   sz = 6;
362   if(sz>BUFS)
363   {
364     Serial.println("Buffer overflow prevented in 0x03.  Recompile with BUFS to a higher value");
365     return 0;
366   }
367   if(confirmation)
368   {
369     for(i=0;i<sz;)
370     {
371       if (Serial1.available())            //Data from the Slave is available
372       {
373         rs[i]=Serial1.read();
374         if(i==1 && rs[i]==0x83) sz=5;
375         i++;
376       }  
377     }
378   }
379   else
380   {
381     for(i=0;i<sz;)
382     {
383         rs[i]=rq[i];
384         i++;
385     }
386   }
387   c=CRC16(rs,sz-2);
388   if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
389   {
390     Serial.println("CRC error in 0x03");
391     return 0;
392   }
393 }
394 
395 
396 ///////////////
397 byte onezero(byte rs[],int start, int num, byte arr[], bool confirmation)
398 {
399   byte rq[132];  //Always 8 bytes
400   //int addr;
401   //int len;
402   short c; //CRC value
403   byte i, j,sz;  //Counters, size
404 
405   if(num==0 || num>0x7B)
406   {
407     Serial.println("Invalid number of registers being written in 0x10.");
408     return 0;
409   }
410   rq[0]=DEVICE; //Global device IO
411   rq[1]=0x10;
412   rq[3]=byte(start&0x00FF);
413   rq[2]=byte((start&0xFF00)>>8);
414   rq[5]=byte(num&0x00FF);
415   rq[4]=byte((num&0xFF00)>>8);
416   rq[6]=num<<1;
417 
418   for(int i=0;i<(num<<1);i++)
419   {
420     rq[7+i]=arr[i];
421   }
422 
423   c = CRC16(rq,7+(num<<1));
424   rq[8+(num<<1)]=0x00FF & c;
425   rq[7+(num<<1)]=c>>8;
426 
427   if(confirmation)
428   {
429     for(i=0;i<9+(num<<1);i++)
430     {
431       Serial1.write(rq[i]);
432     }
433   }
434   else
435   {
436     for(i=0;i<9+(num<<1);i++)
437     {
438       rs[i]=rq[i];
439     }
440   }
441   sz = 9+(num<<1);
442   if(sz>BUFS)
443   {
444     Serial.println("Buffer overflow prevented in 0x04.  Recompile with BUFS to a higher value");
445     return 0;
446   }
447   if(confirmation)
448   {
449     sz=8;
450     for(i=0;i<8;)//always 8
451     {    
452       if (Serial1.available())            //Data from the Slave is available
453       {
454         rs[i]=Serial1.read();
455         i++;
456       }
457     }
458     c=CRC16(rs,sz-2);
459     if(c!=short((rs[sz-2]<<8 | rs[sz-1])))
460     {
461       Serial.println("CRC error in 0x04");
462       return 0;
463     }
464   }
465   return sz;
466 }
467 
468 short CRC16(byte array[],byte s)
469 {
470   static const byte auchCRCHi[] = {
471         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
472         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
473         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
474         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
475         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
476         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
477         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
478         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
479         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
480         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
481         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
482         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
483         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
484         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
485         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
486         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
487         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
488         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
489         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
490         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
491         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
492         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
493         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
494         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
495         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
496         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
497         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
498         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
499         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
500         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
501         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
502         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ; 
503 
504   static const byte auchCRCLo[] = {
505         0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
506         0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
507         0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
508         0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
509         0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
510         0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
511         0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
512         0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
513         0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
514         0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
515         0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
516         0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
517         0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
518         0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
519         0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
520         0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
521         0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
522         0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
523         0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
524         0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
525         0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
526         0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
527         0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
528         0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
529         0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
530         0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
531         0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
532         0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
533         0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
534         0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
535         0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
536         0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;
537 
538   byte uchCRCHi = 0xFF;
539   byte uchCRCLo = 0xFF;
540   byte uIndex;
541 
542   while(s--)
543   {
544     uIndex = uchCRCHi ^ *array++ ;
545     uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
546     uchCRCLo = auchCRCLo[uIndex] ;
547   }
548   return short(uchCRCHi << 8 | uchCRCLo);
549 }