test
Dependencies: mbed Watchdog stm32-sensor-base2
RS485/RS485.cpp@19:7935ca386e13, 2021-11-05 (annotated)
- Committer:
- ruslanbredun
- Date:
- Fri Nov 05 14:39:08 2021 +0000
- Revision:
- 19:7935ca386e13
- Parent:
- 10:0b7f23df690a
LastFirmWare05/11/21;
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; |
ruslanbredun | 9:859bcb293e46 | 9 | const byte STX = '\4'; |
ommpy | 10:0b7f23df690a | 10 | const byte ETX = '\8'; |
nestedslk | 4:f6e22dd39313 | 11 | |
nestedslk | 4:f6e22dd39313 | 12 | RS485::RS485(PinName tx, PinName rx, PinName dere) |
ruslanbredun | 9:859bcb293e46 | 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++) |
ruslanbredun | 9:859bcb293e46 | 54 | //sendComplemented (data[i]); |
ruslanbredun | 9:859bcb293e46 | 55 | putc(data[i]); |
ruslanbredun | 9:859bcb293e46 | 56 | //putc(ETX); // ETX |
ruslanbredun | 9:859bcb293e46 | 57 | //sendComplemented(crc8(data, length)); |
ruslanbredun | 9:859bcb293e46 | 58 | putc(crc8(data, length)); |
nestedslk | 4:f6e22dd39313 | 59 | } // end of sendMsg |
nestedslk | 4:f6e22dd39313 | 60 | |
nestedslk | 4:f6e22dd39313 | 61 | // receive a message, maximum "length" bytes, timeout after "timeout" clock_mseconds |
nestedslk | 4:f6e22dd39313 | 62 | // if nothing received, or an error (eg. bad CRC, bad data) return 0 |
nestedslk | 4:f6e22dd39313 | 63 | // otherwise, returns length of received data |
nestedslk | 4:f6e22dd39313 | 64 | byte RS485::recvMsg (byte * data, // buffer to receive into |
nestedslk | 4:f6e22dd39313 | 65 | const byte length, // maximum buffer size |
nestedslk | 4:f6e22dd39313 | 66 | unsigned long timeout) // clock_mseconds before timing out |
nestedslk | 4:f6e22dd39313 | 67 | { |
nestedslk | 4:f6e22dd39313 | 68 | |
nestedslk | 4:f6e22dd39313 | 69 | unsigned long start_time = lapse.read_ms(); |
nestedslk | 4:f6e22dd39313 | 70 | |
nestedslk | 4:f6e22dd39313 | 71 | bool have_stx = false; |
nestedslk | 4:f6e22dd39313 | 72 | |
nestedslk | 4:f6e22dd39313 | 73 | // variables below are set when we get an STX |
nestedslk | 4:f6e22dd39313 | 74 | bool have_etx; |
nestedslk | 4:f6e22dd39313 | 75 | byte input_pos; |
nestedslk | 4:f6e22dd39313 | 76 | bool first_nibble; |
nestedslk | 4:f6e22dd39313 | 77 | byte current_byte; |
nestedslk | 4:f6e22dd39313 | 78 | |
nestedslk | 4:f6e22dd39313 | 79 | while (lapse.read_ms() - start_time < timeout) |
nestedslk | 4:f6e22dd39313 | 80 | { |
nestedslk | 4:f6e22dd39313 | 81 | if (readable() > 0) |
nestedslk | 4:f6e22dd39313 | 82 | { |
nestedslk | 4:f6e22dd39313 | 83 | byte inByte = getc(); |
nestedslk | 4:f6e22dd39313 | 84 | |
nestedslk | 4:f6e22dd39313 | 85 | switch (inByte) |
nestedslk | 4:f6e22dd39313 | 86 | { |
nestedslk | 4:f6e22dd39313 | 87 | |
nestedslk | 4:f6e22dd39313 | 88 | case STX: // start of text |
nestedslk | 4:f6e22dd39313 | 89 | have_stx = true; |
nestedslk | 4:f6e22dd39313 | 90 | have_etx = false; |
nestedslk | 4:f6e22dd39313 | 91 | input_pos = 0; |
nestedslk | 4:f6e22dd39313 | 92 | first_nibble = true; |
nestedslk | 4:f6e22dd39313 | 93 | start_time = lapse.read_ms(); // reset timeout period |
ruslanbredun | 9:859bcb293e46 | 94 | data[0] = STX; |
nestedslk | 4:f6e22dd39313 | 95 | break; |
nestedslk | 4:f6e22dd39313 | 96 | |
nestedslk | 4:f6e22dd39313 | 97 | default: |
nestedslk | 4:f6e22dd39313 | 98 | // wait until packet officially starts |
nestedslk | 4:f6e22dd39313 | 99 | if (!have_stx) |
nestedslk | 4:f6e22dd39313 | 100 | break; |
nestedslk | 4:f6e22dd39313 | 101 | |
nestedslk | 4:f6e22dd39313 | 102 | // check byte is in valid form (4 bits followed by 4 bits complemented) |
nestedslk | 4:f6e22dd39313 | 103 | if ((inByte >> 4) != ((inByte & 0x0F) ^ 0x0F) ) |
nestedslk | 4:f6e22dd39313 | 104 | return 0; // bad character |
nestedslk | 4:f6e22dd39313 | 105 | |
nestedslk | 4:f6e22dd39313 | 106 | // convert back |
nestedslk | 4:f6e22dd39313 | 107 | inByte >>= 4; |
nestedslk | 4:f6e22dd39313 | 108 | |
nestedslk | 4:f6e22dd39313 | 109 | // high-order nibble? |
nestedslk | 4:f6e22dd39313 | 110 | if (first_nibble) |
nestedslk | 4:f6e22dd39313 | 111 | { |
nestedslk | 4:f6e22dd39313 | 112 | current_byte = inByte; |
nestedslk | 4:f6e22dd39313 | 113 | first_nibble = false; |
nestedslk | 4:f6e22dd39313 | 114 | break; |
nestedslk | 4:f6e22dd39313 | 115 | } // end of first nibble |
nestedslk | 4:f6e22dd39313 | 116 | |
nestedslk | 4:f6e22dd39313 | 117 | // low-order nibble |
nestedslk | 4:f6e22dd39313 | 118 | current_byte <<= 4; |
nestedslk | 4:f6e22dd39313 | 119 | current_byte |= inByte; |
nestedslk | 4:f6e22dd39313 | 120 | first_nibble = true; |
nestedslk | 4:f6e22dd39313 | 121 | |
nestedslk | 4:f6e22dd39313 | 122 | // if we have the ETX this must be the CRC |
nestedslk | 4:f6e22dd39313 | 123 | if (have_etx) |
nestedslk | 4:f6e22dd39313 | 124 | { |
nestedslk | 4:f6e22dd39313 | 125 | if (crc8 (data, input_pos) != current_byte) |
nestedslk | 4:f6e22dd39313 | 126 | return 0; // bad crc |
nestedslk | 4:f6e22dd39313 | 127 | return input_pos; // return received length |
nestedslk | 4:f6e22dd39313 | 128 | } // end if have ETX already |
nestedslk | 4:f6e22dd39313 | 129 | |
nestedslk | 4:f6e22dd39313 | 130 | // keep adding if not full |
nestedslk | 4:f6e22dd39313 | 131 | if (input_pos < length) |
nestedslk | 4:f6e22dd39313 | 132 | data [input_pos++] = current_byte; |
nestedslk | 4:f6e22dd39313 | 133 | else |
nestedslk | 4:f6e22dd39313 | 134 | return 0; // overflow |
nestedslk | 4:f6e22dd39313 | 135 | break; |
nestedslk | 4:f6e22dd39313 | 136 | |
nestedslk | 4:f6e22dd39313 | 137 | } // end of switch |
nestedslk | 4:f6e22dd39313 | 138 | } // end of incoming data |
nestedslk | 4:f6e22dd39313 | 139 | } // end of while not timed out |
nestedslk | 4:f6e22dd39313 | 140 | |
nestedslk | 4:f6e22dd39313 | 141 | return 0; // timeout |
nestedslk | 4:f6e22dd39313 | 142 | } // end of recvMsg |
nestedslk | 4:f6e22dd39313 | 143 |