modbus
- ModbusASCLL
- ModbusRTU
- 二进制编码
- CRC错误校验
- ModbusTCP/IP
RTU
Modbus-RTU模式是指当控制器设为在Modbus网络上以RTU(远程终端模式)模式通信,在消息中的每个8Bit包含两个4Bit的十六进制字符。
1、信息帧发送至少要以3.5个字符时间的停顿间隔开始。在最后一个字符传输字符之后,一个至少3.5个字符时间的停顿标定了信息帧的结束。一个新的信息帧可在此停顿之后开始。如果一个新消息在小于3.5个字符时间内接着前个消息开始,接受的设备将认为它是前一信息帧的延续,这将导致CRC码的值出错。
2、整个信息帧必须作为一连续的流传输。如果在帧完成之前有超过1.5字符时间的停顿时间,接受设备将刷新不完整的信息帧并认为存在丢包现象。
功能码
- 01 读线圈状态 位操作 读单个或多个
- 02 读离散输入状态 位操作 读单个或多个
- 03 读保持寄存器 字操作 读单个或多个
- 04 读输入寄存器 字操作 读单个或多个
- 05 写单个线圈 位操作 单个
- 06 写单个保持寄存器 字操作 单个
- 15 写多个线圈 位操作 多个
- 16 写多个保持寄存器 字操作 多个
example code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#include "DHT.h" #include <HardwareSerial.h>
#define DHTPIN 4 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE);
HardwareSerial SerialPort(1); #define bufferSize 255 #define baudrate 9600 #define slaveID 0x07 #define modbusDataSize 100 #define N 5
void setup() { Serial.begin(115200); Serial1.begin(9600, SERIAL_8N1, 35, 33); pinMode(32,OUTPUT); digitalWrite(32, LOW); dht.begin(); }
void loop() { unsigned int characterTime; unsigned char frame[bufferSize]; unsigned int receivedCrc; unsigned char address=0; unsigned char temp_h; unsigned char temp_l; float h = dht.readHumidity(); float t = dht.readTemperature(); float f = dht.readTemperature(true); if (isnan(h) || isnan(t) || isnan(f)) { Serial.println(F("Failed to read from DHT sensor!")); return; } temp_h=(unsigned char ) t; temp_l=0x00; delay(100);
characterTime = 15000000/baudrate;
while(Serial1.available()>0) { if(address<bufferSize) { frame[address]=Serial1.read(); Serial.write(frame[address]); address++; } else { Serial1.read(); } delayMicroseconds(characterTime); if(Serial1.available()==0) { unsigned short internalCrc = ModRTU_CRC((char*)frame, address-2); internalCrc >> 1; unsigned char high = internalCrc&0xFF; unsigned char low = internalCrc>>8; Serial.write(&frame[0], N+2); if(low==frame[address - 1]&&high==frame[address - 2]) { unsigned char slaveCode = frame[0]; if(slaveCode==slaveID||slaveCode==0) { unsigned char funcCode = frame[1]; if(funcCode==3) { frame[2] = 0x02; frame[3] = temp_h; frame[4] = temp_l; } } } internalCrc = ModRTU_CRC((char*)frame, N); internalCrc >> 1; frame[N] = internalCrc&0xFF; frame[N+1] = internalCrc>>8; digitalWrite(32, HIGH); Serial1.write(&frame[0], N+2); Serial.write(&frame[0], N+2); delay(10); digitalWrite(32, LOW); } } }
unsigned int ModRTU_CRC(char * buf, int len) { unsigned int crc = 0xFFFF; for (int pos = 0; pos < len; pos++) { crc ^= (unsigned int)buf[pos]; for (int i = 8; i != 0; i--) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else crc >>= 1; } } return crc; }
|