-
Notifications
You must be signed in to change notification settings - Fork 190
/
Modbus.h
235 lines (196 loc) · 6.11 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
/*
* Modbus.h
*
* Created on: May 5, 2020
* Author: Alejandro Mera
*/
#ifndef THIRD_PARTY_MODBUS_INC_MODBUS_H_
#define THIRD_PARTY_MODBUS_INC_MODBUS_H_
#include <inttypes.h>
#include "main.h"
#include <stdbool.h>
#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#define ENABLE_USB_CDC 0 //Enable the USB CDC support and examples
#define T35 5
#define MAX_BUFFER 64 //!< maximum size for the communication buffer in bytes
#define TIMEOUT_MODBUS 1000
#define MAX_M_HANDLERS 2
#define MAX_TELEGRAMS 2 //Max number of Telegrams for master
/**
* @struct modbus_t
* @brief
* Master query structure:
* This includes all the necessary fields to make the Master generate a Modbus query.
* A Master may keep several of these structures and send them cyclically or
* use them according to program needs.
*/
typedef struct
{
uint8_t u8id; /*!< Slave address between 1 and 247. 0 means broadcast */
uint8_t u8fct; /*!< Function code: 1, 2, 3, 4, 5, 6, 15 or 16 */
uint16_t u16RegAdd; /*!< Address of the first register to access at slave/s */
uint16_t u16CoilsNo; /*!< Number of coils or registers to access */
uint16_t *au16reg; /*!< Pointer to memory image in master */
uint32_t *u32CurrentTask; /*!< Pointer to the task that will receive notifications from Modbus */
}
modbus_t;
enum
{
USART_HW = 1,
#if ENABLE_USB_CDC == 1
USB_CDC_HW = 2,
#endif
};
/**
* @struct modbusHandler_t
* @brief
* Modbus handler structure
* Contains all the variables required for Modbus daemon operation
*/
typedef struct
{
uint8_t uiModbusType;
UART_HandleTypeDef *port; //HAL Serial Port handler
uint8_t u8id; //!< 0=master, 1..247=slave number
GPIO_TypeDef* EN_Port; //!< flow control pin: 0=USB or RS-232 mode, >1=RS-485 mode
uint16_t EN_Pin; //!< flow control pin: 0=USB or RS-232 mode, >1=RS-485 mode
int8_t i8lastError;
uint8_t au8Buffer[MAX_BUFFER]; //Modbus buffer for communication
uint8_t u8BufferSize;
uint8_t u8lastRec;
uint16_t *au16regs;
uint16_t u16InCnt, u16OutCnt, u16errCnt; //keep statistics of Modbus traffic
uint16_t u16timeOut;
uint32_t u32time, u32timeOut, u32overTime;
uint16_t u16regsize;
uint8_t dataRX;
int8_t i8state;
//uint8_t u8exception;
//FreeRTOS components
//Queue Modbus RX
osMessageQueueId_t QueueModbusHandle;
//Queue Modbus Telegram
osMessageQueueId_t QueueTelegramHandle;
//Task Modbus slave
osThreadId_t myTaskModbusAHandle;
//Timer RX Modbus
xTimerHandle xTimerT35;
//Timer MasterTimeout
xTimerHandle xTimerTimeout;
//Semaphore for Modbus data
osSemaphoreId_t ModBusSphrHandle;
#if ENABLE_USB_CDC == 1
uint8_t u8TypeHW;
//int16_t i16LenRx;
#endif
}
modbusHandler_t;
enum
{
RESPONSE_SIZE = 6,
EXCEPTION_SIZE = 3,
CHECKSUM_SIZE = 2
};
enum
{
SLAVE_RTU = 3,
MASTER_RTU = 4
//SLAVE_TCP = 5,
//MASTER_TCP =6,
};
/**
* @enum MESSAGE
* @brief
* Indexes to telegram frame positions
*/
enum MESSAGE
{
ID = 0, //!< ID field
FUNC, //!< Function code position
ADD_HI, //!< Address high byte
ADD_LO, //!< Address low byte
NB_HI, //!< Number of coils or registers high byte
NB_LO, //!< Number of coils or registers low byte
BYTE_CNT //!< byte counter
};
/**
* @enum MB_FC
* @brief
* Modbus function codes summary.
* These are the implement function codes either for Master or for Slave.
*
* @see also fctsupported
* @see also modbus_t
*/
enum MB_FC
{
MB_FC_NONE = 0, /*!< null operator */
MB_FC_READ_COILS = 1, /*!< FCT=1 -> read coils or digital outputs */
MB_FC_READ_DISCRETE_INPUT = 2, /*!< FCT=2 -> read digital inputs */
MB_FC_READ_REGISTERS = 3, /*!< FCT=3 -> read registers or analog outputs */
MB_FC_READ_INPUT_REGISTER = 4, /*!< FCT=4 -> read analog inputs */
MB_FC_WRITE_COIL = 5, /*!< FCT=5 -> write single coil or output */
MB_FC_WRITE_REGISTER = 6, /*!< FCT=6 -> write single register */
MB_FC_WRITE_MULTIPLE_COILS = 15, /*!< FCT=15 -> write multiple coils or outputs */
MB_FC_WRITE_MULTIPLE_REGISTERS = 16 /*!< FCT=16 -> write multiple registers */
};
enum COM_STATES
{
COM_IDLE = 0,
COM_WAITING = 1
};
enum ERR_LIST
{
ERR_NOT_MASTER = -1,
ERR_POLLING = -2,
ERR_BUFF_OVERFLOW = -3,
ERR_BAD_CRC = -4,
ERR_EXCEPTION = -5,
ERR_BAD_SIZE = -6,
ERR_BAD_ADDRESS = -7,
ERR_TIME_OUT = -8,
ERR_BAD_SLAVE_ID = -9
};
enum
{
NO_REPLY = 255,
EXC_FUNC_CODE = 1,
EXC_ADDR_RANGE = 2,
EXC_REGS_QUANT = 3,
EXC_EXECUTE = 4
};
typedef union {
uint8_t u8[4];
uint16_t u16[2];
uint32_t u32;
} bytesFields ;
modbusHandler_t *mHandlers[MAX_M_HANDLERS];
// Function prototypes
void ModbusInit(modbusHandler_t * modH);
void ModbusStart(modbusHandler_t * modH);
#if ENABLE_USB_CDC == 1
void ModbusStartCDC(modbusHandler_t * modH);
#endif
void setTimeOut( uint16_t u16timeOut); //!<write communication watch-dog timer
uint16_t getTimeOut(); //!<get communication watch-dog timer value
bool getTimeOutState(); //!<get communication watch-dog timer state
void ModbusQuery(modbusHandler_t * modH, modbus_t telegram ); // put a query in the queue tail
void ModbusQueryInject(modbusHandler_t * modH, modbus_t telegram); //put a query in the queue head
uint16_t getInCnt(); //!<number of incoming messages
uint16_t getOutCnt(); //!<number of outcoming messages
uint16_t getErrCnt(); //!<error counter
uint8_t getID(); //!<get slave ID between 1 and 247
uint8_t getState();
uint8_t getLastError(); //!<get last error message
void setID( uint8_t u8id ); //!<write new ID for the slave
void setTxendPinOverTime( uint32_t u32overTime );
void ModbusEnd(); //!<finish any communication and release serial communication port
void StartTaskModbusSlave(void *argument); //slave
void StartTaskModbusMaster(void *argument); //master
uint16_t calcCRC(uint8_t *Buffer, uint8_t u8length);
extern uint8_t numberHandlers;
#endif /* THIRD_PARTY_MODBUS_INC_MODBUS_H_ */