Catalogue of series articles
Tip: you can add the directories of all articles in the series here. You need to add the directories manually
For example:
Tip: after writing the article, the directory can be generated automatically. For how to generate it, please refer to the help document on the right
preface
Introduction:
1. On the basis of #3 chapter, interrupt timing + timeout reception
2. Add CRC verification method and receive response processing
3. Instruction analysis, control nixie tube + led in the main function
Tip: the following is the main content of this article. The following cases can be used for reference
1, Scene
Example:
The host sends a command, the slave parses and responds, and CRC checks
2, Programming implementation
1. Custom agreement
For example:
address | data type | Data area | CRCL | CRCH |
---|---|---|---|---|
01 | 01~03 |
##1
Data type (function code):
Control nixie tube display 0x01, buzzer control 0x02
##2. Slave handshake response:
b. Address error:
Ignore
a.CRC check is correct:
Full data return
The value in the data area is displayed on the nixie tube, for example, only the maximum two groups are displayed
b.CRC check error:
Address + [data type high position 1] + data area + CRC
2. Code design
Step 1: #C51 serial communication 2-# a string of data # timing interrupt to realize timeout reception (recommended)
Continue to develop based on the sample project to verify the correctness of data sending and receiving.
Step 2: add nixie tube display and led functions
Step 3: verify CRC verification. The example uses CRC16-MODBUS (8005, FFFF,0000)
Attach CRC code (look-up table method):
unsigned int GetCRC16(unsigned char *puchMsg, unsigned int usDataLen) { unsigned char uchCRCHi = 0xFF ; //*High CRC byte initialization unsigned char uchCRCLo = 0xFF ; //*Low CRC byte initialization unsigned long uIndex ; // Index in CRC cycle // CRC high byte value table unsigned char code auchCRCHi[260] = { 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 } ; // CRC low byte value table unsigned char code auchCRCLo[260] = { 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 } ; while (usDataLen--) //Transmit message buffer { uIndex = uchCRCLo ^ *puchMsg++ ; // Calculate CRC uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex] ; uchCRCHi = auchCRCLo[uIndex] ; } return (uchCRCHi << 8 | uchCRCLo); }
Step 3:
”The "interrupt timing + timeout sending and receiving" code is no longer posted. See basic routine 3 for details#
void uart_ISR() interrupt 4{} void Timer0_ISR() interrupt 1{}
Step 4:
1. Buffer data CRC verification 2. Verification judgment 3. Receiving response 4. Parsing
if(recv_flag) { recv_flag = 0; timer_start = 0; //Turn off the timer to prevent T0 from executing all the time for (i = 0; i < cRealLen; i++) { uart_Recv[i] = vbuf[i]; } // 1.CRC verification CRC = GetCRC16(uart_Recv, cRealLen-2); //CRCL/CRCH CRCL = CRC & 0x00FF; CRCH = CRC >> 8;
// 2. Verification judgment if((CRCL == uart_Recv[cRealLen - 2]) && (CRCH == uart_Recv[cRealLen - 1])) { sendData(uart_Recv,cRealLen); //@@@@Discard and use sendString(), otherwise it will stop when it meets 0, including 0 of the check code@@@@ if(0x01 != uart_Recv[0]) //If the address is correct, execute the command, otherwise it will not respond { ; } else { Exchange_Func(); fLedShine = 1; } } else //3. Verification error, data type high position 1, return the whole data { uart_Recv[1] |= 0x80; CRC = GetCRC16(uart_Recv, cRealLen-2); //CRCL/CRCH CRCL = CRC & 0x00FF; CRCH = CRC >> 8; uart_Recv[cRealLen - 2] = CRCL; uart_Recv[cRealLen - 1] = CRCH; sendData(uart_Recv,cRealLen); } // sendString(vbuf); //test // sendString(uart_Recv); clr_recvbuffer(vbuf); }
void Exchange_Func(void) { if(0x01 == uart_Recv[0]) //For demonstration only, data type 01 controls nixie tube display { switch(uart_Recv[1]) //The data length represents the number of digits displayed { case 1: SEG_DisBuf[0] = 23; SEG_DisBuf[1] = 23; SEG_DisBuf[2] = uart_Recv[2] >> 4; SEG_DisBuf[3] = uart_Recv[2] & 0x0F; break; case 2: SEG_DisBuf[0] = uart_Recv[2] >> 4; SEG_DisBuf[1] = uart_Recv[2] & 0x0F; SEG_DisBuf[2] = uart_Recv[3] >> 4; SEG_DisBuf[3] = uart_Recv[3] & 0x0F; break; case 3: break; default:break; } }
3. Test verification
@1 correct response:
@2 verification error response
@3 data length change
summary
1. Nixie tube dynamic scanning in T0 timing interrupt, priority processing of shadow elimination, WX_DIS = 0xFF, swith / case statement is used for the test.
2. The number of nixie tubes * scanning interval shall be controlled within 10ms, and the display processing function shall be placed in T0 timing interrupt service function. Therefore, ms level delay shall not be made. Time difference will cause serial port data error
3. modular design, calling after testing.
If the code CRC found on the Internet is wrong in the actual high and low positions, printf() can be used to print the results on the serial port to observe the problem.