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 6
LRC / CRC Generation
V 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
| | |