Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RS485.cpp
00001 #include "RS485.h" 00002 #include <stdarg.h> 00003 00004 typedef unsigned int word; 00005 typedef uint8_t byte; 00006 typedef uint8_t boolean; 00007 typedef void (*voidFuncPtr)(void); 00008 Timer lapse; 00009 const byte STX = '\2'; 00010 const byte ETX = '\3'; 00011 00012 RS485::RS485(PinName tx, PinName rx, PinName dere) 00013 : BufferedSerial(tx, rx) 00014 { 00015 return; 00016 } 00017 00018 00019 byte RS485::crc8(const byte *addr, byte len) 00020 { 00021 byte crc = 0; 00022 while (len--) 00023 { 00024 byte inbyte = *addr++; 00025 for (byte i = 8; i; i--) 00026 { 00027 byte mix = (crc ^ inbyte) & 0x01; 00028 crc >>= 1; 00029 if (mix) 00030 crc ^= 0x8C; 00031 inbyte >>= 1; 00032 } // end of for 00033 } // end of while 00034 return crc; 00035 } // end of crc8 00036 00037 void RS485::sendComplemented( const byte what) 00038 { 00039 byte c ; 00040 // first nibble 00041 c = what >> 4; 00042 putc((c << 4) | (c ^ 0x0F)); 00043 00044 // second nibble 00045 c = what & 0x0F; 00046 putc((c << 4) | (c ^ 0x0F)); 00047 } // end of sendComplemented 00048 00049 00050 void RS485::sendMsg(const byte * data, const byte length) 00051 { 00052 putc(STX); // STX 00053 for (byte i = 0; i < length; i++) 00054 sendComplemented (data[i]); 00055 putc(ETX); // ETX 00056 sendComplemented(crc8(data, length)); 00057 } // end of sendMsg 00058 00059 // receive a message, maximum "length" bytes, timeout after "timeout" clock_mseconds 00060 // if nothing received, or an error (eg. bad CRC, bad data) return 0 00061 // otherwise, returns length of received data 00062 byte RS485::recvMsg (byte * data, // buffer to receive into 00063 const byte length, // maximum buffer size 00064 unsigned long timeout) // clock_mseconds before timing out 00065 { 00066 00067 unsigned long start_time = lapse.read_ms(); 00068 00069 bool have_stx = false; 00070 00071 // variables below are set when we get an STX 00072 bool have_etx; 00073 byte input_pos; 00074 bool first_nibble; 00075 byte current_byte; 00076 00077 while (lapse.read_ms() - start_time < timeout) 00078 { 00079 if (readable() > 0) 00080 { 00081 byte inByte = getc(); 00082 00083 switch (inByte) 00084 { 00085 00086 case STX: // start of text 00087 have_stx = true; 00088 have_etx = false; 00089 input_pos = 0; 00090 first_nibble = true; 00091 start_time = lapse.read_ms(); // reset timeout period 00092 break; 00093 00094 case ETX: // end of text 00095 have_etx = true; 00096 break; 00097 00098 default: 00099 // wait until packet officially starts 00100 if (!have_stx) 00101 break; 00102 00103 // check byte is in valid form (4 bits followed by 4 bits complemented) 00104 if ((inByte >> 4) != ((inByte & 0x0F) ^ 0x0F) ) 00105 return 0; // bad character 00106 00107 // convert back 00108 inByte >>= 4; 00109 00110 // high-order nibble? 00111 if (first_nibble) 00112 { 00113 current_byte = inByte; 00114 first_nibble = false; 00115 break; 00116 } // end of first nibble 00117 00118 // low-order nibble 00119 current_byte <<= 4; 00120 current_byte |= inByte; 00121 first_nibble = true; 00122 00123 // if we have the ETX this must be the CRC 00124 if (have_etx) 00125 { 00126 if (crc8 (data, input_pos) != current_byte) 00127 return 0; // bad crc 00128 return input_pos; // return received length 00129 } // end if have ETX already 00130 00131 // keep adding if not full 00132 if (input_pos < length) 00133 data [input_pos++] = current_byte; 00134 else 00135 return 0; // overflow 00136 break; 00137 00138 } // end of switch 00139 } // end of incoming data 00140 } // end of while not timed out 00141 00142 return 0; // timeout 00143 } // end of recvMsg
Generated on Tue Jul 12 2022 20:26:33 by
