A basic library for RS485 communication

Dependencies:   BufferedSerial

Dependents:   mbed_blinko

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RS485.cpp Source File

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