Testing Modbus RS485 commands
Dependencies: mbed BufferedSerial
RS485.h@4:6a8a69b660c2, 2017-05-21 (annotated)
- Committer:
- Allar
- Date:
- Sun May 21 20:41:37 2017 +0000
- Revision:
- 4:6a8a69b660c2
- Parent:
- 3:9af77202cc27
Published
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Allar | 0:dccd2df6a07c | 1 | |
Allar | 0:dccd2df6a07c | 2 | /** |
Allar | 0:dccd2df6a07c | 3 | * @file RS485.h |
Allar | 0:dccd2df6a07c | 4 | * @brief RS485 protocol - using half duplex method |
Allar | 0:dccd2df6a07c | 5 | * @author Aaron Allar |
Allar | 0:dccd2df6a07c | 6 | * @version 1.0 |
Allar | 0:dccd2df6a07c | 7 | * @see |
Allar | 0:dccd2df6a07c | 8 | * |
Allar | 0:dccd2df6a07c | 9 | * based on this method https://www.gammon.com.au/forum/?id=11428 |
Allar | 0:dccd2df6a07c | 10 | * |
Allar | 0:dccd2df6a07c | 11 | * Can send from 1 to 255 bytes from one node to another with: |
Allar | 0:dccd2df6a07c | 12 | * |
Allar | 0:dccd2df6a07c | 13 | * Packet start indicator (STX) |
Allar | 0:dccd2df6a07c | 14 | * Each data byte is doubled and inverted to check validity |
Allar | 0:dccd2df6a07c | 15 | * Packet end indicator (ETX) |
Allar | 0:dccd2df6a07c | 16 | * Packet CRC (checksum) |
Allar | 0:dccd2df6a07c | 17 | */ |
Allar | 0:dccd2df6a07c | 18 | |
Allar | 0:dccd2df6a07c | 19 | |
Allar | 0:dccd2df6a07c | 20 | |
Allar | 0:dccd2df6a07c | 21 | #ifndef RS485_H |
Allar | 0:dccd2df6a07c | 22 | #define RS485_H |
Allar | 1:f7cead04d73e | 23 | |
Allar | 1:f7cead04d73e | 24 | #include "BufferedSerial.h" |
Allar | 0:dccd2df6a07c | 25 | #include "mbed.h" |
Allar | 0:dccd2df6a07c | 26 | |
Allar | 4:6a8a69b660c2 | 27 | /** RS485 Library |
Allar | 0:dccd2df6a07c | 28 | * |
Allar | 4:6a8a69b660c2 | 29 | * Can send from 1 to 255 bytes from one node to another with: |
Allar | 4:6a8a69b660c2 | 30 | * |
Allar | 4:6a8a69b660c2 | 31 | * Packet start indicator (STX) |
Allar | 4:6a8a69b660c2 | 32 | * Each data byte is doubled and inverted to check validity |
Allar | 4:6a8a69b660c2 | 33 | * Packet end indicator (ETX) |
Allar | 4:6a8a69b660c2 | 34 | * Packet CRC (checksum) |
Allar | 4:6a8a69b660c2 | 35 | * |
Allar | 4:6a8a69b660c2 | 36 | * Using MAX485 modules or the MAX485 CSA+ |
Allar | 0:dccd2df6a07c | 37 | * |
Allar | 0:dccd2df6a07c | 38 | * Example: |
Allar | 0:dccd2df6a07c | 39 | * @code |
Allar | 0:dccd2df6a07c | 40 | * #include "mbed.h" |
Allar | 0:dccd2df6a07c | 41 | * #include <RS485.h> |
Allar | 0:dccd2df6a07c | 42 | * Serial pc(USBTX, USBRX); |
Allar | 3:9af77202cc27 | 43 | * RS485 RS485(PC_10,PC_11,PB_3); // Tx, Rx , !RE and DE MAX485 pin |
Allar | 0:dccd2df6a07c | 44 | * |
Allar | 3:9af77202cc27 | 45 | * DigitalOut ho(PB_3); // this pin should be connected to !RE and DE |
Allar | 0:dccd2df6a07c | 46 | * typedef uint8_t byte; |
Allar | 0:dccd2df6a07c | 47 | * |
Allar | 0:dccd2df6a07c | 48 | * byte regvalue[9]; |
Allar | 0:dccd2df6a07c | 49 | * byte data[9] = {0x01,0x04,0x00,0x48,0x00,0x02,0xf1,0xdd};//your data |
Allar | 0:dccd2df6a07c | 50 | * int main() |
Allar | 0:dccd2df6a07c | 51 | * { |
Allar | 0:dccd2df6a07c | 52 | * pc.printf("main\n"); |
Allar | 0:dccd2df6a07c | 53 | * while(1) { |
Allar | 0:dccd2df6a07c | 54 | * pc.printf("Starting\n"); |
Allar | 3:9af77202cc27 | 55 | * ho = 1; // Enable sending on MAX485 |
Allar | 0:dccd2df6a07c | 56 | * RS485.sendMsg(data,sizeof(data)); |
Allar | 0:dccd2df6a07c | 57 | * wait_ms(600); // Must wait for all the data to be sent |
Allar | 3:9af77202cc27 | 58 | * ho = 0; // Enable receiving on MAX485 |
Allar | 0:dccd2df6a07c | 59 | * pc.printf("Getting data\n"); |
Allar | 0:dccd2df6a07c | 60 | * if(RS485.readable() >0){ |
Allar | 0:dccd2df6a07c | 61 | * memset(regvalue,0,sizeof(regvalue)); |
Allar | 0:dccd2df6a07c | 62 | * wait_ms(200); |
Allar | 0:dccd2df6a07c | 63 | * RS485.recvMsg(regvalue,sizeof(data),500); |
Allar | 0:dccd2df6a07c | 64 | * wait_ms(200); |
Allar | 0:dccd2df6a07c | 65 | * for (int count = 0; count < 9; count++) { |
Allar | 0:dccd2df6a07c | 66 | * pc.printf("%X - ", regvalue[count]); |
Allar | 0:dccd2df6a07c | 67 | * } |
Allar | 0:dccd2df6a07c | 68 | * }else printf("No Data\n"); |
Allar | 0:dccd2df6a07c | 69 | * printf("Done\n"); |
Allar | 0:dccd2df6a07c | 70 | * wait_ms(1000); |
Allar | 0:dccd2df6a07c | 71 | * } |
Allar | 0:dccd2df6a07c | 72 | * } |
Allar | 0:dccd2df6a07c | 73 | * @endcode |
Allar | 0:dccd2df6a07c | 74 | */ |
Allar | 0:dccd2df6a07c | 75 | |
Allar | 0:dccd2df6a07c | 76 | |
Allar | 0:dccd2df6a07c | 77 | /** |
Allar | 0:dccd2df6a07c | 78 | * @class RS485 |
Allar | 4:6a8a69b660c2 | 79 | * @communicating |
Allar | 0:dccd2df6a07c | 80 | */ |
Allar | 0:dccd2df6a07c | 81 | |
Allar | 0:dccd2df6a07c | 82 | class RS485 : public BufferedSerial |
Allar | 0:dccd2df6a07c | 83 | { |
Allar | 0:dccd2df6a07c | 84 | private: |
Allar | 0:dccd2df6a07c | 85 | typedef unsigned int word; |
Allar | 0:dccd2df6a07c | 86 | typedef uint8_t byte; |
Allar | 0:dccd2df6a07c | 87 | typedef uint8_t boolean; |
Allar | 0:dccd2df6a07c | 88 | typedef void (*voidFuncPtr)(void); |
Allar | 0:dccd2df6a07c | 89 | |
Allar | 0:dccd2df6a07c | 90 | public: |
Allar | 0:dccd2df6a07c | 91 | /** Create a BufferedSerial port, connected to the specified transmit and receive pins |
Allar | 0:dccd2df6a07c | 92 | * @param tx Transmit pin |
Allar | 0:dccd2df6a07c | 93 | * @param rx Receive pin |
Allar | 3:9af77202cc27 | 94 | * @param dere Enable pin, this pin should be connected to !RE and DE |
Allar | 0:dccd2df6a07c | 95 | * @note uses BufferedSerial |
Allar | 0:dccd2df6a07c | 96 | */ |
Allar | 0:dccd2df6a07c | 97 | RS485(PinName tx, PinName rx, PinName dere); |
Allar | 0:dccd2df6a07c | 98 | |
Allar | 0:dccd2df6a07c | 99 | /** calculate 8-bit CRC |
Allar | 0:dccd2df6a07c | 100 | * cyclic redundancy check |
Allar | 2:2701d79eba7c | 101 | * @param addr byte pointer of information to use (typical an byte array) |
Allar | 1:f7cead04d73e | 102 | * @param len length of byte of information were converting |
Allar | 0:dccd2df6a07c | 103 | * @return the CRC byte |
Allar | 0:dccd2df6a07c | 104 | */ |
Allar | 0:dccd2df6a07c | 105 | static byte crc8 (const byte *addr, byte len); |
Allar | 0:dccd2df6a07c | 106 | |
Allar | 0:dccd2df6a07c | 107 | /** sendComplemented byte |
Allar | 0:dccd2df6a07c | 108 | * send a byte complemented, repeated |
Allar | 0:dccd2df6a07c | 109 | * only values sent would be (in hex): |
Allar | 0:dccd2df6a07c | 110 | * 0F, 1E, 2D, 3C, 4B, 5A, 69, 78, 87, 96, A5, B4, C3, D2, E1, F0 |
Allar | 0:dccd2df6a07c | 111 | * @what the byte to complement |
Allar | 0:dccd2df6a07c | 112 | */ |
Allar | 0:dccd2df6a07c | 113 | void sendComplemented (const byte what); |
Allar | 0:dccd2df6a07c | 114 | |
Allar | 0:dccd2df6a07c | 115 | /** send message |
Allar | 0:dccd2df6a07c | 116 | * cyclic redundancy check |
Allar | 1:f7cead04d73e | 117 | * @param data the data to be sent through RS485 |
Allar | 1:f7cead04d73e | 118 | * @param length length of the data |
Allar | 0:dccd2df6a07c | 119 | * @note puts STX at start, ETX at end, and add CRC |
Allar | 0:dccd2df6a07c | 120 | */ |
Allar | 0:dccd2df6a07c | 121 | void sendMsg (const byte * data, const byte length); |
Allar | 0:dccd2df6a07c | 122 | |
Allar | 0:dccd2df6a07c | 123 | /** receive message |
Allar | 0:dccd2df6a07c | 124 | * reads serial port and populates data |
Allar | 1:f7cead04d73e | 125 | * @param data buffer to receive into |
Allar | 1:f7cead04d73e | 126 | * @param length length of the data |
Allar | 1:f7cead04d73e | 127 | * @param timeout clock_mseconds before timing out |
Allar | 1:f7cead04d73e | 128 | * @return the number of bytes received |
Allar | 0:dccd2df6a07c | 129 | * |
Allar | 0:dccd2df6a07c | 130 | */ |
Allar | 0:dccd2df6a07c | 131 | byte recvMsg (byte * data, const byte length, unsigned long timeout); |
Allar | 0:dccd2df6a07c | 132 | |
Allar | 0:dccd2df6a07c | 133 | |
Allar | 0:dccd2df6a07c | 134 | }; |
Allar | 0:dccd2df6a07c | 135 | #endif |