-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathAvrModbus.h
More file actions
314 lines (247 loc) · 16.3 KB
/
AvrModbus.h
File metadata and controls
314 lines (247 loc) · 16.3 KB
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/*********************************************************************************/
/*
* Author : Jeong Hyun Gu
* File name : AvrModbus.h
*/
/*********************************************************************************/
#ifndef __AVR_MODBUS_H__
#define __AVR_MODBUS_H__
/*********************************************************************************/
#include "AvrUart.h"
/*********************************************************************************/
#define AVR_MODBUS_REVISION_DATE 20230125
/*********************************************************************************/
/** REVISION HISTORY **/
/*
2023. 01. 25. - 주석 추가.
Jeong Hyun Gu
2022. 04. 22. - AvrModbusMasterFindSlaveById() 특정 조건에서 Slave를 반환하지 못 하는 문제 수정.
Jeong Hyun Gu - AvrModbusSlaveProc()는 이제 다음 펑션을 지원. AVR_MODBUS_ReadInputRegister, AVR_MODBUS_ReadCoilStatus,
AVR_MODBUS_ForceSingleCoil, AVR_MODBUS_ReadInputStatus
- AvrModbusSlaveSetQueryResponseInfo() 추가.
2022. 02. 09. - Master 수신로직 개선. 수신 데이터 수 비교 추가 및 1회 폴링에 1회 수신처리하도록 변경.
Jeong Hyun Gu - support legacy define (enum_AvrModbusFunction)
2022. 01. 14. - AvrModbusSlaveProc() error Response 0x03 삭제.
Jeong Hyun Gu
2021. 07. 20. - enum_AvrModbusFunction에 펑션 추가. 기존 펑션 명칭을 모드버스 레퍼런스 데이터시트와 동일하게 변경.
Jeong Hyun Gu - AvrModbusMasterAddSlavePollData()의 중복추가 확인 부분 수정.
- Master파트 슬레이브 호출 펑션에 따라 수신처리하도록 수정.
- AvrModbusMasterWriteSingle() 추가. AVR_MODBUS_ForceSingleCoil, AVR_MODBUS_PresetSingleRegister 중 펑션 선택 가능.
AvrModbusMasterPresetSingle()는 기존 호환성 고려 삭제하지 않음.
2021. 04. 08. - 2021. 03. 18. 에서 잘 못 수정한 부분 수정. AvrModbusMasterRemoveSlave() 후 AvrModbusMasterAddSlave()하면 슬레이브 호출을
Jeong Hyun Gu 정상적으로 하지 못하는 문제 수정.
2021. 03. 18. - Master파트 tag_AvrModbusMasterSlavePollData는 AvrModbusMasterAddSlave(), AvrModbusMasterAddSlavePollData() 호출할 때
Jeong Hyun Gu 할당 하게 되어 있는데, Master Init 시점에서 메모리 동적할당 성공여부를 확인할 수 없음.
AvrModbusMasterAddSlavePollData()는 보통 잘 사용하지 않으므로 AvrModbusMasterGeneralInit() 시점에서 미리 1개의 tag_AvrModbusMasterSlavePollData를
할당하여 Init시점에서 메모리 할당 성공여부 확인할 수있도록 변경.
2020. 10. 20. - 2020. 07. 03에서 수정한 내용 AvrModbusMasterAddSlave()에서 사용자가 설정한 PollFunction이
Jeong Hyun Gu 반영되지 않고 AVR_MODBUS_ReadHolding로 설정되는 문제 수정.
2020. 09. 09. - Slave파트 마스터가 시작주소를 0으로 호출하면 tag_AvrModbusSlaveCtrl::MapStartAddr와 상관없이
Jeong Hyun Gu 응답하도록 변경. (기존 제품과의 호환성 유지를 위해)
2020. 08. 04. - Slave파트 시작주소 범위를 벗어나 호출하거나 쓰기 명령이 있을 경우 에러 리턴하도록 수정.
Jeong Hyun Gu - Slave파트 시작번지가 200 미만일 경우 정상 응답하지 않는 부분 수정.
2020. 07. 03. - Slave파트 AVR_MODBUS_ReadSerialNumber (0x73)펑션 마스터가 요청하는 길이 부분은 무시하고,
Jeong Hyun Gu 연결 되어 있는 프로그램명 문자열 길이로 응답.
- Master파트 AvrModbusMasterSetSlavePollFunction() 삭제. 앞으로 PollFunction은 AvrModbusMasterAddSlave(),
AvrModbusMasterAddSlavePollData()를 호출할 때 결정하도록 변경.
2020. 06. 23. - Slave파트 AVR_MODBUS_ReadSerialNumber (0x73) 펑션 추가.
Jeong Hyun Gu
2019. 10. 10. - crc16(20191007) 버전 대응 위해 SysTypedef.h 적용.
Jeong Hyun Gu - AvrUart(20191010) 버전 대응 위해 AvrModbusSlaveProc()에서
AvrUartFixTxEnableFloating() 삭제, AvrUartControlTxEnd() 호출.
AvrModbusSlaveGeneralInit()에서 AvrUartSetTxEndDelay() 호출.
2019. 08. 28. - AvrModbusSlaveSetMapStartAddr() 추가.
Jeong Hyun Gu - Slave파트 CustomFrameCheck 추가.
2019. 05. 07. - Master파트 슬레이브 호출 펑션 AVR_MODBUS_ReadInput(0x04) 지원 추가.
Jeong Hyun Gu - AvrModbusMasterSetSlavePollFunction() 추가.
2019. 04. 16. - Slave파트 AvrModbusSlaveProc()함수에서 CRC에러 코드 응답할 때 유효한 펑션코드가 수신 되었는지 검사 추가.
Jeong Hyun Gu (프레임 인식에 오류 발견, A슬레이브 응답 중 B슬레이브가 ID패킷을 수신하지 못 하고 우연히 B슬레이브를 호출하는 것으로 인식하여
동작. 결과적으로 B슬레이브가 CRC에러 응답을 하여 정상응답 패킷과 프레임 충돌 발생. 근본적인 원인 파악이 필요하나 시간관계상
위와 같은 임시조치 추가. 이러한 이슈는 본 모듈을 사용한 슬레이브가 2대 이상일 경우 발생 가능성 있음. 추후 확인 필요.)
- AVR_MODBUS_RECEIVING_DELAY_US 값 '50000' -> '20000' 변경.
2019. 03. 19. - tag_AvrModbusMasterCtrl::SlaveReceive 삭제.
Jeong Hyun Gu - AvrModbusMasterAddSlavePollData() 추가.
이제 마스터는 슬레이브 데이터를 비선형적으로 호출 가능. 예를 들어 200~210번지, 260~280번지등
PollData를 추가하여 순차 호출.
- tag_AvrModbusMasterCtrl::Bit.PollDataAllocFail를 추가하여 동적 메모리 할당 실패 여부 확인.
AvrModbusMasterAddSlave(), AvrModbusMasterAddSlavePollData()호출 후 위 비트 값이 1이면 에러, 0이면 정상.
2019. 01. 10. - AvrModbusSlaveProc함수의 인수 SlaveAddr -> SlaveId 변수명 변경.
Jeong Hyun Gu - Slave파트 PreUserException 추가.
- Master파트 FindSlaveById함수를 AvrModbusMasterFindSlaveById()로 변경하고
public으로 공개.
2018. 10. 23. - Master파트 AvrModbusMasterAddSlave()함수에서 중복 ID 검색수량
Jeong Hyun Gu tag_AvrModbusMasterCtrl::AddedSlave -> tag_AvrModbusMasterCtrl::MaxSlave 변경.
tag_AvrModbusMasterCtrl::SlaveArray에서 추가된 Slave보다 앞쪽 배열이 비어 있는 경우
중복 추가 되는 현상 수정.
- Master파트 FindSlaveById()함수에서 지역변수 Slave의 초기 값
tag_AvrModbusMasterCtrl::SlaveArray -> tag_AvrModbusMasterCtrl::SlavePoll 변경.
tag_AvrModbusMasterCtrl::SlaveArray에서 제거하고자 하는 Slave가 tag_AvrModbusMasterCtrl::AddedSlave
보다 뒤쪽에 위치할 경우 제거 되지 않던 현상 수정.
2018. 09. 06. - Slave파트 AVR_MODBUS_PresetMultiple 커맨드 처리에서
Jeong Hyun Gu tag_AvrModbusSlaveCtrl :: UserException() 함수의 NumberOfRegister인자가
2배 큰 값으로 전달 되던 현상 수정.
2017. 12. 27. - ErrorException() Id가 0xFF일 경우 에러를 응답하지 않음.
Jeong Hyun Gu
2017. 07. 26. - Uart::ReceivingDelay 최소 값 제한.
Jeong Hyun Gu - AvrModbusSlaveProc() 함수에 AvrUartFixTxEnableFloating() 호출 추가.
2017. 03. 22. - Slave파트 일부 public 함수에 초기화 확인 부분 추가.
Jeong Hyun Gu - Master 파트 AvrModbusMasterPresetSingle(), AvrModbusMasterPresetMultiple()는 폴링 상태일 때에만 처리함.
(커맨드 처리전 중복 호출할 경우 정상처리 하지 못 함.)
2017. 02. 24. - Master파트 MasterReceive() 함수에 function code 확인 추가.
Jeong Hyun Gu - AvrModbusMasterSetSlaveNoResponse() 함수 추가.
- AvrModbusMasterSetPollingDelay() 함수의 'MasterProcTick_us' 인수 삭제.
폴링 딜레이 함수는 더 이상 필수 초기화가 아니며, AvrModbusMasterGeneralInit()에서 디폴트 설정.
- AvrUartViewRxBuf() 함수를 사용하지 않고 수신 버퍼에 직접 접근.
- Master 파트 UserException() 함수 추가.
2017. 01. 02. - 2016. 12. 26.에 추가 되었던 내용 삭제. (AvrUart 모듈로 이동)
Jeong Hyun Gu
2016. 12. 26. - Slave파트 AvrModbusSlaveProc()함수에 수신 대기 중 TX Enable 비활성화 추가.
Jeong Hyun Gu
2016. 12. 07. - 'AvrUart' 모듈의 'enum_AvrUartMoveDirection' 타입 삭제와 관련된 부분 수정.
Jeong Hyun Gu - 'AvrUart' 모듈의 'AvrUartClearRx' 함수 삭제와 관련된 부분 수정.
- 'enum_AvrModbusDirection' 타입 삭제.
- 주석 추가.
2016. 11. 21. - Master파트 AvrModbusMasterPresetSingle(), AvrModbusMasterPresetMultiple() 함수에서
Jeong Hyun Gu Master->Status를 핸들링 하지 않던 부분 수정.
2016. 11. 08. - revision valid check 추가.
Jeong Hyun Gu
2016. 11. 04. - Master파트 CheckSlaveId() 함수 삭제.
Jeong Hyun Gu - 하위호환 가능.
2016. 11. 02. - AvrModbusMasterGeneralInit() 함수 일부 수정. (초기화 및 Receiving 최소 지연 추가)
Jeong Hyun Gu - 마스터 변수명 변경. 'PollDelay_us' -> 'PollDelay'
- UART 모듈 변수명 변경. 'Uart->ReceivingDelay_us' -> 'Uart->ReceivingDelay'
- 전처리 값 변경 'AVR_MODBUS_RECEIVING_DELAY_US' 20000 -> 50000
2016. 10. 28. - 초기버전.
Jeong Hyun Gu
*/
/*********************************************************************************/
/**Define**/
#define true 1
#define false 0
#define null 0
#define AVR_MODBUS_MASTER true
#define AVR_MODBUS_SLAVE true
#define AVR_MODBUS_RECEIVING_DELAY_US 20000
#define AVR_MODBUS_DEFAULT_POLLING_DELAY_US 500000
#define AVR_MODBUS_DEFAULT_SLAVE_NO_RESPONSE 20
#define AVR_MODBUS_SLAVE_DEFAULT_TX_END_DELAY 20000
/*********************************************************************************/
/**Enum**/
typedef enum
{
AVR_MODBUS_ReadSerialNumber = 0x73,
AVR_MODBUS_ReadCoilStatus = 0x01,
AVR_MODBUS_ReadInputStatus = 0x02,
AVR_MODBUS_ReadHoldingRegister = 0x03,
AVR_MODBUS_ReadInputRegister = 0x04,
AVR_MODBUS_ForceSingleCoil = 0x05,
AVR_MODBUS_PresetSingleRegister = 0x06,
AVR_MODBUS_PresetMultipleRegister = 0x10,
}enum_AvrModbusFunction;
//support legacy define.
#define AVR_MODBUS_ReadHolding AVR_MODBUS_ReadHoldingRegister
#define AVR_MODBUS_ReadInput AVR_MODBUS_ReadInputRegister
#define AVR_MODBUS_PresetSingle AVR_MODBUS_PresetSingleRegister
#define AVR_MODBUS_PresetMultipleRegister AVR_MODBUS_PresetMultipleRegister
/*********************************************************************************/
/**Struct**/
#if(AVR_MODBUS_SLAVE == true)
typedef struct
{
tU8 *BaseAddr;
tU16 MapStartAddr;
}tag_QueryResponseInfo;
typedef struct tag_AvrModbusSlaveCtrl
{
struct
{
tU8 InitGeneral : 1;
tU8 InitCheckOutRange : 1;
tU8 InitUserException : 1;
tU8 InitPreUserException : 1;
tU8 InitCustomFrameCheck : 1;
tU8 InitSerialNumber : 1;
tU8 InitComplete : 1;
}Bit;
tag_AvrUartCtrl *Uart;
tU8 (*CheckOutRange)(tU16 StartAddr, tU16 NumberOfRegister);
void (*UserException)(tU16 StartAddr, tU16 NumberOfRegister);
tU8 (*PreUserException)(struct tag_AvrModbusSlaveCtrl *Slave, tU8 *SlaveId);
tU16 (*CustomFrameCheck)(tag_AvrUartRingBuf *Que, tU16 Ctr);
char *SerialNumberAddr;
tag_QueryResponseInfo QR_ReadHoldingRegister;
tag_QueryResponseInfo QR_ReadInputRegister;
tag_QueryResponseInfo QR_ReadCoilStatus;
tag_QueryResponseInfo QR_ReadInputStatus;
}tag_AvrModbusSlaveCtrl;
#endif
#if(AVR_MODBUS_MASTER == true)
typedef struct
{
tU16 StartAddr;
tU16 NumberOfRegister;
tU8 *BaseAddr;
enum_AvrModbusFunction PollFunction;
}tag_AvrModbusMasterSlavePollData;
typedef struct
{
tU8 Id;
tU8 NoResponseCnt;
tU8 NoResponseLimit;
tU8 PollDataIndex;
tU8 PollDataMax;
tag_AvrModbusMasterSlavePollData *PollData;
}tag_AvrModbusMasterSlaveInfo;
typedef struct
{
struct
{
tU8 InitGeneral : 1;
tU8 InitRxUserException : 1;
tU8 InitComplete : 1;
tU8 PollDataAllocFail : 1;
}Bit;
tU8 IsWriteCmdPending : 1;
tU8 IsPollingSend : 1;
tag_AvrUartCtrl *Uart;
tU32 Tick_us;
tU32 PollDelay;
tU32 PollCnt;
tag_AvrModbusMasterSlaveInfo *SlaveArray;
tag_AvrModbusMasterSlaveInfo *SlavePoll;
tU8 MaxSlave;
tU8 AddedSlave;
void (*UserException)(tU8 Id);
}tag_AvrModbusMasterCtrl;
#endif
/*********************************************************************************/
/**Function**/
#if(AVR_MODBUS_SLAVE == true)
tU8 AvrModbusSlaveGeneralInit(tag_AvrModbusSlaveCtrl *Slave, tag_AvrUartCtrl *Uart, tU8 *BaseAddr, tU32 SlaveProcTick_us);
tU8 AvrModbusSlaveLinkCheckRangeFunc(tag_AvrModbusSlaveCtrl *Slave, tU8 (*CheckRange)(tU16 StartAddr, tU16 NumberOfRegister));
tU8 AvrModbusSlaveLinkUserExceptionFunc(tag_AvrModbusSlaveCtrl *Slave, void (*UserException)(tU16 StartAddr, tU16 NumberOfRegister));
tU8 AvrModbusSlaveLinkPreUserExceptionFunc(tag_AvrModbusSlaveCtrl *Slave, tU8 (*PreUserException)(tag_AvrModbusSlaveCtrl *Slave, tU8 *SlaveId));
tU8 AvrModbusSlaveLinkCustomFrameCheck(tag_AvrModbusSlaveCtrl *Slave, tU16 (*CustomFrameCheck)(tag_AvrUartRingBuf *Que, tU16 Ctr));
tU8 AvrModbusSlaveLinkSerialNumber(tag_AvrModbusSlaveCtrl *Slave, char *SerialNumberAddr);
tU8 AvrModbusSlaveSetQueryResponseInfo(tag_AvrModbusSlaveCtrl *Slave, enum_AvrModbusFunction Function, tU8 *BaseAddr, tU16 MapStartAddr);
void AvrModbusSlaveProc(tag_AvrModbusSlaveCtrl *Slave, tU8 SlaveId);
#define AvrModbusSlaveSetMapStartAddr(SLAVE, START_ADDR) AvrModbusSlaveSetQueryResponseInfo(SLAVE, AVR_MODBUS_ReadHoldingRegister, (SLAVE)->QR_ReadHoldingRegister.BaseAddr, START_ADDR)
//support legacy function..
#endif
#if(AVR_MODBUS_MASTER == true)
tU8 AvrModbusMasterGeneralInit(tag_AvrModbusMasterCtrl *Master, tag_AvrUartCtrl *Uart, tU8 MaxSlave, tU32 MasterProcTick_us);
tU8 AvrModbusMasterSetPollingDelay(tag_AvrModbusMasterCtrl *Master, tU32 PollDelay_us);
tU8 AvrModbusMasterAddSlave(tag_AvrModbusMasterCtrl *Master, tU8 Id, enum_AvrModbusFunction PollFunction, tU16 StartAddr, tU16 NumberOfRegister, tU8 *BaseAddr);
tU8 AvrModbusMasterAddSlavePollData(tag_AvrModbusMasterCtrl *Master, tU8 Id, enum_AvrModbusFunction PollFunction, tU16 StartAddr, tU16 NumberOfRegister, tU8 *BaseAddr);
void AvrModbusMasterRemoveSlave(tag_AvrModbusMasterCtrl *Master, tU8 Id);
void AvrModbusMasterSetSlaveNoResponse(tag_AvrModbusMasterCtrl *Master, tU8 Id, tU8 NoResponseLimit);
tU8 AvrModbusMasterLinkUserException(tag_AvrModbusMasterCtrl *Master, void (*UserException)(tU8 Id));
void AvrModbusMasterProc(tag_AvrModbusMasterCtrl *Master);
tU8 AvrModbusMasterWriteSingle(tag_AvrModbusMasterCtrl *Master, tU8 SlaveId, enum_AvrModbusFunction Func, tU16 RegAddr, tU16 PresetData);
tU8 AvrModbusMasterPresetSingle(tag_AvrModbusMasterCtrl *Master, tU8 SlaveId, tU16 RegAddr, tU16 PresetData);
tU8 AvrModbusMasterPresetMultiple(tag_AvrModbusMasterCtrl *Master, tU8 SlaveId, tU16 StartAddr, tU16 NumberOfRegister, tU8 *BaseAddr);
tU8 AvrModbusMasterCheckSlaveNoResponse(tag_AvrModbusMasterCtrl *Master, tU8 Id);
tag_AvrModbusMasterSlaveInfo* AvrModbusMasterFindSlaveById(tag_AvrModbusMasterCtrl *Master, tU8 Id);
#endif
/*********************************************************************************/
#endif //__AVR_MODBUS_H__