-
Notifications
You must be signed in to change notification settings - Fork 0
/
Modbus.h
272 lines (225 loc) · 8.25 KB
/
Modbus.h
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/** \file Modbus.h
* \brief Modbus RTU模式下数据包处理头文件
* \author 何亚红
* \version 20220203
* \date 2022
* \copyright MIT License.
*/
#ifndef __MODBUS_H__
#define __MODBUS_H__
#include "stdint.h"
#include "stdbool.h"
#include "stdlib.h"
#include "string.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MODBUS_BROADCAST_ADDRESS 0
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
* Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)
* (chapter 6 section 11 page 29)
* Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)
*/
#define MODBUS_MAX_READ_BITS 2000
#define MODBUS_MAX_WRITE_BITS 1968
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
* Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)
* (chapter 6 section 12 page 31)
* Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)
* (chapter 6 section 17 page 38)
* Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)
*/
#define MODBUS_MAX_READ_REGISTERS 125
#define MODBUS_MAX_WRITE_REGISTERS 123
#define MODBUS_MAX_WR_WRITE_REGISTERS 121
#define MODBUS_MAX_WR_READ_REGISTERS 125
/* The size of the MODBUS PDU is limited by the size constraint inherited from
* the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256
* bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server
* address (1 byte) - CRC (2 bytes) = 253 bytes.
*/
#define MODBUS_MAX_PDU_LENGTH 253
/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
* RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
*/
#define MODBUS_RTU_MAX_ADU_LENGTH 256
/** \brief 检查一帧数据的crc
*
* \param payload 整帧数据(包含CRC)的指针
* \param payload_length 长度(包含CRC)
* \return CRC是否通过
*
*/
bool Modbus_Payload_Check_CRC(uint8_t *payload,size_t payload_length);
/** \brief 在数据帧末尾的添加crc校验
*
* \param payload 整帧数据的指针,需要在末尾留两个字节以填写CRC
* \param payload_length 长度(包含CRC)
* \return 是否调用成功
*
*/
bool Modbus_Payload_Append_CRC(uint8_t *payload,size_t payload_length);
typedef struct
{
uint8_t slave_addr;/**< 从机地址,主要指本从机地址 */
/** \brief 串口输出函数,当解析完成后,将调用此函数输出数据,不可为NULL。
*
* \param data 串口输出数据的指针
* \param data_length 串口输出数据长度
* \return
*
*/
void (*output)(uint8_t *data,size_t data_length);
/** \brief 读取输入点(线圈)
*
* \param addr 地址
* \return bool 当前状态
*
*/
bool (*read_IX)(size_t addr);
/** \brief 写输出线圈
*
* \param addr 地址
* \param data 数据,数据定义查看Modbus协议定义
* \return
*
*/
void (*write_OX)(size_t addr,uint16_t data);
/** \brief 读输出线圈
*
* \param addr 地址
* \return 当前状态
*
*/
bool (*read_OX)(size_t addr);
/** \brief 读保持寄存器
*
* \param addr 地址
* \return 数据
*
*/
uint16_t (*read_hold_register)(size_t addr);
/** \brief 写保持寄存器
*
* \param addr 地址
* \param data 数据
* \return
*
*/
void (*write_hold_register)(size_t addr,uint16_t data);
/** \brief 读输入寄存器
*
* \param addr 地址
* \return 数据
*
*/
uint16_t (*read_input_register)(size_t addr);
} modbus_slave_context_t/**< 从机的上下文结构定义 */;
/** \brief Modbus从机解析输入。
* 当从机接收到一帧数据后,调用此函数。
* 此函数会自动调用相关回调函数完成Modbus输出。
* \param ctx 上下文指针,需要自行定义
* \param input_data 输入数据指针
* \param input_data_length 输入数据长度
* \param buff 缓冲(存放临时数据)
* \param buff_length 缓冲长度(需大于等于输入数据长度,足够存放输出数据)
* \return 是否成功执行
*
*/
bool Modbus_Slave_Parse_Input(modbus_slave_context_t *ctx,uint8_t *input_data,size_t input_data_length,uint8_t *buff,size_t buff_length);
typedef struct
{
uint8_t slave_addr;/**< 从机地址,主要指与此主机通信的从机地址 */
/** \brief 串口输出函数,当解析完成后,将调用此函数输出数据,不可为NULL。
*
* \param data 串口输出数据的指针
* \param data_length 串口输出数据长度
* \return
*
*/
void (*output)(uint8_t *data,size_t data_length);
/** \brief 请求数据(读串口输入),当Modbus请求发出后,会调用此函数等待从机回应,不可为NULL。
*
* \param data 请求数据的指针
* \param data_length 请求数据的长度(最大)
* \return size_t 成功读取的数据长度
*
*/
size_t (*request_reply)(uint8_t *data,size_t data_length);
} modbus_master_context_t/**< 主机的上下文结构定义 */;
/** \brief Modbus主机读取输入点
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待读取的数据指针
* \param number 待读取数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Read_IX(modbus_master_context_t *ctx,uint16_t start_addr,bool *data,size_t number,uint8_t *buff,size_t buff_length);
/** \brief Modbus主机读取输出线圈
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待读取的数据指针
* \param number 待读取数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Read_OX(modbus_master_context_t *ctx,uint16_t start_addr,bool *data,size_t number,uint8_t *buff,size_t buff_length);
/** \brief Modbus主机读取保持寄存器
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待读取的数据指针
* \param number 待读取数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Read_Hold_Register(modbus_master_context_t *ctx,uint16_t start_addr,uint16_t *data,size_t number,uint8_t *buff,size_t buff_length);
/** \brief Modbus主机读取输入寄存器
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待读取的数据指针
* \param number 待读取数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Read_Input_Register(modbus_master_context_t *ctx,uint16_t start_addr,uint16_t *data,size_t number,uint8_t *buff,size_t buff_length);
/** \brief Modbus主机写输出线圈
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待写入的数据指针
* \param number 待写入数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Write_OX(modbus_master_context_t *ctx,uint16_t start_addr,bool *data,size_t number,uint8_t *buff,size_t buff_length);
/** \brief Modbus主机写保持寄存器
*
* \param ctx 上下文指针,需要自行定义
* \param start_addr 起始地址(寻址地址)
* \param data 待写入的数据指针
* \param number 待写入数据长度
* \param buff 缓冲,用于发送和接收数据,尽量大
* \param buff_length 缓冲长度
* \return 是否成功执行
*
*/
bool Modbus_Master_Write_Hold_Register(modbus_master_context_t *ctx,uint16_t start_addr,uint16_t *data,size_t number,uint8_t *buff,size_t buff_length);
#ifdef __cplusplus
}
#endif
#endif