Skip to content

Commit a73bd17

Browse files
Merge pull request #30 from TimerOverflow/20220422
20220422
2 parents bec9074 + d9c5218 commit a73bd17

File tree

2 files changed

+179
-49
lines changed

2 files changed

+179
-49
lines changed

AvrModbus.c

Lines changed: 155 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include "AvrModbus.h"
1010
#include "crc16.h"
1111
/*********************************************************************************/
12-
#if(AVR_MODBUS_REVISION_DATE != 20220209)
12+
#if(AVR_MODBUS_REVISION_DATE != 20220422)
1313
#error wrong include file. (AvrModbus.h)
1414
#endif
1515
/*********************************************************************************/
@@ -67,7 +67,7 @@ static void ErrorException(tag_AvrModbusSlaveCtrl *Slave, tU8 ErrCode)
6767
}
6868
}
6969
/*********************************************************************************/
70-
static void SlaveReadHolding(tag_AvrModbusSlaveCtrl *Slave)
70+
static void SlaveReadRegisters(tag_AvrModbusSlaveCtrl *Slave, tag_QueryResponseInfo *QueryResponseInfo)
7171
{
7272
tag_AvrUartRingBuf *TxQue = &Slave->Uart->TxQueue;
7373
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
@@ -87,7 +87,7 @@ static void SlaveReadHolding(tag_AvrModbusSlaveCtrl *Slave)
8787

8888
StartAddr = (tU16) (RxQue->Buf[2] << 8) + RxQue->Buf[3];
8989
NumberOfPoint = (tU16) (RxQue->Buf[4] << 8) + RxQue->Buf[5];
90-
MapStartAddr = StartAddr == 0 ? 0 : Slave->MapStartAddr;
90+
MapStartAddr = StartAddr == 0 ? 0 : QueryResponseInfo->MapStartAddr;
9191

9292
if(StartAddr < MapStartAddr)
9393
{
@@ -97,7 +97,7 @@ static void SlaveReadHolding(tag_AvrModbusSlaveCtrl *Slave)
9797
{
9898
StartAddr -= MapStartAddr;
9999
NumberOfPoint *= 2;
100-
BaseAddr = (tU8 *) (((tU16 *) Slave->BaseAddr) + StartAddr);
100+
BaseAddr = (tU8 *) (((tU16 *) QueryResponseInfo->BaseAddr) + StartAddr);
101101

102102
AvrUartPutChar(Slave->Uart, RxQue->Buf[0]); //Slave Address
103103
AvrUartPutChar(Slave->Uart, RxQue->Buf[1]); //Function
@@ -124,7 +124,102 @@ static void SlaveReadHolding(tag_AvrModbusSlaveCtrl *Slave)
124124
}
125125
}
126126
/*********************************************************************************/
127-
static void SlavePresetSingle(tag_AvrModbusSlaveCtrl *Slave)
127+
static void SlaveReadStatus(tag_AvrModbusSlaveCtrl *Slave, tag_QueryResponseInfo *QueryResponseInfo)
128+
{
129+
tag_AvrUartRingBuf *TxQue = &Slave->Uart->TxQueue;
130+
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
131+
tU16 StartAddr, NumberOfPoint, Crc16, i, MapStartAddr;
132+
tU8 *BaseAddr;
133+
134+
StartAddr = (tU16) (RxQue->Buf[2] << 8) + RxQue->Buf[3];
135+
NumberOfPoint = (tU16) (RxQue->Buf[4] << 8) + RxQue->Buf[5];
136+
MapStartAddr = StartAddr == 0 ? 0 : QueryResponseInfo->MapStartAddr;
137+
138+
if(StartAddr < MapStartAddr)
139+
{
140+
ErrorException(Slave, 2);
141+
}
142+
else
143+
{
144+
StartAddr -= MapStartAddr;
145+
NumberOfPoint = (NumberOfPoint / 8) + ((NumberOfPoint % 8) ? 1 : 0);
146+
BaseAddr = (tU8 *) (((tU16 *) QueryResponseInfo->BaseAddr) + StartAddr);
147+
148+
AvrUartPutChar(Slave->Uart, RxQue->Buf[0]); //Slave Address
149+
AvrUartPutChar(Slave->Uart, RxQue->Buf[1]); //Function
150+
AvrUartPutChar(Slave->Uart, NumberOfPoint); //Byte Count
151+
152+
for(i = 0; i < NumberOfPoint; i++)
153+
{
154+
AvrUartPutChar(Slave->Uart, BaseAddr[i]);
155+
}
156+
157+
if(Slave->Bit.InitCustomFrameCheck)
158+
{
159+
Crc16 = Slave->CustomFrameCheck(TxQue, TxQue->Ctr);
160+
}
161+
else
162+
{
163+
Crc16 = Crc16Check(TxQue->OutPtr, TxQue->Buf, &TxQue->Buf[TxQue->Size - 1], TxQue->Ctr);
164+
}
165+
166+
AvrUartPutChar(Slave->Uart, (Crc16 >> 8));
167+
AvrUartPutChar(Slave->Uart, (Crc16 & 0x00FF));
168+
AvrUartStartTx(Slave->Uart);
169+
}
170+
}
171+
/*********************************************************************************/
172+
static void SlaveForceSingleCoil(tag_AvrModbusSlaveCtrl *Slave, tag_QueryResponseInfo *QueryResponseInfo)
173+
{
174+
tag_AvrUartRingBuf *TxQue = &Slave->Uart->TxQueue;
175+
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
176+
tU16 RegisterAddr, ForceData, Crc16, Move;
177+
tU8 *BaseAddr;
178+
179+
RegisterAddr = (tU16) (RxQue->Buf[2] << 8) + RxQue->Buf[3];
180+
ForceData = (tU16) (RxQue->Buf[4] << 8) + RxQue->Buf[5];
181+
182+
if(((Slave->Bit.InitCheckOutRange == true) && (Slave->CheckOutRange(RegisterAddr, 1) == true)) || (RegisterAddr < QueryResponseInfo->MapStartAddr))
183+
{
184+
ErrorException(Slave, 2);
185+
}
186+
else
187+
{
188+
Move = RegisterAddr - QueryResponseInfo->MapStartAddr;
189+
BaseAddr = QueryResponseInfo->BaseAddr + (Move / 8);
190+
*BaseAddr = ForceData ? *BaseAddr | (1 << (Move % 8)) : *BaseAddr & ~(1 << (Move % 8));
191+
192+
if(Slave->Bit.InitUserException == true)
193+
{
194+
Slave->UserException(RegisterAddr, 1);
195+
}
196+
197+
if(RxQue->Buf[0] != 0)
198+
{
199+
AvrUartPutChar(Slave->Uart, RxQue->Buf[0]); //Slave Address
200+
AvrUartPutChar(Slave->Uart, RxQue->Buf[1]); //Function
201+
AvrUartPutChar(Slave->Uart, RxQue->Buf[2]); //Register Address Hi
202+
AvrUartPutChar(Slave->Uart, RxQue->Buf[3]); //Register Address Lo
203+
AvrUartPutChar(Slave->Uart, RxQue->Buf[4]); //Preset Data Hi
204+
AvrUartPutChar(Slave->Uart, RxQue->Buf[5]); //Preset Data Lo
205+
206+
if(Slave->Bit.InitCustomFrameCheck)
207+
{
208+
Crc16 = Slave->CustomFrameCheck(TxQue, TxQue->Ctr);
209+
}
210+
else
211+
{
212+
Crc16 = Crc16Check(TxQue->OutPtr, TxQue->Buf, &TxQue->Buf[TxQue->Size - 1], TxQue->Ctr);
213+
}
214+
215+
AvrUartPutChar(Slave->Uart, (Crc16 >> 8));
216+
AvrUartPutChar(Slave->Uart, (Crc16 & 0x00FF));
217+
AvrUartStartTx(Slave->Uart);
218+
}
219+
}
220+
}
221+
/*********************************************************************************/
222+
static void SlavePresetSingle(tag_AvrModbusSlaveCtrl *Slave, tag_QueryResponseInfo *QueryResponseInfo)
128223
{
129224
tag_AvrUartRingBuf *TxQue = &Slave->Uart->TxQueue;
130225
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
@@ -145,13 +240,13 @@ static void SlavePresetSingle(tag_AvrModbusSlaveCtrl *Slave)
145240
RegisterAddr = (tU16) (RxQue->Buf[2] << 8) + RxQue->Buf[3];
146241
PresetData = (tU16) (RxQue->Buf[4] << 8) + RxQue->Buf[5];
147242

148-
if(((Slave->Bit.InitCheckOutRange == true) && (Slave->CheckOutRange(RegisterAddr, 1) == true)) || (RegisterAddr < Slave->MapStartAddr))
243+
if(((Slave->Bit.InitCheckOutRange == true) && (Slave->CheckOutRange(RegisterAddr, 1) == true)) || (RegisterAddr < QueryResponseInfo->MapStartAddr))
149244
{
150245
ErrorException(Slave, 2);
151246
}
152247
else
153248
{
154-
BaseAddr = ((tU16 *) Slave->BaseAddr) + (RegisterAddr - Slave->MapStartAddr);
249+
BaseAddr = ((tU16 *) QueryResponseInfo->BaseAddr) + (RegisterAddr - QueryResponseInfo->MapStartAddr);
155250
*BaseAddr = PresetData;
156251

157252
if(Slave->Bit.InitUserException == true)
@@ -184,7 +279,7 @@ static void SlavePresetSingle(tag_AvrModbusSlaveCtrl *Slave)
184279
}
185280
}
186281
/*********************************************************************************/
187-
static void SlavePresetMultiple(tag_AvrModbusSlaveCtrl *Slave)
282+
static void SlavePresetMultiple(tag_AvrModbusSlaveCtrl *Slave, tag_QueryResponseInfo *QueryResponseInfo)
188283
{
189284
tag_AvrUartRingBuf *TxQue = &Slave->Uart->TxQueue;
190285
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
@@ -204,7 +299,7 @@ static void SlavePresetMultiple(tag_AvrModbusSlaveCtrl *Slave)
204299

205300
StartAddr = (RxQue->Buf[2] << 8) + RxQue->Buf[3];
206301
NumberOfRegister = (RxQue->Buf[4] << 8) + RxQue->Buf[5];
207-
MapStartAddr = StartAddr == 0 ? 0 : Slave->MapStartAddr;
302+
MapStartAddr = StartAddr == 0 ? 0 : QueryResponseInfo->MapStartAddr;
208303

209304
if(((Slave->Bit.InitCheckOutRange == true) && (Slave->CheckOutRange(StartAddr, NumberOfRegister) == true)) || (StartAddr < MapStartAddr))
210305
{
@@ -214,7 +309,7 @@ static void SlavePresetMultiple(tag_AvrModbusSlaveCtrl *Slave)
214309
{
215310
Length = NumberOfRegister * 2;
216311
Length = (Length > (Slave->Uart->RxQueue.Size - 9)) ? (Slave->Uart->RxQueue.Size - 9) : Length;
217-
BaseAddr = (tU8 *) (((tU16 *) Slave->BaseAddr) + (StartAddr - MapStartAddr));
312+
BaseAddr = (tU8 *) (((tU16 *) QueryResponseInfo->BaseAddr) + (StartAddr - MapStartAddr));
218313

219314
for(i = 0; i < Length; i += 2)
220315
{
@@ -314,8 +409,12 @@ tU8 AvrModbusSlaveGeneralInit(tag_AvrModbusSlaveCtrl *Slave, tag_AvrUartCtrl *Ua
314409
if(Uart->Bit.InitComplete == true)
315410
{
316411
Slave->Uart = Uart;
317-
Slave->BaseAddr = BaseAddr;
318-
Slave->MapStartAddr = 200;
412+
413+
AvrModbusSlaveSetQueryResponseInfo(Slave, AVR_MODBUS_ReadHoldingRegister, BaseAddr, 200);
414+
AvrModbusSlaveSetQueryResponseInfo(Slave, AVR_MODBUS_ReadInputRegister, BaseAddr, 200);
415+
AvrModbusSlaveSetQueryResponseInfo(Slave, AVR_MODBUS_ReadCoilStatus, BaseAddr, 200);
416+
AvrModbusSlaveSetQueryResponseInfo(Slave, AVR_MODBUS_ReadInputStatus, BaseAddr, 200);
417+
319418
Slave->Uart->ReceivingDelay = AVR_MODBUS_RECEIVING_DELAY_US / SlaveProcTick_us;
320419
if(Slave->Uart->ReceivingDelay < 2) Slave->Uart->ReceivingDelay = 2;
321420
AvrUartSetTxEndDelay(Uart, AVR_MODBUS_SLAVE_DEFAULT_TX_END_DELAY, SlaveProcTick_us);
@@ -415,31 +514,6 @@ tU8 AvrModbusSlaveLinkPreUserExceptionFunc(tag_AvrModbusSlaveCtrl *Slave, tU8 (*
415514
return Slave->Bit.InitPreUserException;
416515
}
417516
/*********************************************************************************/
418-
tU8 AvrModbusSlaveSetMapStartAddr(tag_AvrModbusSlaveCtrl *Slave, tU16 MapStartAddr)
419-
{
420-
/*
421-
1) 인수
422-
- Slave : tag_AvrModbusSlaveCtrl 인스턴스의 주소.
423-
- MapStartAddr : 모드버스맵상의 시작 주소.
424-
425-
2) 반환
426-
- 0 : 초기화 실패
427-
- 1 : 초기화 성공
428-
429-
3) 설명
430-
- 슬레이브의 모드버스맵 주소상 시작 주소 설정.
431-
*/
432-
433-
if(Slave->Bit.InitComplete == false)
434-
{
435-
return false;
436-
}
437-
438-
Slave->MapStartAddr = MapStartAddr;
439-
440-
return true;
441-
}
442-
/*********************************************************************************/
443517
tU8 AvrModbusSlaveLinkCustomFrameCheck(tag_AvrModbusSlaveCtrl *Slave, tU16 (*CustomFrameCheck)(tag_AvrUartRingBuf *RxQue, tU16 Ctr))
444518
{
445519
/*
@@ -492,6 +566,30 @@ tU8 AvrModbusSlaveLinkSerialNumber(tag_AvrModbusSlaveCtrl *Slave, char *SerialNu
492566
return Slave->Bit.InitSerialNumber;
493567
}
494568
/*********************************************************************************/
569+
tU8 AvrModbusSlaveSetQueryResponseInfo(tag_AvrModbusSlaveCtrl *Slave, enum_AvrModbusFunction Function, tU8 *BaseAddr, tU16 MapStartAddr)
570+
{
571+
tag_QueryResponseInfo *pQueryResponseInfo;
572+
573+
switch(Function)
574+
{
575+
case AVR_MODBUS_PresetSingleRegister :
576+
case AVR_MODBUS_PresetMultipleRegister :
577+
case AVR_MODBUS_ReadHoldingRegister : pQueryResponseInfo = &Slave->QR_ReadHoldingRegister; break;
578+
case AVR_MODBUS_ForceSingleCoil :
579+
case AVR_MODBUS_ReadCoilStatus : pQueryResponseInfo = &Slave->QR_ReadCoilStatus; break;
580+
case AVR_MODBUS_ReadInputStatus : pQueryResponseInfo = &Slave->QR_ReadInputStatus; break;
581+
case AVR_MODBUS_ReadInputRegister : pQueryResponseInfo = &Slave->QR_ReadInputRegister; break;
582+
583+
default :
584+
case AVR_MODBUS_ReadSerialNumber : return false;
585+
}
586+
587+
pQueryResponseInfo->BaseAddr = BaseAddr;
588+
pQueryResponseInfo->MapStartAddr = MapStartAddr;
589+
590+
return true;
591+
}
592+
/*********************************************************************************/
495593
void AvrModbusSlaveProc(tag_AvrModbusSlaveCtrl *Slave, tU8 SlaveId)
496594
{
497595
tag_AvrUartRingBuf *RxQue = &Slave->Uart->RxQueue;
@@ -539,16 +637,32 @@ void AvrModbusSlaveProc(tag_AvrModbusSlaveCtrl *Slave, tU8 SlaveId)
539637
{
540638
switch(RxQue->Buf[1])
541639
{
640+
case AVR_MODBUS_ReadCoilStatus :
641+
SlaveReadStatus(Slave, &Slave->QR_ReadCoilStatus);
642+
break;
643+
644+
case AVR_MODBUS_ReadInputStatus :
645+
SlaveReadStatus(Slave, &Slave->QR_ReadInputStatus);
646+
break;
647+
542648
case AVR_MODBUS_ReadHoldingRegister :
543-
SlaveReadHolding(Slave);
649+
SlaveReadRegisters(Slave, &Slave->QR_ReadHoldingRegister);
650+
break;
651+
652+
case AVR_MODBUS_ReadInputRegister :
653+
SlaveReadRegisters(Slave, &Slave->QR_ReadInputRegister);
654+
break;
655+
656+
case AVR_MODBUS_ForceSingleCoil :
657+
SlaveForceSingleCoil(Slave, &Slave->QR_ReadCoilStatus);
544658
break;
545659

546660
case AVR_MODBUS_PresetSingleRegister :
547-
SlavePresetSingle(Slave);
661+
SlavePresetSingle(Slave, &Slave->QR_ReadHoldingRegister);
548662
break;
549663

550664
case AVR_MODBUS_PresetMultipleRegister :
551-
SlavePresetMultiple(Slave);
665+
SlavePresetMultiple(Slave, &Slave->QR_ReadHoldingRegister);
552666
break;
553667

554668
case AVR_MODBUS_ReadSerialNumber :
@@ -1277,7 +1391,7 @@ tag_AvrModbusMasterSlaveInfo* AvrModbusMasterFindSlaveById(tag_AvrModbusMasterCt
12771391
return null;
12781392
}
12791393

1280-
for(i = 0; i < Master->AddedSlave; i++)
1394+
for(i = 0; i < Master->MaxSlave; i++)
12811395
{
12821396
if(Slave->Id == Id)
12831397
{

AvrModbus.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,19 @@
99
/*********************************************************************************/
1010
#include "AvrUart.h"
1111
/*********************************************************************************/
12-
#define AVR_MODBUS_REVISION_DATE 20220209
12+
#define AVR_MODBUS_REVISION_DATE 20220422
1313
/*********************************************************************************/
1414
/** REVISION HISTORY **/
1515
/*
16+
2022. 04. 22. - AvrModbusMasterFindSlaveById() 특정 조건에서 Slave를 반환하지 못 하는 문제 수정.
17+
Jeong Hyun Gu - AvrModbusSlaveProc()는 이제 다음 펑션을 지원. AVR_MODBUS_ReadInputRegister, AVR_MODBUS_ReadCoilStatus,
18+
AVR_MODBUS_ForceSingleCoil, AVR_MODBUS_ReadInputStatus
19+
- AvrModbusSlaveSetQueryResponseInfo() 추가.
20+
1621
2022. 02. 09. - Master 수신로직 개선. 수신 데이터 수 비교 추가 및 1회 폴링에 1회 수신처리하도록 변경.
1722
Jeong Hyun Gu - support legacy define (enum_AvrModbusFunction)
1823
19-
2022. 01. 14. - AvrModbusSlaveProc() error respone 0x03 삭제.
24+
2022. 01. 14. - AvrModbusSlaveProc() error Response 0x03 삭제.
2025
Jeong Hyun Gu
2126
2227
2021. 07. 20. - enum_AvrModbusFunction에 펑션 추가. 기존 펑션 명칭을 모드버스 레퍼런스 데이터시트와 동일하게 변경.
@@ -81,8 +86,8 @@
8186
8287
2018. 10. 23. - Master파트 AvrModbusMasterAddSlave()함수에서 중복 ID 검색수량
8388
Jeong Hyun Gu tag_AvrModbusMasterCtrl::AddedSlave -> tag_AvrModbusMasterCtrl::MaxSlave 변경.
84-
tag_AvrModbusMasterCtrl::SlaveArray에서 추가된 Slave보다 앞쪽 배열이 비어 있는 경우
85-
중복 추가 되는 현상 수정.
89+
tag_AvrModbusMasterCtrl::SlaveArray에서 추가된 Slave보다 앞쪽 배열이 비어 있는 경우
90+
중복 추가 되는 현상 수정.
8691
- Master파트 FindSlaveById()함수에서 지역변수 Slave의 초기 값
8792
tag_AvrModbusMasterCtrl::SlaveArray -> tag_AvrModbusMasterCtrl::SlavePoll 변경.
8893
tag_AvrModbusMasterCtrl::SlaveArray에서 제거하고자 하는 Slave가 tag_AvrModbusMasterCtrl::AddedSlave
@@ -179,6 +184,12 @@ typedef enum
179184

180185
#if(AVR_MODBUS_SLAVE == true)
181186

187+
typedef struct
188+
{
189+
tU8 *BaseAddr;
190+
tU16 MapStartAddr;
191+
}tag_QueryResponseInfo;
192+
182193
typedef struct tag_AvrModbusSlaveCtrl
183194
{
184195
struct
@@ -198,9 +209,12 @@ typedef struct tag_AvrModbusSlaveCtrl
198209
tU8 (*PreUserException)(struct tag_AvrModbusSlaveCtrl *Slave, tU8 *SlaveId);
199210
tU16 (*CustomFrameCheck)(tag_AvrUartRingBuf *Que, tU16 Ctr);
200211

201-
tU8 *BaseAddr;
202212
char *SerialNumberAddr;
203-
tU16 MapStartAddr;
213+
214+
tag_QueryResponseInfo QR_ReadHoldingRegister;
215+
tag_QueryResponseInfo QR_ReadInputRegister;
216+
tag_QueryResponseInfo QR_ReadCoilStatus;
217+
tag_QueryResponseInfo QR_ReadInputStatus;
204218
}tag_AvrModbusSlaveCtrl;
205219

206220
#endif
@@ -264,13 +278,15 @@ tU8 AvrModbusSlaveGeneralInit(tag_AvrModbusSlaveCtrl *Slave, tag_AvrUartCtrl *Ua
264278
tU8 AvrModbusSlaveLinkCheckRangeFunc(tag_AvrModbusSlaveCtrl *Slave, tU8 (*CheckRange)(tU16 StartAddr, tU16 NumberOfRegister));
265279
tU8 AvrModbusSlaveLinkUserExceptionFunc(tag_AvrModbusSlaveCtrl *Slave, void (*UserException)(tU16 StartAddr, tU16 NumberOfRegister));
266280
tU8 AvrModbusSlaveLinkPreUserExceptionFunc(tag_AvrModbusSlaveCtrl *Slave, tU8 (*PreUserException)(tag_AvrModbusSlaveCtrl *Slave, tU8 *SlaveId));
267-
tU8 AvrModbusSlaveSetMapStartAddr(tag_AvrModbusSlaveCtrl *Slave, tU16 MapStartAddr);
268281
tU8 AvrModbusSlaveLinkCustomFrameCheck(tag_AvrModbusSlaveCtrl *Slave, tU16 (*CustomFrameCheck)(tag_AvrUartRingBuf *Que, tU16 Ctr));
269282
tU8 AvrModbusSlaveLinkSerialNumber(tag_AvrModbusSlaveCtrl *Slave, char *SerialNumberAddr);
283+
tU8 AvrModbusSlaveSetQueryResponseInfo(tag_AvrModbusSlaveCtrl *Slave, enum_AvrModbusFunction Function, tU8 *BaseAddr, tU16 MapStartAddr);
270284
void AvrModbusSlaveProc(tag_AvrModbusSlaveCtrl *Slave, tU8 SlaveId);
271285

272-
#endif
286+
#define AvrModbusSlaveSetMapStartAddr(SLAVE, START_ADDR) AvrModbusSlaveSetQueryResponseInfo(SLAVE, AVR_MODBUS_ReadHoldingRegister, (SLAVE)->QR_ReadHoldingRegister.BaseAddr, START_ADDR)
287+
//support legacy function..
273288

289+
#endif
274290

275291
#if(AVR_MODBUS_MASTER == true)
276292

0 commit comments

Comments
 (0)