|  Durante todo el año recibimos muchos mail, 
pidiéndonos información para realizar trabajos sobre autómatas. Así que ahora es 
el momento para recordaros que necesitamos de vuestra colaboración enviándonos 
los que ya habéis presentado.             |  | Chapter 6VLRC / CRC Generation
 LRC Generation 
V	 CRC Generation 
	6.1	LRC Generation
 
The Longitudinal Redundancy Check (LRC) field is one byte, 
containing an eight-bit binary value. The LRC value is calculated 
by the transmitting device, which appends the LRC to the 
message. The receiving device recalculates an LRC during receipt 
of the message, and compares the calculated value to the actual 
value it received in the LRC field. If the two values are not equal, 
an error results.
 
The LRC is calculated by adding together successive eight-bit 
bytes in the message, discarding any carries, then two's 
complementing the result. The LRC is an eight-bit field, therefore 
each new addition of a character that would result in a value 
higher than 255 decimal simply rolls over the field's value 
through zero. Because there is no ninth bit, the carry is discarded 
automatically.
 
	Generating an LRC
 
	Step 1	Add all bytes in the message, excluding the starting colon and 
ending CRLF. Add them into an eight-bit field, so that carries 
will be discarded.
 
	Step 2	Subtract the final field value from FF hex (all 1's), to produce the 
ones-complement.
 
	Step 3	Add 1 to produce the two's-complement.
 
Placing the LRC into the Message
 
When the the eight-bit LRC (two ASCII characters) is transmitted 
in the message, the high order character will be transmitted first, 
followed by the low order character-e.g., if the LRC value is 61 
hex (0110 0001):
 
  
 Figure 8 LRC Character Sequence
 
Example
 
An example of a C language function performing LRC generation 
is shown below. The function takes two arguments:
 
  
unsigned char *auchMsg ;	A pointer to the message buffer 
con-
						 			taining binary data to be used for
									 generating the LRC
 
unsigned short usDataLen ;	The quantity of bytes in the 
									message buffer.
The function returns the LRC as a type unsigned char. 
LRC Generation Function
 
  
static unsigned char LRC(auchMsg, usDataLen)
 
unsigned char *auchMsg ;		/* message to calculate  */
unsigned short usDataLen ;		/* LRC upon quantity of  */
										/* bytes in message      */
 
{
	unsigned char uchLRC = 0 ;	/* LRC char initialized   */
	while (usDataLen--)		/* pass through message  */ 
		uchLRC += *auchMsg++ ;	/* buffer add buffer byte*/ 
										/* without carry         */
 
	return ((unsigned char)(-((char_uchLRC))) ;
										/* return twos complemen */
}
6.2	CRC Generation 
The Cyclical Redundancy Check (CRC) field is two bytes, 
containing a 16-bit binary value. The CRC value is calculated by 
the transmitting device, which appends the CRC to the message. 
The receiving device recalculates a CRC during receipt of the 
message, and compares the calculated value to the actual value it 
received in the CRC field. If the two values are not equal, an error 
results.
 
The CRC is started by first preloading a 16-bit register to all 1's.  
Then a process begins of applying successive eight-bit bytes of the 
message to the current contents of the register. Only the eight bits 
of data in each character are used for generating the CRC. Start 
and stop bits, and the parity bit, do not apply to the CRC.
 
During generation of the CRC, each eight-bit character is 
exclusive ORed with the register contents. The result is shifted in 
the direction of the least significant bit (LSB), with a zero filled 
into the most significant bit (MSB) position. The LSB is extracted 
and examined. If the LSB was a 1, the register is then exclusive 
ORed with a preset, fixed value. If the LSB was a 0, no exclusive 
OR takes place.
 
This process is repeated until eight shifts have been performed. 
After the last (eighth) shift, the next eight-bit character is 
exclusive ORed with the register's current value, and the process 
repeats for eight more shifts as described above. The final 
contents of the register, after all the characters of the message 
have been applied, is the CRC value.
 
	Generating a CRC
 
	Step 1	Load a 16-bit register with FFFF hex (all 1's). Call this the CRC 
register.
 
	Step 2	Exclusive OR the first eight-bit byte of the message with the low 
order byte of the 16-bit CRC register, putting the result in the 
CRC register.
 
	Step 3	Shift the CRC register one bit to the right (toward the LSB), 
zerofilling the MSB. Extract and examine the LSB.
 
	Step 4	If the LSB is 0, repeat Step 3 (another shift). If the LSB is 1, 
Exclusive OR the CRC register with the polynomial value A001 
hex (1010 0000 0000 0001).
 
	Step 5	Repeat Steps 3 and 4 until eight shifts have been performed. 
When this is done, a complete eight-bit byte will have been 
processed.
 
	Step 6	Repeat Steps 2 ... 5 for the next eight-bit byte of the message. 
Continue doing this until all bytes have been processed.
 
	Result	The final contents of the CRC register is the CRC value.
 
	Step 7	When the CRC is placed into the message, its upper and lower 
bytes must be swapped as described below.
 
Placing the CRC into the Message
 
When the 16-bit CRC (two eight-bit bytes) is transmitted in the 
message, the low order byte will be transmitted first, followed by 
the high order byte-e.g., if the CRC value is 1241 hex (0001 0010 
0100 0001):
 
  
 Figure 9 CRC Byte Sequence
 
Example
 
An example of a C language function performing CRC generation 
is shown on the following pages. All of the possible CRC values 
are preloaded into two arrays, which are simply indexed as the 
function increments through the message buffer. One array 
contains all of the 256 possible CRC values for the high byte of the 
16-bit CRC field, and the other array contains all of the values for 
the low byte.
 
Indexing the CRC in this way provides faster execution than 
would be achieved by calculating a new CRC value with each new 
character from the message buffer.
 
  Note: This function performs the swapping of the high/low 
CRC bytes internally. The bytes are already swapped in the CRC 
value that is returned from the function. Therefore the CRC 
value returned from the function can be directly placed into the 
message for transmission.
 
The function takes two arguments:
 
  
unsigned char *puchMsg ; 	A pointer to the message buffer
									containing binary data to be used
									for generating the CRC
 
unsigned short usDataLen ;	The quantity of bytes in the 
									message buffer.
The function returns the CRC as a type unsigned short. 
CRC Generation Function
 
  
unsigned short CRC16(puchMsg, usDataLen)
 
unsigned char *puchMsg ;		/* message to calculate CRC 
upon */
unsigned short usDataLen ;		/* quantity of bytes in message  
*/
 
{
	unsigned char uchCRCHi = 0xFF ;	/* high CRC byte 
initialized */
	unsigned char uchCRCLo = 0xFF ;	/* low CRC byte 
initialized  */
	unsigned uIndex ;				/* will index into CRC 
lookup*/
											/* table                   
  */
	while (usDataLen--)		/* pass through message buffer  
  */
		{
		uIndex = uchCRCHi ^ *puchMsgg++ ;	/* calculate the CRC  
 */
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex} ;
		uchCRCLo = auchCRCLo[uIndex] ;
		}
	return (uchCRCHi << 8 | uchCRCLo) ;
}
High Order Byte Table 
  
/* Table of CRC values for high-order byte */
 
static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ; 
Low Order Byte Table
  
/* Table of CRC values for low-order byte */
 
static char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
www.automatas.org |  |  |