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.
Diff: RS485/RS485.cpp
- Revision:
- 4:f6e22dd39313
- Parent:
- 2:b7fdc74e5c5d
- Child:
- 8:c3cffab85b0d
--- a/RS485/RS485.cpp Tue Jul 07 15:02:22 2020 +0000
+++ b/RS485/RS485.cpp Sat Jul 18 14:59:04 2020 +0000
@@ -1,18 +1,144 @@
#include "RS485.h"
-
-RS485::RS485(PinName tx, PinName rx, PinName mode, const char *name) : Serial( tx, rx, name), m_modePin(mode)
-{
- m_modePin = 0;
+#include <stdarg.h>
+
+typedef unsigned int word;
+typedef uint8_t byte;
+typedef uint8_t boolean;
+typedef void (*voidFuncPtr)(void);
+Timer lapse;
+ const byte STX = '\2';
+ const byte ETX = '\3';
+
+RS485::RS485(PinName tx, PinName rx, PinName dere)
+ : BufferedSerial(tx, rx)
+{
+ return;
}
-
-int RS485::_getc() {
- return _base_getc();
-}
-
-int RS485::_putc(int c) {
- m_modePin = 1;
- int ret = _base_putc(c);
- m_modePin = 0;
- return ret;
-}
-
+
+
+byte RS485::crc8(const byte *addr, byte len)
+{
+ byte crc = 0;
+ while (len--)
+ {
+ byte inbyte = *addr++;
+ for (byte i = 8; i; i--)
+ {
+ byte mix = (crc ^ inbyte) & 0x01;
+ crc >>= 1;
+ if (mix)
+ crc ^= 0x8C;
+ inbyte >>= 1;
+ } // end of for
+ } // end of while
+ return crc;
+} // end of crc8
+
+void RS485::sendComplemented( const byte what)
+{
+ byte c ;
+ // first nibble
+ c = what >> 4;
+ putc((c << 4) | (c ^ 0x0F));
+
+ // second nibble
+ c = what & 0x0F;
+ putc((c << 4) | (c ^ 0x0F));
+} // end of sendComplemented
+
+
+void RS485::sendMsg(const byte * data, const byte length)
+{
+ putc(STX); // STX
+ for (byte i = 0; i < length; i++)
+ sendComplemented (data[i]);
+ putc(ETX); // ETX
+ sendComplemented(crc8(data, length));
+} // end of sendMsg
+
+// receive a message, maximum "length" bytes, timeout after "timeout" clock_mseconds
+// if nothing received, or an error (eg. bad CRC, bad data) return 0
+// otherwise, returns length of received data
+byte RS485::recvMsg (byte * data, // buffer to receive into
+ const byte length, // maximum buffer size
+ unsigned long timeout) // clock_mseconds before timing out
+ {
+
+ unsigned long start_time = lapse.read_ms();
+
+ bool have_stx = false;
+
+ // variables below are set when we get an STX
+ bool have_etx;
+ byte input_pos;
+ bool first_nibble;
+ byte current_byte;
+
+ while (lapse.read_ms() - start_time < timeout)
+ {
+ if (readable() > 0)
+ {
+ byte inByte = getc();
+
+ switch (inByte)
+ {
+
+ case STX: // start of text
+ have_stx = true;
+ have_etx = false;
+ input_pos = 0;
+ first_nibble = true;
+ start_time = lapse.read_ms(); // reset timeout period
+ break;
+
+ case ETX: // end of text
+ have_etx = true;
+ break;
+
+ default:
+ // wait until packet officially starts
+ if (!have_stx)
+ break;
+
+ // check byte is in valid form (4 bits followed by 4 bits complemented)
+ if ((inByte >> 4) != ((inByte & 0x0F) ^ 0x0F) )
+ return 0; // bad character
+
+ // convert back
+ inByte >>= 4;
+
+ // high-order nibble?
+ if (first_nibble)
+ {
+ current_byte = inByte;
+ first_nibble = false;
+ break;
+ } // end of first nibble
+
+ // low-order nibble
+ current_byte <<= 4;
+ current_byte |= inByte;
+ first_nibble = true;
+
+ // if we have the ETX this must be the CRC
+ if (have_etx)
+ {
+ if (crc8 (data, input_pos) != current_byte)
+ return 0; // bad crc
+ return input_pos; // return received length
+ } // end if have ETX already
+
+ // keep adding if not full
+ if (input_pos < length)
+ data [input_pos++] = current_byte;
+ else
+ return 0; // overflow
+ break;
+
+ } // end of switch
+ } // end of incoming data
+ } // end of while not timed out
+
+ return 0; // timeout
+} // end of recvMsg
+
\ No newline at end of file