mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-29 17:22:56 +08:00
add modbus module
add aglie_mmodbus add agile_modbus and LICENSE fix warning add serialize deserialize API
This commit is contained in:
parent
194394fbeb
commit
fc9562ccd6
201
package/modbus/LICENSE
Normal file
201
package/modbus/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
183
package/modbus/_modbus.c
Normal file
183
package/modbus/_modbus.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include "_modbus__ModBus.h"
|
||||
#include "_modbus__ModBusRTU.h"
|
||||
#include "_modbus__ModBusTCP.h"
|
||||
#include "agile_modbus.h"
|
||||
|
||||
void _modbus__ModBusRTU___init__(PikaObj* self,
|
||||
int sendBUffSize,
|
||||
int readBuffSize) {
|
||||
agile_modbus_rtu_t ctx_rtu = {0};
|
||||
agile_modbus_t* ctx = &ctx_rtu._ctx;
|
||||
obj_setBytes(self, "sendBuff", NULL, sendBUffSize);
|
||||
obj_setBytes(self, "readBuff", NULL, readBuffSize);
|
||||
agile_modbus_rtu_init(&ctx_rtu, obj_getBytes(self, "sendBuff"),
|
||||
sendBUffSize, obj_getBytes(self, "readBuff"),
|
||||
readBuffSize);
|
||||
obj_setStruct(self, "ctx_rtu", ctx_rtu);
|
||||
obj_setPtr(self, "ctx", ctx);
|
||||
}
|
||||
|
||||
void _modbus__ModBus_setSlave(PikaObj* self, int slave) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
agile_modbus_set_slave(ctx, slave);
|
||||
}
|
||||
|
||||
void _modbus__ModBusTCP___init__(PikaObj* self,
|
||||
int sendBuffSize,
|
||||
int readBuffSize) {
|
||||
agile_modbus_tcp_t ctx_tcp = {0};
|
||||
agile_modbus_t* ctx = &ctx_tcp._ctx;
|
||||
obj_setBytes(self, "sendBuff", NULL, sendBuffSize);
|
||||
obj_setBytes(self, "readBuff", NULL, readBuffSize);
|
||||
agile_modbus_tcp_init(&ctx_tcp, obj_getBytes(self, "sendBuff"),
|
||||
sendBuffSize, obj_getBytes(self, "readBuff"),
|
||||
readBuffSize);
|
||||
obj_setStruct(self, "ctx_tcp", ctx_tcp);
|
||||
obj_setPtr(self, "ctx", ctx);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeMaskWriteRegister(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_mask_write_register(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadBits(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_bits(ctx, msgLength, dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadInputBits(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_input_bits(ctx, msgLength, dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadInputRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_input_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReportSlaveId(PikaObj* self,
|
||||
int msgLength,
|
||||
int maxDest,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_report_slave_id(ctx, msgLength, maxDest,
|
||||
dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteAndReadRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_and_read_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteBit(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_bit(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteBits(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_bits(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteRegister(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_register(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteRegisters(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_registers(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeMaskWriteRegister(PikaObj* self,
|
||||
int addr,
|
||||
int andMask,
|
||||
int orMask) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_mask_write_register(ctx, addr, andMask,
|
||||
orMask);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadBits(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_bits(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadInputBits(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_input_bits(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadInputRegisters(PikaObj* self,
|
||||
int addr,
|
||||
int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_input_registers(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadRegisters(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_registers(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReportSlaveId(PikaObj* self) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_report_slave_id(ctx);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteAndReadRegisters(PikaObj* self,
|
||||
int writeAddr,
|
||||
int writeNb,
|
||||
uint8_t* src,
|
||||
int readAddr,
|
||||
int readNb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_and_read_registers(
|
||||
ctx, writeAddr, writeNb, (uint16_t*)src, readAddr, readNb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteBit(PikaObj* self, int addr, int status) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_bit(ctx, addr, status);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteBits(PikaObj* self,
|
||||
int addr,
|
||||
int nb,
|
||||
uint8_t* src) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_bits(ctx, addr, nb, src);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteRegister(PikaObj* self, int addr, int value) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_register(ctx, addr, value);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteRegisters(PikaObj* self,
|
||||
int addr,
|
||||
int nb,
|
||||
uint8_t* src) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_registers(ctx, addr, nb,
|
||||
(uint16_t*)src);
|
||||
}
|
31
package/modbus/_modbus.pyi
Normal file
31
package/modbus/_modbus.pyi
Normal file
@ -0,0 +1,31 @@
|
||||
class _ModBus:
|
||||
def setSlave(self, slave: int): ...
|
||||
def serializeReadBits(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadBits(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadInputBits(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadInputBits(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadRegisters(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadInputRegisters(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadInputRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeWriteBit(self, addr: int, status: int) -> int: ...
|
||||
def deserializeWriteBit(self, msgLength: int) -> int: ...
|
||||
def serializeWriteRegister(self, addr: int, value: int) -> int: ...
|
||||
def deserializeWriteRegister(self, msgLength: int) -> int: ...
|
||||
def serializeWriteBits(self, addr: int, nb: int, src: bytes) -> int: ...
|
||||
def deserializeWriteBits(self, msgLength: int) -> int: ...
|
||||
def serializeWriteRegisters(self, addr: int, nb: int, src: bytes) -> int: ...
|
||||
def deserializeWriteRegisters(self, msgLength: int) -> int: ...
|
||||
def serializeMaskWriteRegister(self, addr: int, andMask: int, orMask: int) -> int: ...
|
||||
def deserializeMaskWriteRegister(self, msgLength: int) -> int: ...
|
||||
def serializeWriteAndReadRegisters(self, writeAddr: int, writeNb: int, src: bytes, readAddr: int, readNb: int) -> int: ...
|
||||
def deserializeWriteAndReadRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReportSlaveId(self) -> int: ...
|
||||
def deserializeReportSlaveId(self, msgLength: int, maxDest: int, dest: bytes) -> int: ...
|
||||
|
||||
class _ModBusRTU(_ModBus):
|
||||
def __init__(self, sendBuffSize: int, readBuffSize: int): ...
|
||||
|
||||
|
||||
class _ModBusTCP(_ModBus):
|
||||
def __init__(self, sendBuffSize: int, readBuffSize: int): ...
|
1519
package/modbus/agile_modbus.c
Normal file
1519
package/modbus/agile_modbus.c
Normal file
File diff suppressed because it is too large
Load Diff
359
package/modbus/agile_modbus.h
Normal file
359
package/modbus/agile_modbus.h
Normal file
@ -0,0 +1,359 @@
|
||||
/**
|
||||
* @file agile_modbus.h
|
||||
* @brief Agile Modbus 软件包通用头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2022-07-28
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_H
|
||||
#define __PKG_AGILE_MODBUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup COMMON
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup COMMON_Exported_Constants Common Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup Modbus_Function_Codes Modbus Function Codes
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_FC_READ_COILS 0x01
|
||||
#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS 0x02
|
||||
#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS 0x03
|
||||
#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS 0x04
|
||||
#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL 0x05
|
||||
#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
|
||||
#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS 0x07
|
||||
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F
|
||||
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
|
||||
#define AGILE_MODBUS_FC_REPORT_SLAVE_ID 0x11
|
||||
#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER 0x16
|
||||
#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup Modbus_Constants Modbus Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_VERSION_STRING "AMB_1.1.0" /**< Agile Modbus 版本号 */
|
||||
|
||||
#define AGILE_MODBUS_BROADCAST_ADDRESS 0 /**< Modbus 广播地址 */
|
||||
|
||||
/** @name Quantity limit of Coils
|
||||
@verbatim
|
||||
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)
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_READ_BITS 2000
|
||||
#define AGILE_MODBUS_MAX_WRITE_BITS 1968
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @name Quantity limit of Registers
|
||||
@verbatim
|
||||
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)
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_READ_REGISTERS 125
|
||||
#define AGILE_MODBUS_MAX_WRITE_REGISTERS 123
|
||||
#define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS 121
|
||||
#define AGILE_MODBUS_MAX_WR_READ_REGISTERS 125
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
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.
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_PDU_LENGTH 253
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
Consequently:
|
||||
- RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256
|
||||
bytes.
|
||||
- TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.
|
||||
so the maximum of both backend in 260 bytes. This size can used to allocate
|
||||
an array of bytes to store responses and it will be compatible with the two
|
||||
backends.
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_ADU_LENGTH 260
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup COMMON_Exported_Types Common Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Modbus 异常码
|
||||
*/
|
||||
enum {
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
|
||||
AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
|
||||
AGILE_MODBUS_EXCEPTION_ACKNOWLEDGE,
|
||||
AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
|
||||
AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
|
||||
AGILE_MODBUS_EXCEPTION_MEMORY_PARITY,
|
||||
AGILE_MODBUS_EXCEPTION_NOT_DEFINED,
|
||||
AGILE_MODBUS_EXCEPTION_GATEWAY_PATH,
|
||||
AGILE_MODBUS_EXCEPTION_GATEWAY_TARGET,
|
||||
AGILE_MODBUS_EXCEPTION_UNKNOW = 0xff
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modbus 后端类型
|
||||
*/
|
||||
typedef enum {
|
||||
AGILE_MODBUS_BACKEND_TYPE_RTU = 0, /**< RTU */
|
||||
AGILE_MODBUS_BACKEND_TYPE_TCP /**< TCP */
|
||||
} agile_modbus_backend_type_t;
|
||||
|
||||
/**
|
||||
* @brief Modbus 收到消息类型
|
||||
*
|
||||
@verbatim
|
||||
---------- Request Indication ----------
|
||||
| Client | ---------------------->| Server |
|
||||
---------- Confirmation Response ----------
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
typedef enum {
|
||||
AGILE_MODBUS_MSG_INDICATION, /**< 主机端的请求消息 */
|
||||
AGILE_MODBUS_MSG_CONFIRMATION /**< 服务器端的请求消息 */
|
||||
} agile_modbus_msg_type_t;
|
||||
|
||||
/**
|
||||
* @brief 包含 modbus 头部参数结构体
|
||||
*/
|
||||
typedef struct agile_modbus_sft {
|
||||
int slave; /**< 从机地址 */
|
||||
int function; /**< 功能码 */
|
||||
int t_id; /**< 事务标识符 */
|
||||
} agile_modbus_sft_t;
|
||||
|
||||
typedef struct agile_modbus agile_modbus_t; /**< Agile Modbus 结构体 */
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 后端接口结构体
|
||||
*/
|
||||
typedef struct agile_modbus_backend {
|
||||
uint32_t backend_type; /**< 后端类型 */
|
||||
uint32_t header_length; /**< 头部长度,不包含功能码 */
|
||||
uint32_t checksum_length; /**< 校验数据长度 */
|
||||
uint32_t max_adu_length; /**< 后端 ADU 长度 */
|
||||
int (*set_slave)(agile_modbus_t *ctx, int slave); /**< 设置地址接口 */
|
||||
int (*build_request_basis)(agile_modbus_t *ctx, int function, int addr,
|
||||
int nb, uint8_t *req); /**< 构建基础请求报文接口 */
|
||||
int (*build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp); /**< 构建基础响应报文接口 */
|
||||
int (*prepare_response_tid)(const uint8_t *req, int *req_length); /**< 准备响应接口 */
|
||||
int (*send_msg_pre)(uint8_t *req, int req_length); /**< 预发送数据接口 */
|
||||
int (*check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length); /**< 检查接收数据完整性接口 */
|
||||
int (*pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length); /**< 预检查确认接口 */
|
||||
} agile_modbus_backend_t;
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 结构体
|
||||
*/
|
||||
struct agile_modbus {
|
||||
int slave; /**< 从机地址 */
|
||||
uint8_t *send_buf; /**< 发送缓冲区 */
|
||||
int send_bufsz; /**< 发送缓冲区大小 */
|
||||
uint8_t *read_buf; /**< 接收缓冲区 */
|
||||
int read_bufsz; /**< 接收缓冲区大小 */
|
||||
uint8_t (*compute_meta_length_after_function)(agile_modbus_t *ctx, int function,
|
||||
agile_modbus_msg_type_t msg_type); /**< 自定义计算数据元长度接口 */
|
||||
int (*compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg,
|
||||
int msg_length, agile_modbus_msg_type_t msg_type); /**< 自定义计算数据长度接口 */
|
||||
const agile_modbus_backend_t *backend; /**< 后端接口 */
|
||||
void *backend_data; /**< 后端数据,指向 RTU 或 TCP 结构体 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Slave
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup Slave_Exported_Types Slave Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 从机信息结构体
|
||||
*/
|
||||
struct agile_modbus_slave_info {
|
||||
agile_modbus_sft_t *sft; /**< sft 结构体指针 */
|
||||
int *rsp_length; /**< 响应数据长度指针 */
|
||||
int address; /**< 寄存器地址 */
|
||||
int nb; /**< 数目 */
|
||||
uint8_t *buf; /**< 不同功能码需要使用的数据域 */
|
||||
int send_index; /**< 发送缓冲区当前索引 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 从机回调函数
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave_info 从机信息体
|
||||
* @param data 私有数据
|
||||
* @return =0:正常;
|
||||
* <0:异常
|
||||
* (-AGILE_MODBUS_EXCEPTION_UNKNOW(-255): 未知异常,从机不会打包响应数据)
|
||||
* (其他负数异常码: 从机会打包异常响应数据)
|
||||
*/
|
||||
typedef int (*agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup COMMON_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
int agile_modbus_set_slave(agile_modbus_t *ctx, int slave);
|
||||
void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx,
|
||||
uint8_t (*cb)(agile_modbus_t *ctx, int function,
|
||||
agile_modbus_msg_type_t msg_type));
|
||||
void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx,
|
||||
int (*cb)(agile_modbus_t *ctx, uint8_t *msg,
|
||||
int msg_length, agile_modbus_msg_type_t msg_type));
|
||||
int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Master
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Master_Common_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
|
||||
int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
|
||||
int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status);
|
||||
int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value);
|
||||
int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src);
|
||||
int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src);
|
||||
int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
|
||||
int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx,
|
||||
int write_addr, int write_nb,
|
||||
const uint16_t *src,
|
||||
int read_addr, int read_nb);
|
||||
int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx);
|
||||
int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Master_Raw_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
|
||||
int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Slave
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Slave_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict,
|
||||
agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length);
|
||||
void agile_modbus_slave_io_set(uint8_t *buf, int index, int status);
|
||||
uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index);
|
||||
void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data);
|
||||
uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Include RTU and TCP module */
|
||||
#include "agile_modbus_rtu.h"
|
||||
#include "agile_modbus_tcp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PKG_AGILE_MODBUS_H */
|
291
package/modbus/agile_modbus_rtu.c
Normal file
291
package/modbus/agile_modbus_rtu.c
Normal file
@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @file agile_modbus_rtu.c
|
||||
* @brief Agile Modbus 软件包 RTU 源文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "agile_modbus.h"
|
||||
#include "agile_modbus_rtu.h"
|
||||
|
||||
/** @defgroup RTU RTU
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Private_Constants RTU Private Constants
|
||||
* @{
|
||||
*/
|
||||
/** Table of CRC values for high-order byte */
|
||||
static const uint8_t _table_crc_hi[] =
|
||||
{
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
|
||||
|
||||
/** Table of CRC values for low-order byte */
|
||||
static const uint8_t _table_crc_lo[] =
|
||||
{
|
||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
|
||||
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
|
||||
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
|
||||
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
|
||||
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
|
||||
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
|
||||
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
|
||||
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
|
||||
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
|
||||
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
|
||||
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
|
||||
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
|
||||
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
|
||||
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
|
||||
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
|
||||
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
|
||||
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
|
||||
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
|
||||
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
|
||||
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
|
||||
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
|
||||
0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Private_Functions RTU Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU CRC16 计算
|
||||
* @param buffer 数据指针
|
||||
* @param buffer_length 数据长度
|
||||
* @return CRC16 值
|
||||
*/
|
||||
static uint16_t agile_modbus_rtu_crc16(uint8_t *buffer, uint16_t buffer_length)
|
||||
{
|
||||
uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
|
||||
uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
|
||||
unsigned int i; /* will index into CRC lookup */
|
||||
|
||||
/* pass through message buffer */
|
||||
while (buffer_length--) {
|
||||
i = crc_hi ^ *buffer++; /* calculate the CRC */
|
||||
crc_hi = crc_lo ^ _table_crc_hi[i];
|
||||
crc_lo = _table_crc_lo[i];
|
||||
}
|
||||
|
||||
return (crc_hi << 8 | crc_lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 设置地址接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave 从机地址
|
||||
* @return 0:成功
|
||||
*/
|
||||
static int agile_modbus_rtu_set_slave(agile_modbus_t *ctx, int slave)
|
||||
{
|
||||
ctx->slave = slave;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 构建基础请求报文接口(头部报文)
|
||||
* @param ctx modbus 句柄
|
||||
* @param function 功能码
|
||||
* @param addr 寄存器地址
|
||||
* @param nb 寄存器数目
|
||||
* @param req 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_build_request_basis(agile_modbus_t *ctx, int function,
|
||||
int addr, int nb,
|
||||
uint8_t *req)
|
||||
{
|
||||
req[0] = ctx->slave;
|
||||
req[1] = function;
|
||||
req[2] = addr >> 8;
|
||||
req[3] = addr & 0x00ff;
|
||||
req[4] = nb >> 8;
|
||||
req[5] = nb & 0x00ff;
|
||||
|
||||
return AGILE_MODBUS_RTU_PRESET_REQ_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 构建基础响应报文接口(头部报文)
|
||||
* @param sft modbus 头部参数结构体指针
|
||||
* @param rsp 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp)
|
||||
{
|
||||
rsp[0] = sft->slave;
|
||||
rsp[1] = sft->function;
|
||||
|
||||
return AGILE_MODBUS_RTU_PRESET_RSP_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 准备响应接口
|
||||
* @note 该 API 会将 req_length 自动减去 AGILE_MODBUS_RTU_CHECKSUM_LENGTH 长度
|
||||
* @param req 请求数据指针
|
||||
* @param req_length 请求数据长度
|
||||
* @return 0 (RTU 没有事务标识符)
|
||||
*/
|
||||
static int agile_modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
|
||||
{
|
||||
(*req_length) -= AGILE_MODBUS_RTU_CHECKSUM_LENGTH;
|
||||
/* No TID */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 预发送数据接口
|
||||
* @note 该 API 会计算 CRC16 并自动填入尾部
|
||||
* @param req 数据存放指针
|
||||
* @param req_length 已有数据长度
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
|
||||
{
|
||||
uint16_t crc = agile_modbus_rtu_crc16(req, req_length);
|
||||
req[req_length++] = crc >> 8;
|
||||
req[req_length++] = crc & 0x00FF;
|
||||
|
||||
return req_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 检查接收数据完整性接口(CRC16 对比)
|
||||
* @param ctx modbus 句柄
|
||||
* @param msg 接收数据指针
|
||||
* @param msg_length 有效数据长度
|
||||
* @return >0:有效数据长度; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_rtu_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
|
||||
{
|
||||
uint16_t crc_calculated;
|
||||
uint16_t crc_received;
|
||||
|
||||
crc_calculated = agile_modbus_rtu_crc16(msg, msg_length - 2);
|
||||
crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
|
||||
|
||||
/* Check CRC of msg */
|
||||
if (crc_calculated == crc_received)
|
||||
return msg_length;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 预检查确认接口(请求响应地址对比)
|
||||
* @note 如果请求地址是广播地址0,返回成功
|
||||
* @param ctx modbus 句柄
|
||||
* @param req 请求数据指针
|
||||
* @param rsp 响应数据指针
|
||||
* @param rsp_length 响应数据长度
|
||||
* @return 0:成功; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_rtu_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length)
|
||||
{
|
||||
/* Check responding slave is the slave we requested (except for broacast
|
||||
* request) */
|
||||
if (req[0] != rsp[0] && req[0] != AGILE_MODBUS_BROADCAST_ADDRESS)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTU_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 后端接口
|
||||
*/
|
||||
static const agile_modbus_backend_t agile_modbus_rtu_backend =
|
||||
{
|
||||
AGILE_MODBUS_BACKEND_TYPE_RTU,
|
||||
AGILE_MODBUS_RTU_HEADER_LENGTH,
|
||||
AGILE_MODBUS_RTU_CHECKSUM_LENGTH,
|
||||
AGILE_MODBUS_RTU_MAX_ADU_LENGTH,
|
||||
agile_modbus_rtu_set_slave,
|
||||
agile_modbus_rtu_build_request_basis,
|
||||
agile_modbus_rtu_build_response_basis,
|
||||
agile_modbus_rtu_prepare_response_tid,
|
||||
agile_modbus_rtu_send_msg_pre,
|
||||
agile_modbus_rtu_check_integrity,
|
||||
agile_modbus_rtu_pre_check_confirmation};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Functions RTU Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 初始化
|
||||
* @param ctx RTU 句柄
|
||||
* @param send_buf 发送缓冲区
|
||||
* @param send_bufsz 发送缓冲区大小
|
||||
* @param read_buf 接收缓冲区
|
||||
* @param read_bufsz 接收缓冲区大小
|
||||
* @return 0:成功
|
||||
*/
|
||||
int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
|
||||
{
|
||||
agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz);
|
||||
ctx->_ctx.backend = &agile_modbus_rtu_backend;
|
||||
ctx->_ctx.backend_data = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
79
package/modbus/agile_modbus_rtu.h
Normal file
79
package/modbus/agile_modbus_rtu.h
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file agile_modbus_rtu.h
|
||||
* @brief Agile Modbus 软件包 RTU 头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_RTU_H
|
||||
#define __PKG_AGILE_MODBUS_RTU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup RTU
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Constants RTU Exported Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_RTU_HEADER_LENGTH 1
|
||||
#define AGILE_MODBUS_RTU_PRESET_REQ_LENGTH 6
|
||||
#define AGILE_MODBUS_RTU_PRESET_RSP_LENGTH 2
|
||||
|
||||
#define AGILE_MODBUS_RTU_CHECKSUM_LENGTH 2
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
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
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_RTU_MAX_ADU_LENGTH 256
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Types RTU Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 结构体
|
||||
*/
|
||||
typedef struct agile_modbus_rtu {
|
||||
agile_modbus_t _ctx; /**< modbus 句柄 */
|
||||
} agile_modbus_rtu_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTU_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PKG_AGILE_MODBUS_RTU_H */
|
226
package/modbus/agile_modbus_tcp.c
Normal file
226
package/modbus/agile_modbus_tcp.c
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @file agile_modbus_tcp.c
|
||||
* @brief Agile Modbus 软件包 TCP 源文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "agile_modbus.h"
|
||||
#include "agile_modbus_tcp.h"
|
||||
|
||||
/** @defgroup TCP TCP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Private_Functions TCP Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 设置地址接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave 从机地址
|
||||
* @return 0:成功
|
||||
*/
|
||||
static int agile_modbus_tcp_set_slave(agile_modbus_t *ctx, int slave)
|
||||
{
|
||||
ctx->slave = slave;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 构建基础请求报文接口(头部报文)
|
||||
* @param ctx modbus 句柄
|
||||
* @param function 功能码
|
||||
* @param addr 寄存器地址
|
||||
* @param nb 寄存器数目
|
||||
* @param req 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_build_request_basis(agile_modbus_t *ctx, int function,
|
||||
int addr, int nb,
|
||||
uint8_t *req)
|
||||
{
|
||||
agile_modbus_tcp_t *ctx_tcp = ctx->backend_data;
|
||||
|
||||
/* Increase transaction ID */
|
||||
if (ctx_tcp->t_id < UINT16_MAX)
|
||||
ctx_tcp->t_id++;
|
||||
else
|
||||
ctx_tcp->t_id = 0;
|
||||
req[0] = ctx_tcp->t_id >> 8;
|
||||
req[1] = ctx_tcp->t_id & 0x00ff;
|
||||
|
||||
/* Protocol Modbus */
|
||||
req[2] = 0;
|
||||
req[3] = 0;
|
||||
|
||||
/* Length will be defined later by set_req_length_tcp at offsets 4
|
||||
and 5 */
|
||||
|
||||
req[6] = ctx->slave;
|
||||
req[7] = function;
|
||||
req[8] = addr >> 8;
|
||||
req[9] = addr & 0x00ff;
|
||||
req[10] = nb >> 8;
|
||||
req[11] = nb & 0x00ff;
|
||||
|
||||
return AGILE_MODBUS_TCP_PRESET_REQ_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 构建基础响应报文接口(头部报文)
|
||||
* @param sft modbus 头部参数结构体指针
|
||||
* @param rsp 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp)
|
||||
{
|
||||
/* Extract from MODBUS Messaging on TCP/IP Implementation
|
||||
Guide V1.0b (page 23/46):
|
||||
The transaction identifier is used to associate the future
|
||||
response with the request. */
|
||||
rsp[0] = sft->t_id >> 8;
|
||||
rsp[1] = sft->t_id & 0x00ff;
|
||||
|
||||
/* Protocol Modbus */
|
||||
rsp[2] = 0;
|
||||
rsp[3] = 0;
|
||||
|
||||
/* Length will be set later by send_msg (4 and 5) */
|
||||
|
||||
/* The slave ID is copied from the indication */
|
||||
rsp[6] = sft->slave;
|
||||
rsp[7] = sft->function;
|
||||
|
||||
return AGILE_MODBUS_TCP_PRESET_RSP_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 准备响应接口
|
||||
* @param req 请求数据指针
|
||||
* @param req_length 请求数据长度
|
||||
* @return 事务标识符
|
||||
*/
|
||||
static int agile_modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
|
||||
{
|
||||
return (req[0] << 8) + req[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 预发送数据接口(计算长度字段的值并存入)
|
||||
* @param req 数据存放指针
|
||||
* @param req_length 已有数据长度
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
|
||||
{
|
||||
/* Substract the header length to the message length */
|
||||
int mbap_length = req_length - 6;
|
||||
|
||||
req[4] = mbap_length >> 8;
|
||||
req[5] = mbap_length & 0x00FF;
|
||||
|
||||
return req_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 检查接收数据完整性接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param msg 接收数据指针
|
||||
* @param msg_length 有效数据长度
|
||||
* @return 有效数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
|
||||
{
|
||||
return msg_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 预检查确认接口(对比事务标识符和协议标识符)
|
||||
* @param ctx modbus 句柄
|
||||
* @param req 请求数据指针
|
||||
* @param rsp 响应数据指针
|
||||
* @param rsp_length 响应数据长度
|
||||
* @return 0:成功; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_tcp_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length)
|
||||
{
|
||||
/* Check transaction ID */
|
||||
if (req[0] != rsp[0] || req[1] != rsp[1])
|
||||
return -1;
|
||||
|
||||
/* Check protocol ID */
|
||||
if (rsp[2] != 0x0 && rsp[3] != 0x0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Private_Constants TCP Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 后端接口
|
||||
*/
|
||||
static const agile_modbus_backend_t agile_modbus_tcp_backend =
|
||||
{
|
||||
AGILE_MODBUS_BACKEND_TYPE_TCP,
|
||||
AGILE_MODBUS_TCP_HEADER_LENGTH,
|
||||
AGILE_MODBUS_TCP_CHECKSUM_LENGTH,
|
||||
AGILE_MODBUS_TCP_MAX_ADU_LENGTH,
|
||||
agile_modbus_tcp_set_slave,
|
||||
agile_modbus_tcp_build_request_basis,
|
||||
agile_modbus_tcp_build_response_basis,
|
||||
agile_modbus_tcp_prepare_response_tid,
|
||||
agile_modbus_tcp_send_msg_pre,
|
||||
agile_modbus_tcp_check_integrity,
|
||||
agile_modbus_tcp_pre_check_confirmation};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Functions TCP Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 初始化
|
||||
* @param ctx TCP 句柄
|
||||
* @param send_buf 发送缓冲区
|
||||
* @param send_bufsz 发送缓冲区大小
|
||||
* @param read_buf 接收缓冲区
|
||||
* @param read_bufsz 接收缓冲区大小
|
||||
* @return 0:成功
|
||||
*/
|
||||
int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
|
||||
{
|
||||
agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz);
|
||||
ctx->_ctx.backend = &agile_modbus_tcp_backend;
|
||||
ctx->_ctx.backend_data = ctx;
|
||||
|
||||
ctx->t_id = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
83
package/modbus/agile_modbus_tcp.h
Normal file
83
package/modbus/agile_modbus_tcp.h
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file agile_modbus_tcp.h
|
||||
* @brief Agile Modbus 软件包 TCP 头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_TCP_H
|
||||
#define __PKG_AGILE_MODBUS_TCP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup TCP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Constants TCP Exported Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_TCP_HEADER_LENGTH 7
|
||||
#define AGILE_MODBUS_TCP_PRESET_REQ_LENGTH 12
|
||||
#define AGILE_MODBUS_TCP_PRESET_RSP_LENGTH 8
|
||||
|
||||
#define AGILE_MODBUS_TCP_CHECKSUM_LENGTH 0
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||
TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_TCP_MAX_ADU_LENGTH 260
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Types TCP Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 结构体
|
||||
*/
|
||||
typedef struct agile_modbus_tcp {
|
||||
agile_modbus_t _ctx; /**< modbus 句柄 */
|
||||
uint16_t t_id; /**< Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
|
||||
(page 23/46):
|
||||
The transaction identifier is used to associate the future response
|
||||
with the request. This identifier is unique on each TCP connection. */
|
||||
} agile_modbus_tcp_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup TCP_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
5
package/modbus/modbus.py
Normal file
5
package/modbus/modbus.py
Normal file
@ -0,0 +1,5 @@
|
||||
import _modbus
|
||||
|
||||
|
||||
class ModBus(_modbus._Modbus):
|
||||
...
|
6
port/linux/.vscode/settings.json
vendored
6
port/linux/.vscode/settings.json
vendored
@ -60,6 +60,10 @@
|
||||
"streambuf": "c",
|
||||
"tuple": "c",
|
||||
"typeinfo": "c",
|
||||
"variant": "c"
|
||||
"variant": "c",
|
||||
"_modbus__modbus.h": "c",
|
||||
"agile_modbus.h": "c",
|
||||
"_modbus__modbusrtu.h": "c",
|
||||
"_modbus__modbustcp.h": "c"
|
||||
}
|
||||
}
|
31
port/linux/package/pikascript/_modbus.pyi
Normal file
31
port/linux/package/pikascript/_modbus.pyi
Normal file
@ -0,0 +1,31 @@
|
||||
class _ModBus:
|
||||
def setSlave(self, slave: int): ...
|
||||
def serializeReadBits(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadBits(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadInputBits(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadInputBits(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadRegisters(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReadInputRegisters(self, addr: int, nb: int) -> int: ...
|
||||
def deserializeReadInputRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeWriteBit(self, addr: int, status: int) -> int: ...
|
||||
def deserializeWriteBit(self, msgLength: int) -> int: ...
|
||||
def serializeWriteRegister(self, addr: int, value: int) -> int: ...
|
||||
def deserializeWriteRegister(self, msgLength: int) -> int: ...
|
||||
def serializeWriteBits(self, addr: int, nb: int, src: bytes) -> int: ...
|
||||
def deserializeWriteBits(self, msgLength: int) -> int: ...
|
||||
def serializeWriteRegisters(self, addr: int, nb: int, src: bytes) -> int: ...
|
||||
def deserializeWriteRegisters(self, msgLength: int) -> int: ...
|
||||
def serializeMaskWriteRegister(self, addr: int, andMask: int, orMask: int) -> int: ...
|
||||
def deserializeMaskWriteRegister(self, msgLength: int) -> int: ...
|
||||
def serializeWriteAndReadRegisters(self, writeAddr: int, writeNb: int, src: bytes, readAddr: int, readNb: int) -> int: ...
|
||||
def deserializeWriteAndReadRegisters(self, msgLength: int, dest: bytes) -> int: ...
|
||||
def serializeReportSlaveId(self) -> int: ...
|
||||
def deserializeReportSlaveId(self, msgLength: int, maxDest: int, dest: bytes) -> int: ...
|
||||
|
||||
class _ModBusRTU(_ModBus):
|
||||
def __init__(self, sendBuffSize: int, readBuffSize: int): ...
|
||||
|
||||
|
||||
class _ModBusTCP(_ModBus):
|
||||
def __init__(self, sendBuffSize: int, readBuffSize: int): ...
|
@ -20,6 +20,8 @@ import socket
|
||||
import random
|
||||
import re
|
||||
import PikaNN
|
||||
import modbus
|
||||
|
||||
mem = PikaStdLib.MemChecker()
|
||||
print('hello pikascript!')
|
||||
print('mem used max:')
|
||||
|
5
port/linux/package/pikascript/modbus.py
Normal file
5
port/linux/package/pikascript/modbus.py
Normal file
@ -0,0 +1,5 @@
|
||||
import _modbus
|
||||
|
||||
|
||||
class ModBus(_modbus._Modbus):
|
||||
...
|
201
port/linux/package/pikascript/pikascript-lib/modbus/LICENSE
Normal file
201
port/linux/package/pikascript/pikascript-lib/modbus/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
183
port/linux/package/pikascript/pikascript-lib/modbus/_modbus.c
Normal file
183
port/linux/package/pikascript/pikascript-lib/modbus/_modbus.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include "_modbus__ModBus.h"
|
||||
#include "_modbus__ModBusRTU.h"
|
||||
#include "_modbus__ModBusTCP.h"
|
||||
#include "agile_modbus.h"
|
||||
|
||||
void _modbus__ModBusRTU___init__(PikaObj* self,
|
||||
int sendBUffSize,
|
||||
int readBuffSize) {
|
||||
agile_modbus_rtu_t ctx_rtu = {0};
|
||||
agile_modbus_t* ctx = &ctx_rtu._ctx;
|
||||
obj_setBytes(self, "sendBuff", NULL, sendBUffSize);
|
||||
obj_setBytes(self, "readBuff", NULL, readBuffSize);
|
||||
agile_modbus_rtu_init(&ctx_rtu, obj_getBytes(self, "sendBuff"),
|
||||
sendBUffSize, obj_getBytes(self, "readBuff"),
|
||||
readBuffSize);
|
||||
obj_setStruct(self, "ctx_rtu", ctx_rtu);
|
||||
obj_setPtr(self, "ctx", ctx);
|
||||
}
|
||||
|
||||
void _modbus__ModBus_setSlave(PikaObj* self, int slave) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
agile_modbus_set_slave(ctx, slave);
|
||||
}
|
||||
|
||||
void _modbus__ModBusTCP___init__(PikaObj* self,
|
||||
int sendBuffSize,
|
||||
int readBuffSize) {
|
||||
agile_modbus_tcp_t ctx_tcp = {0};
|
||||
agile_modbus_t* ctx = &ctx_tcp._ctx;
|
||||
obj_setBytes(self, "sendBuff", NULL, sendBuffSize);
|
||||
obj_setBytes(self, "readBuff", NULL, readBuffSize);
|
||||
agile_modbus_tcp_init(&ctx_tcp, obj_getBytes(self, "sendBuff"),
|
||||
sendBuffSize, obj_getBytes(self, "readBuff"),
|
||||
readBuffSize);
|
||||
obj_setStruct(self, "ctx_tcp", ctx_tcp);
|
||||
obj_setPtr(self, "ctx", ctx);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeMaskWriteRegister(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_mask_write_register(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadBits(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_bits(ctx, msgLength, dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadInputBits(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_input_bits(ctx, msgLength, dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadInputRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_input_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReadRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_read_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeReportSlaveId(PikaObj* self,
|
||||
int msgLength,
|
||||
int maxDest,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_report_slave_id(ctx, msgLength, maxDest,
|
||||
dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteAndReadRegisters(PikaObj* self,
|
||||
int msgLength,
|
||||
uint8_t* dest) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_and_read_registers(ctx, msgLength,
|
||||
(uint16_t*)dest);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteBit(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_bit(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteBits(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_bits(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteRegister(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_register(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_deserializeWriteRegisters(PikaObj* self, int msgLength) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_deserialize_write_registers(ctx, msgLength);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeMaskWriteRegister(PikaObj* self,
|
||||
int addr,
|
||||
int andMask,
|
||||
int orMask) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_mask_write_register(ctx, addr, andMask,
|
||||
orMask);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadBits(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_bits(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadInputBits(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_input_bits(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadInputRegisters(PikaObj* self,
|
||||
int addr,
|
||||
int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_input_registers(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReadRegisters(PikaObj* self, int addr, int nb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_read_registers(ctx, addr, nb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeReportSlaveId(PikaObj* self) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_report_slave_id(ctx);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteAndReadRegisters(PikaObj* self,
|
||||
int writeAddr,
|
||||
int writeNb,
|
||||
uint8_t* src,
|
||||
int readAddr,
|
||||
int readNb) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_and_read_registers(
|
||||
ctx, writeAddr, writeNb, (uint16_t*)src, readAddr, readNb);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteBit(PikaObj* self, int addr, int status) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_bit(ctx, addr, status);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteBits(PikaObj* self,
|
||||
int addr,
|
||||
int nb,
|
||||
uint8_t* src) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_bits(ctx, addr, nb, src);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteRegister(PikaObj* self, int addr, int value) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_register(ctx, addr, value);
|
||||
}
|
||||
|
||||
int _modbus__ModBus_serializeWriteRegisters(PikaObj* self,
|
||||
int addr,
|
||||
int nb,
|
||||
uint8_t* src) {
|
||||
agile_modbus_t* ctx = obj_getPtr(self, "ctx");
|
||||
return agile_modbus_serialize_write_registers(ctx, addr, nb,
|
||||
(uint16_t*)src);
|
||||
}
|
1519
port/linux/package/pikascript/pikascript-lib/modbus/agile_modbus.c
Normal file
1519
port/linux/package/pikascript/pikascript-lib/modbus/agile_modbus.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,359 @@
|
||||
/**
|
||||
* @file agile_modbus.h
|
||||
* @brief Agile Modbus 软件包通用头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2022-07-28
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_H
|
||||
#define __PKG_AGILE_MODBUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup COMMON
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup COMMON_Exported_Constants Common Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup Modbus_Function_Codes Modbus Function Codes
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_FC_READ_COILS 0x01
|
||||
#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS 0x02
|
||||
#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS 0x03
|
||||
#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS 0x04
|
||||
#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL 0x05
|
||||
#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
|
||||
#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS 0x07
|
||||
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F
|
||||
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
|
||||
#define AGILE_MODBUS_FC_REPORT_SLAVE_ID 0x11
|
||||
#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER 0x16
|
||||
#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup Modbus_Constants Modbus Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_VERSION_STRING "AMB_1.1.0" /**< Agile Modbus 版本号 */
|
||||
|
||||
#define AGILE_MODBUS_BROADCAST_ADDRESS 0 /**< Modbus 广播地址 */
|
||||
|
||||
/** @name Quantity limit of Coils
|
||||
@verbatim
|
||||
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)
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_READ_BITS 2000
|
||||
#define AGILE_MODBUS_MAX_WRITE_BITS 1968
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @name Quantity limit of Registers
|
||||
@verbatim
|
||||
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)
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_READ_REGISTERS 125
|
||||
#define AGILE_MODBUS_MAX_WRITE_REGISTERS 123
|
||||
#define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS 121
|
||||
#define AGILE_MODBUS_MAX_WR_READ_REGISTERS 125
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
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.
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_PDU_LENGTH 253
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
Consequently:
|
||||
- RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256
|
||||
bytes.
|
||||
- TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.
|
||||
so the maximum of both backend in 260 bytes. This size can used to allocate
|
||||
an array of bytes to store responses and it will be compatible with the two
|
||||
backends.
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_MAX_ADU_LENGTH 260
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup COMMON_Exported_Types Common Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Modbus 异常码
|
||||
*/
|
||||
enum {
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
|
||||
AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
|
||||
AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
|
||||
AGILE_MODBUS_EXCEPTION_ACKNOWLEDGE,
|
||||
AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
|
||||
AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
|
||||
AGILE_MODBUS_EXCEPTION_MEMORY_PARITY,
|
||||
AGILE_MODBUS_EXCEPTION_NOT_DEFINED,
|
||||
AGILE_MODBUS_EXCEPTION_GATEWAY_PATH,
|
||||
AGILE_MODBUS_EXCEPTION_GATEWAY_TARGET,
|
||||
AGILE_MODBUS_EXCEPTION_UNKNOW = 0xff
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modbus 后端类型
|
||||
*/
|
||||
typedef enum {
|
||||
AGILE_MODBUS_BACKEND_TYPE_RTU = 0, /**< RTU */
|
||||
AGILE_MODBUS_BACKEND_TYPE_TCP /**< TCP */
|
||||
} agile_modbus_backend_type_t;
|
||||
|
||||
/**
|
||||
* @brief Modbus 收到消息类型
|
||||
*
|
||||
@verbatim
|
||||
---------- Request Indication ----------
|
||||
| Client | ---------------------->| Server |
|
||||
---------- Confirmation Response ----------
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
typedef enum {
|
||||
AGILE_MODBUS_MSG_INDICATION, /**< 主机端的请求消息 */
|
||||
AGILE_MODBUS_MSG_CONFIRMATION /**< 服务器端的请求消息 */
|
||||
} agile_modbus_msg_type_t;
|
||||
|
||||
/**
|
||||
* @brief 包含 modbus 头部参数结构体
|
||||
*/
|
||||
typedef struct agile_modbus_sft {
|
||||
int slave; /**< 从机地址 */
|
||||
int function; /**< 功能码 */
|
||||
int t_id; /**< 事务标识符 */
|
||||
} agile_modbus_sft_t;
|
||||
|
||||
typedef struct agile_modbus agile_modbus_t; /**< Agile Modbus 结构体 */
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 后端接口结构体
|
||||
*/
|
||||
typedef struct agile_modbus_backend {
|
||||
uint32_t backend_type; /**< 后端类型 */
|
||||
uint32_t header_length; /**< 头部长度,不包含功能码 */
|
||||
uint32_t checksum_length; /**< 校验数据长度 */
|
||||
uint32_t max_adu_length; /**< 后端 ADU 长度 */
|
||||
int (*set_slave)(agile_modbus_t *ctx, int slave); /**< 设置地址接口 */
|
||||
int (*build_request_basis)(agile_modbus_t *ctx, int function, int addr,
|
||||
int nb, uint8_t *req); /**< 构建基础请求报文接口 */
|
||||
int (*build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp); /**< 构建基础响应报文接口 */
|
||||
int (*prepare_response_tid)(const uint8_t *req, int *req_length); /**< 准备响应接口 */
|
||||
int (*send_msg_pre)(uint8_t *req, int req_length); /**< 预发送数据接口 */
|
||||
int (*check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length); /**< 检查接收数据完整性接口 */
|
||||
int (*pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length); /**< 预检查确认接口 */
|
||||
} agile_modbus_backend_t;
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 结构体
|
||||
*/
|
||||
struct agile_modbus {
|
||||
int slave; /**< 从机地址 */
|
||||
uint8_t *send_buf; /**< 发送缓冲区 */
|
||||
int send_bufsz; /**< 发送缓冲区大小 */
|
||||
uint8_t *read_buf; /**< 接收缓冲区 */
|
||||
int read_bufsz; /**< 接收缓冲区大小 */
|
||||
uint8_t (*compute_meta_length_after_function)(agile_modbus_t *ctx, int function,
|
||||
agile_modbus_msg_type_t msg_type); /**< 自定义计算数据元长度接口 */
|
||||
int (*compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg,
|
||||
int msg_length, agile_modbus_msg_type_t msg_type); /**< 自定义计算数据长度接口 */
|
||||
const agile_modbus_backend_t *backend; /**< 后端接口 */
|
||||
void *backend_data; /**< 后端数据,指向 RTU 或 TCP 结构体 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Slave
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup Slave_Exported_Types Slave Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Agile Modbus 从机信息结构体
|
||||
*/
|
||||
struct agile_modbus_slave_info {
|
||||
agile_modbus_sft_t *sft; /**< sft 结构体指针 */
|
||||
int *rsp_length; /**< 响应数据长度指针 */
|
||||
int address; /**< 寄存器地址 */
|
||||
int nb; /**< 数目 */
|
||||
uint8_t *buf; /**< 不同功能码需要使用的数据域 */
|
||||
int send_index; /**< 发送缓冲区当前索引 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 从机回调函数
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave_info 从机信息体
|
||||
* @param data 私有数据
|
||||
* @return =0:正常;
|
||||
* <0:异常
|
||||
* (-AGILE_MODBUS_EXCEPTION_UNKNOW(-255): 未知异常,从机不会打包响应数据)
|
||||
* (其他负数异常码: 从机会打包异常响应数据)
|
||||
*/
|
||||
typedef int (*agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup COMMON_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
int agile_modbus_set_slave(agile_modbus_t *ctx, int slave);
|
||||
void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx,
|
||||
uint8_t (*cb)(agile_modbus_t *ctx, int function,
|
||||
agile_modbus_msg_type_t msg_type));
|
||||
void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx,
|
||||
int (*cb)(agile_modbus_t *ctx, uint8_t *msg,
|
||||
int msg_length, agile_modbus_msg_type_t msg_type));
|
||||
int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Master
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Master_Common_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
|
||||
int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
|
||||
int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb);
|
||||
int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status);
|
||||
int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value);
|
||||
int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src);
|
||||
int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src);
|
||||
int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
|
||||
int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length);
|
||||
int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx,
|
||||
int write_addr, int write_nb,
|
||||
const uint16_t *src,
|
||||
int read_addr, int read_nb);
|
||||
int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
|
||||
int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx);
|
||||
int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Master_Raw_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
|
||||
int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Modbus_Slave
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Slave_Operation_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict,
|
||||
agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length);
|
||||
void agile_modbus_slave_io_set(uint8_t *buf, int index, int status);
|
||||
uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index);
|
||||
void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data);
|
||||
uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Include RTU and TCP module */
|
||||
#include "agile_modbus_rtu.h"
|
||||
#include "agile_modbus_tcp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PKG_AGILE_MODBUS_H */
|
@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @file agile_modbus_rtu.c
|
||||
* @brief Agile Modbus 软件包 RTU 源文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "agile_modbus.h"
|
||||
#include "agile_modbus_rtu.h"
|
||||
|
||||
/** @defgroup RTU RTU
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Private_Constants RTU Private Constants
|
||||
* @{
|
||||
*/
|
||||
/** Table of CRC values for high-order byte */
|
||||
static const uint8_t _table_crc_hi[] =
|
||||
{
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
|
||||
|
||||
/** Table of CRC values for low-order byte */
|
||||
static const uint8_t _table_crc_lo[] =
|
||||
{
|
||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
|
||||
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
|
||||
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
|
||||
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
|
||||
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
|
||||
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
|
||||
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
|
||||
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
|
||||
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
|
||||
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
|
||||
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
|
||||
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
|
||||
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
|
||||
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
|
||||
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
|
||||
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
|
||||
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
|
||||
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
|
||||
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
|
||||
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
|
||||
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
|
||||
0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Private_Functions RTU Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU CRC16 计算
|
||||
* @param buffer 数据指针
|
||||
* @param buffer_length 数据长度
|
||||
* @return CRC16 值
|
||||
*/
|
||||
static uint16_t agile_modbus_rtu_crc16(uint8_t *buffer, uint16_t buffer_length)
|
||||
{
|
||||
uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
|
||||
uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
|
||||
unsigned int i; /* will index into CRC lookup */
|
||||
|
||||
/* pass through message buffer */
|
||||
while (buffer_length--) {
|
||||
i = crc_hi ^ *buffer++; /* calculate the CRC */
|
||||
crc_hi = crc_lo ^ _table_crc_hi[i];
|
||||
crc_lo = _table_crc_lo[i];
|
||||
}
|
||||
|
||||
return (crc_hi << 8 | crc_lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 设置地址接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave 从机地址
|
||||
* @return 0:成功
|
||||
*/
|
||||
static int agile_modbus_rtu_set_slave(agile_modbus_t *ctx, int slave)
|
||||
{
|
||||
ctx->slave = slave;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 构建基础请求报文接口(头部报文)
|
||||
* @param ctx modbus 句柄
|
||||
* @param function 功能码
|
||||
* @param addr 寄存器地址
|
||||
* @param nb 寄存器数目
|
||||
* @param req 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_build_request_basis(agile_modbus_t *ctx, int function,
|
||||
int addr, int nb,
|
||||
uint8_t *req)
|
||||
{
|
||||
req[0] = ctx->slave;
|
||||
req[1] = function;
|
||||
req[2] = addr >> 8;
|
||||
req[3] = addr & 0x00ff;
|
||||
req[4] = nb >> 8;
|
||||
req[5] = nb & 0x00ff;
|
||||
|
||||
return AGILE_MODBUS_RTU_PRESET_REQ_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 构建基础响应报文接口(头部报文)
|
||||
* @param sft modbus 头部参数结构体指针
|
||||
* @param rsp 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp)
|
||||
{
|
||||
rsp[0] = sft->slave;
|
||||
rsp[1] = sft->function;
|
||||
|
||||
return AGILE_MODBUS_RTU_PRESET_RSP_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 准备响应接口
|
||||
* @note 该 API 会将 req_length 自动减去 AGILE_MODBUS_RTU_CHECKSUM_LENGTH 长度
|
||||
* @param req 请求数据指针
|
||||
* @param req_length 请求数据长度
|
||||
* @return 0 (RTU 没有事务标识符)
|
||||
*/
|
||||
static int agile_modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
|
||||
{
|
||||
(*req_length) -= AGILE_MODBUS_RTU_CHECKSUM_LENGTH;
|
||||
/* No TID */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 预发送数据接口
|
||||
* @note 该 API 会计算 CRC16 并自动填入尾部
|
||||
* @param req 数据存放指针
|
||||
* @param req_length 已有数据长度
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
|
||||
{
|
||||
uint16_t crc = agile_modbus_rtu_crc16(req, req_length);
|
||||
req[req_length++] = crc >> 8;
|
||||
req[req_length++] = crc & 0x00FF;
|
||||
|
||||
return req_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 检查接收数据完整性接口(CRC16 对比)
|
||||
* @param ctx modbus 句柄
|
||||
* @param msg 接收数据指针
|
||||
* @param msg_length 有效数据长度
|
||||
* @return >0:有效数据长度; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_rtu_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
|
||||
{
|
||||
uint16_t crc_calculated;
|
||||
uint16_t crc_received;
|
||||
|
||||
crc_calculated = agile_modbus_rtu_crc16(msg, msg_length - 2);
|
||||
crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
|
||||
|
||||
/* Check CRC of msg */
|
||||
if (crc_calculated == crc_received)
|
||||
return msg_length;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTU 预检查确认接口(请求响应地址对比)
|
||||
* @note 如果请求地址是广播地址0,返回成功
|
||||
* @param ctx modbus 句柄
|
||||
* @param req 请求数据指针
|
||||
* @param rsp 响应数据指针
|
||||
* @param rsp_length 响应数据长度
|
||||
* @return 0:成功; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_rtu_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length)
|
||||
{
|
||||
/* Check responding slave is the slave we requested (except for broacast
|
||||
* request) */
|
||||
if (req[0] != rsp[0] && req[0] != AGILE_MODBUS_BROADCAST_ADDRESS)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTU_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 后端接口
|
||||
*/
|
||||
static const agile_modbus_backend_t agile_modbus_rtu_backend =
|
||||
{
|
||||
AGILE_MODBUS_BACKEND_TYPE_RTU,
|
||||
AGILE_MODBUS_RTU_HEADER_LENGTH,
|
||||
AGILE_MODBUS_RTU_CHECKSUM_LENGTH,
|
||||
AGILE_MODBUS_RTU_MAX_ADU_LENGTH,
|
||||
agile_modbus_rtu_set_slave,
|
||||
agile_modbus_rtu_build_request_basis,
|
||||
agile_modbus_rtu_build_response_basis,
|
||||
agile_modbus_rtu_prepare_response_tid,
|
||||
agile_modbus_rtu_send_msg_pre,
|
||||
agile_modbus_rtu_check_integrity,
|
||||
agile_modbus_rtu_pre_check_confirmation};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Functions RTU Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 初始化
|
||||
* @param ctx RTU 句柄
|
||||
* @param send_buf 发送缓冲区
|
||||
* @param send_bufsz 发送缓冲区大小
|
||||
* @param read_buf 接收缓冲区
|
||||
* @param read_bufsz 接收缓冲区大小
|
||||
* @return 0:成功
|
||||
*/
|
||||
int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
|
||||
{
|
||||
agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz);
|
||||
ctx->_ctx.backend = &agile_modbus_rtu_backend;
|
||||
ctx->_ctx.backend_data = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file agile_modbus_rtu.h
|
||||
* @brief Agile Modbus 软件包 RTU 头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_RTU_H
|
||||
#define __PKG_AGILE_MODBUS_RTU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup RTU
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Constants RTU Exported Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_RTU_HEADER_LENGTH 1
|
||||
#define AGILE_MODBUS_RTU_PRESET_REQ_LENGTH 6
|
||||
#define AGILE_MODBUS_RTU_PRESET_RSP_LENGTH 2
|
||||
|
||||
#define AGILE_MODBUS_RTU_CHECKSUM_LENGTH 2
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
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
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_RTU_MAX_ADU_LENGTH 256
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTU_Exported_Types RTU Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTU 结构体
|
||||
*/
|
||||
typedef struct agile_modbus_rtu {
|
||||
agile_modbus_t _ctx; /**< modbus 句柄 */
|
||||
} agile_modbus_rtu_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTU_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_rtu_init(agile_modbus_rtu_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PKG_AGILE_MODBUS_RTU_H */
|
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @file agile_modbus_tcp.c
|
||||
* @brief Agile Modbus 软件包 TCP 源文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "agile_modbus.h"
|
||||
#include "agile_modbus_tcp.h"
|
||||
|
||||
/** @defgroup TCP TCP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Private_Functions TCP Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 设置地址接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param slave 从机地址
|
||||
* @return 0:成功
|
||||
*/
|
||||
static int agile_modbus_tcp_set_slave(agile_modbus_t *ctx, int slave)
|
||||
{
|
||||
ctx->slave = slave;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 构建基础请求报文接口(头部报文)
|
||||
* @param ctx modbus 句柄
|
||||
* @param function 功能码
|
||||
* @param addr 寄存器地址
|
||||
* @param nb 寄存器数目
|
||||
* @param req 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_build_request_basis(agile_modbus_t *ctx, int function,
|
||||
int addr, int nb,
|
||||
uint8_t *req)
|
||||
{
|
||||
agile_modbus_tcp_t *ctx_tcp = ctx->backend_data;
|
||||
|
||||
/* Increase transaction ID */
|
||||
if (ctx_tcp->t_id < UINT16_MAX)
|
||||
ctx_tcp->t_id++;
|
||||
else
|
||||
ctx_tcp->t_id = 0;
|
||||
req[0] = ctx_tcp->t_id >> 8;
|
||||
req[1] = ctx_tcp->t_id & 0x00ff;
|
||||
|
||||
/* Protocol Modbus */
|
||||
req[2] = 0;
|
||||
req[3] = 0;
|
||||
|
||||
/* Length will be defined later by set_req_length_tcp at offsets 4
|
||||
and 5 */
|
||||
|
||||
req[6] = ctx->slave;
|
||||
req[7] = function;
|
||||
req[8] = addr >> 8;
|
||||
req[9] = addr & 0x00ff;
|
||||
req[10] = nb >> 8;
|
||||
req[11] = nb & 0x00ff;
|
||||
|
||||
return AGILE_MODBUS_TCP_PRESET_REQ_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 构建基础响应报文接口(头部报文)
|
||||
* @param sft modbus 头部参数结构体指针
|
||||
* @param rsp 数据存放指针
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_build_response_basis(agile_modbus_sft_t *sft, uint8_t *rsp)
|
||||
{
|
||||
/* Extract from MODBUS Messaging on TCP/IP Implementation
|
||||
Guide V1.0b (page 23/46):
|
||||
The transaction identifier is used to associate the future
|
||||
response with the request. */
|
||||
rsp[0] = sft->t_id >> 8;
|
||||
rsp[1] = sft->t_id & 0x00ff;
|
||||
|
||||
/* Protocol Modbus */
|
||||
rsp[2] = 0;
|
||||
rsp[3] = 0;
|
||||
|
||||
/* Length will be set later by send_msg (4 and 5) */
|
||||
|
||||
/* The slave ID is copied from the indication */
|
||||
rsp[6] = sft->slave;
|
||||
rsp[7] = sft->function;
|
||||
|
||||
return AGILE_MODBUS_TCP_PRESET_RSP_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 准备响应接口
|
||||
* @param req 请求数据指针
|
||||
* @param req_length 请求数据长度
|
||||
* @return 事务标识符
|
||||
*/
|
||||
static int agile_modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
|
||||
{
|
||||
return (req[0] << 8) + req[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 预发送数据接口(计算长度字段的值并存入)
|
||||
* @param req 数据存放指针
|
||||
* @param req_length 已有数据长度
|
||||
* @return 数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
|
||||
{
|
||||
/* Substract the header length to the message length */
|
||||
int mbap_length = req_length - 6;
|
||||
|
||||
req[4] = mbap_length >> 8;
|
||||
req[5] = mbap_length & 0x00FF;
|
||||
|
||||
return req_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 检查接收数据完整性接口
|
||||
* @param ctx modbus 句柄
|
||||
* @param msg 接收数据指针
|
||||
* @param msg_length 有效数据长度
|
||||
* @return 有效数据长度
|
||||
*/
|
||||
static int agile_modbus_tcp_check_integrity(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
|
||||
{
|
||||
return msg_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCP 预检查确认接口(对比事务标识符和协议标识符)
|
||||
* @param ctx modbus 句柄
|
||||
* @param req 请求数据指针
|
||||
* @param rsp 响应数据指针
|
||||
* @param rsp_length 响应数据长度
|
||||
* @return 0:成功; 其他:异常
|
||||
*/
|
||||
static int agile_modbus_tcp_pre_check_confirmation(agile_modbus_t *ctx, const uint8_t *req,
|
||||
const uint8_t *rsp, int rsp_length)
|
||||
{
|
||||
/* Check transaction ID */
|
||||
if (req[0] != rsp[0] || req[1] != rsp[1])
|
||||
return -1;
|
||||
|
||||
/* Check protocol ID */
|
||||
if (rsp[2] != 0x0 && rsp[3] != 0x0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Private_Constants TCP Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 后端接口
|
||||
*/
|
||||
static const agile_modbus_backend_t agile_modbus_tcp_backend =
|
||||
{
|
||||
AGILE_MODBUS_BACKEND_TYPE_TCP,
|
||||
AGILE_MODBUS_TCP_HEADER_LENGTH,
|
||||
AGILE_MODBUS_TCP_CHECKSUM_LENGTH,
|
||||
AGILE_MODBUS_TCP_MAX_ADU_LENGTH,
|
||||
agile_modbus_tcp_set_slave,
|
||||
agile_modbus_tcp_build_request_basis,
|
||||
agile_modbus_tcp_build_response_basis,
|
||||
agile_modbus_tcp_prepare_response_tid,
|
||||
agile_modbus_tcp_send_msg_pre,
|
||||
agile_modbus_tcp_check_integrity,
|
||||
agile_modbus_tcp_pre_check_confirmation};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Functions TCP Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 初始化
|
||||
* @param ctx TCP 句柄
|
||||
* @param send_buf 发送缓冲区
|
||||
* @param send_bufsz 发送缓冲区大小
|
||||
* @param read_buf 接收缓冲区
|
||||
* @param read_bufsz 接收缓冲区大小
|
||||
* @return 0:成功
|
||||
*/
|
||||
int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
|
||||
{
|
||||
agile_modbus_common_init(&(ctx->_ctx), send_buf, send_bufsz, read_buf, read_bufsz);
|
||||
ctx->_ctx.backend = &agile_modbus_tcp_backend;
|
||||
ctx->_ctx.backend_data = ctx;
|
||||
|
||||
ctx->t_id = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file agile_modbus_tcp.h
|
||||
* @brief Agile Modbus 软件包 TCP 头文件
|
||||
* @author 马龙伟 (2544047213@qq.com)
|
||||
* @date 2021-12-02
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Ma Longwei.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PKG_AGILE_MODBUS_TCP_H
|
||||
#define __PKG_AGILE_MODBUS_TCP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup TCP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Constants TCP Exported Constants
|
||||
* @{
|
||||
*/
|
||||
#define AGILE_MODBUS_TCP_HEADER_LENGTH 7
|
||||
#define AGILE_MODBUS_TCP_PRESET_REQ_LENGTH 12
|
||||
#define AGILE_MODBUS_TCP_PRESET_RSP_LENGTH 8
|
||||
|
||||
#define AGILE_MODBUS_TCP_CHECKSUM_LENGTH 0
|
||||
|
||||
/**
|
||||
@verbatim
|
||||
Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||
TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
#define AGILE_MODBUS_TCP_MAX_ADU_LENGTH 260
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TCP_Exported_Types TCP Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TCP 结构体
|
||||
*/
|
||||
typedef struct agile_modbus_tcp {
|
||||
agile_modbus_t _ctx; /**< modbus 句柄 */
|
||||
uint16_t t_id; /**< Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
|
||||
(page 23/46):
|
||||
The transaction identifier is used to associate the future response
|
||||
with the request. This identifier is unique on each TCP connection. */
|
||||
} agile_modbus_tcp_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup TCP_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
int agile_modbus_tcp_init(agile_modbus_tcp_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user