test
Dependencies: mbed Watchdog stm32-sensor-base2
RS485/RS485.cpp@4:f6e22dd39313, 2020-07-18 (annotated)
- Committer:
- nestedslk
- Date:
- Sat Jul 18 14:59:04 2020 +0000
- Revision:
- 4:f6e22dd39313
- Parent:
- 2:b7fdc74e5c5d
- Child:
- 8:c3cffab85b0d
testing version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ommpy | 2:b7fdc74e5c5d | 1 | #include "RS485.h" |
nestedslk | 4:f6e22dd39313 | 2 | #include <stdarg.h> |
nestedslk | 4:f6e22dd39313 | 3 | |
nestedslk | 4:f6e22dd39313 | 4 | typedef unsigned int word; |
nestedslk | 4:f6e22dd39313 | 5 | typedef uint8_t byte; |
nestedslk | 4:f6e22dd39313 | 6 | typedef uint8_t boolean; |
nestedslk | 4:f6e22dd39313 | 7 | typedef void (*voidFuncPtr)(void); |
nestedslk | 4:f6e22dd39313 | 8 | Timer lapse; |
nestedslk | 4:f6e22dd39313 | 9 | const byte STX = '\2'; |
nestedslk | 4:f6e22dd39313 | 10 | const byte ETX = '\3'; |
nestedslk | 4:f6e22dd39313 | 11 | |
nestedslk | 4:f6e22dd39313 | 12 | RS485::RS485(PinName tx, PinName rx, PinName dere) |
nestedslk | 4:f6e22dd39313 | 13 | : BufferedSerial(tx, rx) |
nestedslk | 4:f6e22dd39313 | 14 | { |
nestedslk | 4:f6e22dd39313 | 15 | return; |
ommpy | 2:b7fdc74e5c5d | 16 | } |
nestedslk | 4:f6e22dd39313 | 17 | |
nestedslk | 4:f6e22dd39313 | 18 | |
nestedslk | 4:f6e22dd39313 | 19 | byte RS485::crc8(const byte *addr, byte len) |
nestedslk | 4:f6e22dd39313 | 20 | { |
nestedslk | 4:f6e22dd39313 | 21 | byte crc = 0; |
nestedslk | 4:f6e22dd39313 | 22 | while (len--) |
nestedslk | 4:f6e22dd39313 | 23 | { |
nestedslk | 4:f6e22dd39313 | 24 | byte inbyte = *addr++; |
nestedslk | 4:f6e22dd39313 | 25 | for (byte i = 8; i; i--) |
nestedslk | 4:f6e22dd39313 | 26 | { |
nestedslk | 4:f6e22dd39313 | 27 | byte mix = (crc ^ inbyte) & 0x01; |
nestedslk | 4:f6e22dd39313 | 28 | crc >>= 1; |
nestedslk | 4:f6e22dd39313 | 29 | if (mix) |
nestedslk | 4:f6e22dd39313 | 30 | crc ^= 0x8C; |
nestedslk | 4:f6e22dd39313 | 31 | inbyte >>= 1; |
nestedslk | 4:f6e22dd39313 | 32 | } // end of for |
nestedslk | 4:f6e22dd39313 | 33 | } // end of while |
nestedslk | 4:f6e22dd39313 | 34 | return crc; |
nestedslk | 4:f6e22dd39313 | 35 | } // end of crc8 |
nestedslk | 4:f6e22dd39313 | 36 | |
nestedslk | 4:f6e22dd39313 | 37 | void RS485::sendComplemented( const byte what) |
nestedslk | 4:f6e22dd39313 | 38 | { |
nestedslk | 4:f6e22dd39313 | 39 | byte c ; |
nestedslk | 4:f6e22dd39313 | 40 | // first nibble |
nestedslk | 4:f6e22dd39313 | 41 | c = what >> 4; |
nestedslk | 4:f6e22dd39313 | 42 | putc((c << 4) | (c ^ 0x0F)); |
nestedslk | 4:f6e22dd39313 | 43 | |
nestedslk | 4:f6e22dd39313 | 44 | // second nibble |
nestedslk | 4:f6e22dd39313 | 45 | c = what & 0x0F; |
nestedslk | 4:f6e22dd39313 | 46 | putc((c << 4) | (c ^ 0x0F)); |
nestedslk | 4:f6e22dd39313 | 47 | } // end of sendComplemented |
nestedslk | 4:f6e22dd39313 | 48 | |
nestedslk | 4:f6e22dd39313 | 49 | |
nestedslk | 4:f6e22dd39313 | 50 | void RS485::sendMsg(const byte * data, const byte length) |
nestedslk | 4:f6e22dd39313 | 51 | { |
nestedslk | 4:f6e22dd39313 | 52 | putc(STX); // STX |
nestedslk | 4:f6e22dd39313 | 53 | for (byte i = 0; i < length; i++) |
nestedslk | 4:f6e22dd39313 | 54 | sendComplemented (data[i]); |
nestedslk | 4:f6e22dd39313 | 55 | putc(ETX); // ETX |
nestedslk | 4:f6e22dd39313 | 56 | sendComplemented(crc8(data, length)); |
nestedslk | 4:f6e22dd39313 | 57 | } // end of sendMsg |
nestedslk | 4:f6e22dd39313 | 58 | |
nestedslk | 4:f6e22dd39313 | 59 | // receive a message, maximum "length" bytes, timeout after "timeout" clock_mseconds |
nestedslk | 4:f6e22dd39313 | 60 | // if nothing received, or an error (eg. bad CRC, bad data) return 0 |
nestedslk | 4:f6e22dd39313 | 61 | // otherwise, returns length of received data |
nestedslk | 4:f6e22dd39313 | 62 | byte RS485::recvMsg (byte * data, // buffer to receive into |
nestedslk | 4:f6e22dd39313 | 63 | const byte length, // maximum buffer size |
nestedslk | 4:f6e22dd39313 | 64 | unsigned long timeout) // clock_mseconds before timing out |
nestedslk | 4:f6e22dd39313 | 65 | { |
nestedslk | 4:f6e22dd39313 | 66 | |
nestedslk | 4:f6e22dd39313 | 67 | unsigned long start_time = lapse.read_ms(); |
nestedslk | 4:f6e22dd39313 | 68 | |
nestedslk | 4:f6e22dd39313 | 69 | bool have_stx = false; |
nestedslk | 4:f6e22dd39313 | 70 | |
nestedslk | 4:f6e22dd39313 | 71 | // variables below are set when we get an STX |
nestedslk | 4:f6e22dd39313 | 72 | bool have_etx; |
nestedslk | 4:f6e22dd39313 | 73 | byte input_pos; |
nestedslk | 4:f6e22dd39313 | 74 | bool first_nibble; |
nestedslk | 4:f6e22dd39313 | 75 | byte current_byte; |
nestedslk | 4:f6e22dd39313 | 76 | |
nestedslk | 4:f6e22dd39313 | 77 | while (lapse.read_ms() - start_time < timeout) |
nestedslk | 4:f6e22dd39313 | 78 | { |
nestedslk | 4:f6e22dd39313 | 79 | if (readable() > 0) |
nestedslk | 4:f6e22dd39313 | 80 | { |
nestedslk | 4:f6e22dd39313 | 81 | byte inByte = getc(); |
nestedslk | 4:f6e22dd39313 | 82 | |
nestedslk | 4:f6e22dd39313 | 83 | switch (inByte) |
nestedslk | 4:f6e22dd39313 | 84 | { |
nestedslk | 4:f6e22dd39313 | 85 | |
nestedslk | 4:f6e22dd39313 | 86 | case STX: // start of text |
nestedslk | 4:f6e22dd39313 | 87 | have_stx = true; |
nestedslk | 4:f6e22dd39313 | 88 | have_etx = false; |
nestedslk | 4:f6e22dd39313 | 89 | input_pos = 0; |
nestedslk | 4:f6e22dd39313 | 90 | first_nibble = true; |
nestedslk | 4:f6e22dd39313 | 91 | start_time = lapse.read_ms(); // reset timeout period |
nestedslk | 4:f6e22dd39313 | 92 | break; |
nestedslk | 4:f6e22dd39313 | 93 | |
nestedslk | 4:f6e22dd39313 | 94 | case ETX: // end of text |
nestedslk | 4:f6e22dd39313 | 95 | have_etx = true; |
nestedslk | 4:f6e22dd39313 | 96 | break; |
nestedslk | 4:f6e22dd39313 | 97 | |
nestedslk | 4:f6e22dd39313 | 98 | default: |
nestedslk | 4:f6e22dd39313 | 99 | // wait until packet officially starts |
nestedslk | 4:f6e22dd39313 | 100 | if (!have_stx) |
nestedslk | 4:f6e22dd39313 | 101 | break; |
nestedslk | 4:f6e22dd39313 | 102 | |
nestedslk | 4:f6e22dd39313 | 103 | // check byte is in valid form (4 bits followed by 4 bits complemented) |
nestedslk | 4:f6e22dd39313 | 104 | if ((inByte >> 4) != ((inByte & 0x0F) ^ 0x0F) ) |
nestedslk | 4:f6e22dd39313 | 105 | return 0; // bad character |
nestedslk | 4:f6e22dd39313 | 106 | |
nestedslk | 4:f6e22dd39313 | 107 | // convert back |
nestedslk | 4:f6e22dd39313 | 108 | inByte >>= 4; |
nestedslk | 4:f6e22dd39313 | 109 | |
nestedslk | 4:f6e22dd39313 | 110 | // high-order nibble? |
nestedslk | 4:f6e22dd39313 | 111 | if (first_nibble) |
nestedslk | 4:f6e22dd39313 | 112 | { |
nestedslk | 4:f6e22dd39313 | 113 | current_byte = inByte; |
nestedslk | 4:f6e22dd39313 | 114 | first_nibble = false; |
nestedslk | 4:f6e22dd39313 | 115 | break; |
nestedslk | 4:f6e22dd39313 | 116 | } // end of first nibble |
nestedslk | 4:f6e22dd39313 | 117 | |
nestedslk | 4:f6e22dd39313 | 118 | // low-order nibble |
nestedslk | 4:f6e22dd39313 | 119 | current_byte <<= 4; |
nestedslk | 4:f6e22dd39313 | 120 | current_byte |= inByte; |
nestedslk | 4:f6e22dd39313 | 121 | first_nibble = true; |
nestedslk | 4:f6e22dd39313 | 122 | |
nestedslk | 4:f6e22dd39313 | 123 | // if we have the ETX this must be the CRC |
nestedslk | 4:f6e22dd39313 | 124 | if (have_etx) |
nestedslk | 4:f6e22dd39313 | 125 | { |
nestedslk | 4:f6e22dd39313 | 126 | if (crc8 (data, input_pos) != current_byte) |
nestedslk | 4:f6e22dd39313 | 127 | return 0; // bad crc |
nestedslk | 4:f6e22dd39313 | 128 | return input_pos; // return received length |
nestedslk | 4:f6e22dd39313 | 129 | } // end if have ETX already |
nestedslk | 4:f6e22dd39313 | 130 | |
nestedslk | 4:f6e22dd39313 | 131 | // keep adding if not full |
nestedslk | 4:f6e22dd39313 | 132 | if (input_pos < length) |
nestedslk | 4:f6e22dd39313 | 133 | data [input_pos++] = current_byte; |
nestedslk | 4:f6e22dd39313 | 134 | else |
nestedslk | 4:f6e22dd39313 | 135 | return 0; // overflow |
nestedslk | 4:f6e22dd39313 | 136 | break; |
nestedslk | 4:f6e22dd39313 | 137 | |
nestedslk | 4:f6e22dd39313 | 138 | } // end of switch |
nestedslk | 4:f6e22dd39313 | 139 | } // end of incoming data |
nestedslk | 4:f6e22dd39313 | 140 | } // end of while not timed out |
nestedslk | 4:f6e22dd39313 | 141 | |
nestedslk | 4:f6e22dd39313 | 142 | return 0; // timeout |
nestedslk | 4:f6e22dd39313 | 143 | } // end of recvMsg |
nestedslk | 4:f6e22dd39313 | 144 |