108 lines
2.6 KiB
C
108 lines
2.6 KiB
C
|
/*
|
||
|
RS485 protocol library - non-blocking.
|
||
|
|
||
|
Devised and written by Nick Gammon.
|
||
|
Date: 4 December 2012
|
||
|
Version: 1.0
|
||
|
|
||
|
Licence: Released for public use.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "Arduino.h"
|
||
|
|
||
|
|
||
|
class RS485
|
||
|
{
|
||
|
|
||
|
typedef size_t (*WriteCallback) (const byte what); // send a byte to serial port
|
||
|
typedef int (*AvailableCallback) (); // return number of bytes available
|
||
|
typedef int (*ReadCallback) (); // read a byte from serial port
|
||
|
|
||
|
enum {
|
||
|
STX = '\2', // start of text
|
||
|
ETX = '\3' // end of text
|
||
|
}; // end of enum
|
||
|
|
||
|
// callback functions to do reading/writing
|
||
|
ReadCallback fReadCallback_;
|
||
|
AvailableCallback fAvailableCallback_;
|
||
|
WriteCallback fWriteCallback_;
|
||
|
|
||
|
// where we save incoming stuff
|
||
|
byte * data_;
|
||
|
|
||
|
// how much data is in the buffer
|
||
|
const int bufferSize_;
|
||
|
|
||
|
// this is true once we have valid data in buf
|
||
|
bool available_;
|
||
|
|
||
|
// an STX (start of text) signals a packet start
|
||
|
bool haveSTX_;
|
||
|
|
||
|
// count of errors
|
||
|
unsigned long errorCount_;
|
||
|
|
||
|
// variables below are set when we get an STX
|
||
|
bool haveETX_;
|
||
|
byte inputPos_;
|
||
|
byte currentByte_;
|
||
|
bool firstNibble_;
|
||
|
unsigned long startTime_;
|
||
|
|
||
|
// helper private functions
|
||
|
byte crc8 (const byte *addr, byte len);
|
||
|
void sendComplemented (const byte what);
|
||
|
|
||
|
public:
|
||
|
|
||
|
// constructor
|
||
|
RS485 (ReadCallback fReadCallback,
|
||
|
AvailableCallback fAvailableCallback,
|
||
|
WriteCallback fWriteCallback,
|
||
|
const byte bufferSize) :
|
||
|
fReadCallback_ (fReadCallback),
|
||
|
fAvailableCallback_ (fAvailableCallback),
|
||
|
fWriteCallback_ (fWriteCallback),
|
||
|
data_ (NULL),
|
||
|
bufferSize_ (bufferSize)
|
||
|
{}
|
||
|
|
||
|
// destructor - frees memory used
|
||
|
~RS485 () { stop (); }
|
||
|
|
||
|
// allocate memory for buf_
|
||
|
void begin ();
|
||
|
|
||
|
// free memory in buf_
|
||
|
void stop ();
|
||
|
|
||
|
// handle incoming data, return true if packet ready
|
||
|
bool update ();
|
||
|
|
||
|
// reset to no incoming data (eg. after a timeout)
|
||
|
void reset ();
|
||
|
|
||
|
// send data
|
||
|
void sendMsg (const byte * data, const byte length);
|
||
|
|
||
|
// returns true if packet available
|
||
|
bool available () const { return available_; };
|
||
|
|
||
|
// once available, returns the address of the current message
|
||
|
byte * getData () const { return data_; }
|
||
|
byte getLength () const { return inputPos_; }
|
||
|
|
||
|
// return how many errors we have had
|
||
|
unsigned long getErrorCount () const { return errorCount_; }
|
||
|
|
||
|
// return when last packet started
|
||
|
unsigned long getPacketStartTime () const { return startTime_; }
|
||
|
|
||
|
// return true if a packet has started to be received
|
||
|
bool isPacketStarted () const { return haveSTX_; }
|
||
|
|
||
|
}; // end of class RS485
|
||
|
|