libmodbus手冊函數詳解

最近做libmodbus相關內容,因爲中文沒有libmodbus各個函數的詳細解釋,所以在此把要用的libmodbus的手冊包括所有的函數都翻譯整理一下,給自己和大家們學習,歡迎大家交流指正。手冊原文http://libmodbus.org/docs/v3.0.6/,   http://libmodbus.org/docs/v3.1.4/


 

目錄

libmodbus

特點

概要

描述

環境(contexts)

RTU環境

創建modbus RTU 環境

初試化RTU環境指針 modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)

設置串口模式

獲取當前串口模式 int modbus_rtu_get_serial_mode(modbus_t *ctx);

設置串口模式 int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);

在 RTU環境下 中獲取當前RTS模式 int modbus_rtu_get_rts(modbus_t *ctx)(3.1.4版本補充)

在RTU環境下獲取設置RTS模式 int modbus_rtu_set_rts(modbus_t *ctx, int mode)(3.1.4版本補充)

自定義RTS實現 int modbus_rtu_set_custom_rts(modbus_t *ctx, void (set_rts) (modbus_t ctx, int on))(3.1.4版本補充)

獲取RTU中當前RTS延遲 int modbus_rtu_get_rts_delay(modbus_t *ctx);(3.1.4版本補充)

設置RTU中的RTS延遲   int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);(3.1.4版本補充)

TCP(IPv4)環境

創建Modbus TCP環境 modbus_t *modbus_new_tcp(const char *ip, int port);

TCP PI(IPv4和IPv6)環境

創建Modbus TCP PI環境modbus_t *modbus_new_tcp_pi(const char *node, const char *service);

通用函數:

釋放modbus環境void modbus_free(modbus_t *ctx);

設置從站ID int modbus_set_slave(modbus_t *ctx, int slave);(3.1.4版本補充)

啓用調試模式 int modbus_set_debug(modbus_t *ctx, int flag);(3.1.4版本補充)

超時設置: 

獲取字節之間的超時 int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);

設置字節之間超時間隔 void modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);

獲取響應超時時間void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout);

設置超時響應時間 void modbus_set_response_timeout(modbus_t *ctx, struct timeval *timeout);

設置錯誤恢復模式 int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);(3.1.4版本補充)

設置環境套接字(socket )int modbus_set_socket(modbus_t *ctx, int s);

獲取環境套接字(socket) int modbus_get_socket(modbus_t *ctx);

檢索當前標頭長度 int modbus_get_header_length(modbus_t *ctx);

用於數據操作的宏

用於操作位和字節的函數(3.1.4版本修改)

從單個字節值設置多個位void modbus_set_bits_from_byte(uint8_t *dest, int index, const uint8_t value);

從字節數組設置多個位void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte);

從多個位獲取數值uint8_t modbus_get_byte_from_bits(const uint8_t *src, int index, unsigned int nb_bits);

設置或獲取浮點數

ABCD順序獲取浮點值float modbus_get_float_abcd(const uint16_t *src);

ABCD順序存儲浮點值void modbus_set_float_abcd(float f, uint16_t *dest);

BADC順序獲取浮點值float modbus_get_float_badc(const uint16_t *src);

BADC順序存儲浮點值void modbus_set_float_badc(float f, uint16_t *dest);

CDAB順序獲取浮點值float modbus_get_float_cdab(const uint16_t *src);

CDAB順序存儲浮點值void modbus_set_float_cdab(float f, uint16_t *dest);

DCBA順序獲取浮點值float modbus_get_float_dcba(const uint16_t *src);

DCBA順序存儲浮點值void modbus_set_float_dcba(float f, uint16_t *dest);

連接

建立連接 int modbus_connect(modbus_t *ctx);

關閉連接 void modbus_close(modbus_t *ctx);

沖洗未連接數據int modbus_flush(modbus_t *ctx);

主機(客戶端Client)

讀取數據

讀取位(讀取線圈狀態) int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

讀取輸入位(讀取輸入狀態) int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

讀取保持寄存器 int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

讀取輸入寄存器int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

讀取控制器(controller)描述  int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);

寫數據

寫一位數據(強置單線圈)int modbus_write_bit(modbus_t *ctx, int addr, int status);

寫單寄存器(預置單寄存器)int modbus_write_register(modbus_t *ctx, int addr, int value);

寫多位數據(強置多線圈)int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);

寫多寄存器(預置多寄存器)int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);

寫和讀數據

在單個處理中寫入和讀取多個寄存器int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb, const uint16_t *dest);

原始請求

發送原始請求 int modbus_send_raw_request (modbus_t *ctx, uint8_t *raw_req, int raw_req_length);

收到確認請求 int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);

回覆異常

發送一個異常響應*int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

從機(服務器server)

數據映射

分配位(線圈)和寄存器的數組modbus_mapping_t modbus_mapping_new (int nb_bits, int nb_input_bits, int nb_registers, intnb_input_registers);

釋放modbus_mapping_t 結構void modbus_mapping_free(modbus_mapping_t *mb_mapping);

接收

收到指示請求 int modbus_receive(modbus_t *ctx, uint8_t *req);

回覆

響應收到的請求int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);

發送異常響應int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

錯誤處理

返回錯誤信息const char *modbus_strerror(int errnum);

雜項

版權協議


 

libmodbus

版本號:V3.0.6(已加入3.1.4版本補充)

特點

     libmodbus是一個快速、跨平臺的Modbus庫。

概要

#include <modbus.h>

cc `pkg-config --cflags --libs libmodbus` files

描述

libmodbus是一個與使用Modbus協議的設備進行數據發送/接收的庫。該庫包含各種後端(backends)通過不同網絡進行通信(例如,RTU模式下的串口或TCP / IPv6中的以太網)。

 http://www.modbus.org網站提供了協議規範文檔http://www.modbus.org/specs.php

libmodbus提供了較低通信層的抽象,並在所有支持的平臺上提供相同的API。

本文檔介紹了了libmodbus概念,介紹了libmodbus如何從在不同的硬件和平臺中實現Modbus通信,併爲libmodbus庫提供的函數提供了參考手冊。

環境(contexts)

Modbus協議包含許多變體(例如串行RTU或Ehternet TCP),爲了簡化變體的實現,該庫被設計成爲每個變體使用後端(backends)。後端也是滿足其他要求(例如實時操作)的便捷方法。每個後端都提供了一個特定的函數來創建一個新的modbus_t環境。 modbus_t環境是一個不透明的結構,包含根據所選變體與其他Modbus設備建立連接的所有必要信息。


RTU環境

RTU後端(遠程終端單元)用於串口通信,並使用用於協議通信的數據的緊湊的二進制表示形式。RTU格式遵循命令/數據,和CRC(cyclic redundancy check循環冗餘校驗)作爲錯誤檢查機制,以確保數據的可靠性。Modbus RTU是可用於Modbus的最常用的實現方式。Modbus RTU消息必須連續發送,不能有字符間隔(摘自Wikipedia,Modbus, http://en.wikipedia.org/wiki/Modbus  截至2011年3月13日,格林尼治時間20:51)。

Modbus RTU框架調用一個從站,一個處理Modbus請求的設備/服務器,以及一個發送請求的客戶端(主站)。通信始終由主站服務端發起。

許多Modbus設備可以在同一個的物理鏈路上連接在一起(總線結構),因此在發送消息之前,必須使用modbus_set_slave設置從站(接收設備 )ID。如果您正在運行一個從站,則其從站號將用於過濾接收的消息。

 

創建modbus RTU 環境

初試化RTU環境指針 modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)

modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);


//參考代碼:
modbus_t *ctx;
 
ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}

這個 modbus_new_rtu()函數會生成並初始化一個modbus的結構體來在串行線路中使用RTU模式進行通訊。

device 指定OS處理的串行端口的名稱,比如 /dev/ttyS0 or /dev/ttyUSB0,在windows系統上,如果COM編號大於9,必須要在COM前加上\\.\ ,比如 \\\\.\\COM10.,參照http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx

 baud :指定連接的波特率,比如9600, 19200, 57600, 115200等。

parity :代表奇偶檢驗位,有如下值:

N   無奇偶校驗

E  偶數校驗

O  奇數校驗

data_bit :指定數據的位數,允許值有: 5, 6, 7 ,8.

stop_bit :指定停止位位數,允許值有1和2.

返回:如果建立成功,modbus_new_rtu()函數將返回指向modbus_t結構的指針。 否則它將返回NULL並將errno設置爲An invalid argument was given.。

設置串口模式

獲取當前串口模式 int modbus_rtu_get_serial_mode(modbus_t *ctx);

int modbus_rtu_get_serial_mode (modbus_t *ctx);

返回:如果成功, 函數應返回 MODBUS_RTU_RS232 或 MODBUS_RTU_RS485 。否則, 它將返回-1並將errno設爲The current libmodbus backend is not RTU.

只用於RTU環境。

設置串口模式 int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);

int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);

mode: 填入 MODBUS_RTU_RS232 或 MODBUS_RTU_RS485

返回值:如果成功, 函數應返回0。否則, 它將返回-1 並將 errno 設置爲下面定義的值之一。

EINVAL The current libmodbus backend is not RTU.

ENOTSUP The function is not supported on your platform.。

如果對 ioctl () 的調用失敗, 將返回 ioctl 的錯誤代碼。

在 RTU環境下 中獲取當前RTS模式 int modbus_rtu_get_rts(modbus_t *ctx)(3.1.4版本補充)

int modbus_rtu_get_rts (modbus_t *ctx);

可以獲得在當前ctx環境下發送請求的的模式。

返回值:

       MODBUS_RTU_RTS_NONE

       MODBUS_RTU_RTS_UP

       MODBUS_RTU_RTS_DOWN

       -1,即調用失敗,並設置EINVAL爲The libmodbus backend is not RTU.

 

在RTU環境下獲取設置RTS模式 int modbus_rtu_set_rts(modbus_t *ctx, int mode)(3.1.4版本補充)

int modbus_rtu_set_rts(modbus_t *ctx, int mode);

//例子:啓動有正極性的RTS模式
modbus_t *ctx;
uint16_t tab_reg[10];

ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

rc = modbus_read_registers(ctx, 0, 7, tab_reg);
if (rc == -1) {
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}

modbus_close(ctx);
modbus_free(ctx);

設置發送請求模式用於在RS485串行總線上進行通訊,默認模式爲MODBUS_RTU_RTS_NONE,在把數據寫入線路之前不會有信號發出。

要啓用RTS 模式, 必須使用 MODBUS_RTU_RTS_UP或MODBUS_RTU_RTS_DOWN, 這些模式啓用 RTS 模式並同時設置極性。使用MODBUS_RTU_RTS_UP時, 將RTS 標誌位置爲使能並進行 ioctl 調用, 然後在1毫秒的延遲後在總線上寫入數據, 然後將 RTS 標誌位置爲非使能進行另一個 ioctl 調用, 並再次延遲1毫秒。MODBUS_RTU_RTS_DOWN模式與之類似, 但使用相反的 RTS 標誌位。

如果成功, 函數應返回0。否則, 它將返回-1 並將 errno 設置爲The libmodbus backend isn’t RTU or the mode given in argument is invalid.。

 

自定義RTS實現 int modbus_rtu_set_custom_rts(modbus_t *ctx, void (set_rts) (modbus_t ctx, int on))(3.1.4版本補充)

int modbus_rtu_set_custom_rts(modbus_t *ctx, void (set_rts) (modbus_t ctx, int on));

設置傳輸前後設置RST PIN要調用的自定義函數,默認情況下,默認情況下,設置爲使用IOCTL調用切換RTS PIN的內部函數。

注意,該函數遵循RTS模式,必須使用值MODBUS_RTU_RTS_UPMODBUS_RTU_RTS_DOWN來調用該函數。

返回:如果成功, modbus_rtu_set_custom_rts ()函數應返回0。否則, 它將返回-1 並將 errno 設置爲The libmodbus backend is not RTU.

 

獲取RTU中當前RTS延遲 int modbus_rtu_get_rts_delay(modbus_t *ctx);(3.1.4版本補充)

int modbus_rtu_get_rts_delay(modbus_t *ctx);

返回:成功則以微秒爲單位返回當前RTS延遲。否則它將返回-1並設置errno爲The libmodbus backend is not RTU.。

 

設置RTU中的RTS延遲   int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);(3.1.4版本補充)

int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);

設置請求發送延遲。

返回:成功,返回0。否則它將返回-1並設置errno:The libmodbus backend is not RTU or a negative delay was specified.


TCP(IPv4)環境

TCP後端實現了用於通過TCP / IPv4網絡進行通信的Modbus變體。它不需要校驗和計算,因爲底層TCP會處理相同的功能。

創建Modbus TCP環境 modbus_t *modbus_new_tcp(const char *ip, int port);

modbus_t *modbus_new_tcp(const char *ip, int port);
//例子:
modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 1502);
if (ctx == NULL) {
    fprintf(stderr, "Unable to allocate libmodbus context\n");
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

ip:希望連接的服務器ip地址

port:要使用的 TCP 端口。將端口設置爲MODBUS_TCP_DEFAULT_PORT使用默認值之一 (502)。使用大於或等於1024的端口號很方便, 因爲沒有必要擁有管理員權限。

返回:成功返回指向modbus_t結構體的指針。否則, 它應返回 NULL 並將 errno 設置爲An invalid IP address was given.


TCP PI(IPv4和IPv6)環境

TCP PI(Protocol Indepedent)後端實現用於通過TCP IPv4和IPv6網絡進行通信的Modbus變體。 它不需要校驗和計算,因爲較低層負責相同的操作。 與單獨的TCP IPv4後端不同,TCP PI後端提供主機名解析,但它消耗大約1Kb的額外內存。

創建Modbus TCP PI環境modbus_t *modbus_new_tcp_pi(const char *node, const char *service);

modbus_t *modbus_new_tcp_pi(const char *node, const char *service);
//例子
modbus_t *ctx;

ctx = modbus_new_tcp_pi("::1", "1502");
if (ctx == NULL) {
    fprintf(stderr, "Unable to allocate libmodbus context\n");
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

應分配和初始化一個 modbus_t 結構, 以便與一個 IPv4 或 Ipv6 服務器進行通信。

node參數指定要連接的主機的主機名或 IP 地址, 例如。192.168.0.5 ,:: 1server.com.

service參數是要連接到的服務名稱/端口號。要使用默認的接口端口, 請使用字符串 "502"。在許多 Unix 系統上, 使用大於或等於1024的端口號是很方便的, 因爲沒有必要擁有管理員權限。

返回值:成功返回指向modbus_t結構的指針。否則, 它應返回 NULL 並將 errno 設置爲The node string is empty or has been truncated. The service string is empty or has been truncated。

 


通用函數:

在使用任何libmodbus函數之前,調用者必須使用上述功能分配和初始化 modbus_t環境,然後提供以下函數來修改和釋放環境:

釋放modbus環境void modbus_free(modbus_t *ctx);

void modbus_free(modbus_t *ctx);


設置從站ID int modbus_set_slave(modbus_t *ctx, int slave);(3.1.4版本補充)

int modbus_set_slave(modbus_t *ctx, int slave);
//例子
modbus_t *ctx;

ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}

rc = modbus_set_slave(ctx, YOUR_DEVICE_ID);
if (rc == -1) {
    fprintf(stderr, "Invalid slave ID\n");
    modbus_free(ctx);
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

設定libmodbus環境中的slave ID。

若爲RTU模式

定義遠程設備的從站ID以在主站模式下進行通信,或將內部從站ID設置爲從站模式。 根據協議,Modbus設備只接受包含了其從機號碼(slave number)或特殊廣播號碼的消息。

若爲TCP模式

如果消息必須到達串行網絡上的設備,則僅在TCP中需要從站號碼。 某些不兼容的設備或軟件(例如modpoll)使用從站ID作爲單元標識符,這是不正確的(參見Modbus Messaging Implementation Guide v1.0b的第23頁)沒有從站值,故障的遠程設備或軟件會丟棄請求! 特殊值MODBUS_TCP_SLAVE(0xFF)可用於TCP模式以恢復默認值。

廣播地址是 MODBUS_BROADCAST_ADDRESS 。 當您希望網絡中的所有Modbus設備都收到請求時,必須使用此特殊值。

返回:成功則返回0,否者返回-1並將errno設定爲The slave number is invalid.。

 

啓用調試模式 int modbus_set_debug(modbus_t *ctx, int flag);(3.1.4版本補充)

int modbus_set_debug(modbus_t *ctx, int flag);

通過是用flag設置debug調試標誌位,默認情況下,布爾標誌位flag被設置爲FALSE,當falg被設置爲TRUE時,會在stdout和stderr上顯示很多冗長的信息,可以用於顯示modbus消息的字節:

[00][14][00][00][00][06][12][03][00][6B][00][03]
Waiting for a confirmation…
<00><14><00><00><00><09><12><03><06><02><2B><00><00><00><00>

返回:成功返回0,否則返回-1.

 

超時設置: 

獲取字節之間的超時 int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);

int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
//例子:
uint32_t to_sec;
uint32_t to_usec;

/* Save original timeout */
modbus_get_byte_timeout(ctx, &to_sec, &to_usec);

實現在to_secto_usec參數中存儲同一消息的兩個連續字節之間的超時間隔。

返回:成功返回0,否則返回-1

 

設置字節之間超時間隔 void modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);

void modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);

設置同一消息的兩個連續字節之間的超時間隔。超時是在select()函數返回之前所經過的時間量的上限, 如果時間超過定義的超時, 則等待響應的函數將引發ETIMEDOUT錯誤。to_usec參數的值必須在範圍0到999999之間。

如果to_secto_usec都爲零, 則不會使用此超時。在這種情況下, modbus_set_response_timeout ()控制響應的整個處理, 必須在響應超時過期之前接收完整的確認響應。只設置字節超時爲1時, 響應超時僅用於等待響應的第一個字節。

返回:成功0,失敗返回-1並設置errno爲:The argument ctx is NULL or to_usec is larger than 1000000.

 

獲取響應超時時間void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout);

void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout);
//例子
struct timeval old_response_timeout;
struct timeval response_timeout;
 
/* Save original timeout保存原始的超時參數 */
modbus_get_response_timeout(ctx, &old_response_timeout);
 
/* Define a new and too short timeout!定義一個新的更短的超時參數 */
response_timeout.tv_sec = 0;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);

modbus_get_response_timeout 函數會保存用於等待超時參數中的響應的超時間隔。

 

設置超時響應時間 void modbus_set_response_timeout(modbus_t *ctx, struct timeval *timeout);

void modbus_set_response_timeout(modbus_t *ctx, struct timeval *timeout);
//例子
struct timeval old_response_timeout;
struct timeval response_timeout;
 
/* Save original timeout */
modbus_get_response_timeout(ctx, &old_response_timeout);
 
/* Define a new and too short timeout! */
response_timeout.tv_sec = 0;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);

modbus_set_response_timeout 函數應設置用於等待響應的超時間隔。如果在接收響應之前等待的時間超過給定的超時時間,則會引發錯誤。

 

設置錯誤恢復模式 int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);(3.1.4版本補充)

int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);
//例子
modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |
                          MODBUS_ERROR_RECOVERY_PROTOCOL);

用於設置連接失敗或者不期望接收到的字節時應用的錯誤恢復模式,參數  error_recovery 可以是按位(bitewise)或者其他檢誤方式(ed)使用0或者以下的常量。

默認情況下沒有錯誤恢復 (MODBUS_ERROR_RECOVERY_NONE), 因此應用程序負責控制 libmodbus 函數返回的錯誤值, 並在必要時處理它們。

設置(MODBUS_ERROR_RECOVERY_LINK)時, 庫將嘗試在 libmodbus 上下文的響應超時定義的延遲之後重新連接。此模式將嘗試無限關閉/連接的循環, 直到成功發送呼叫, 並只嘗試一次重新建立連接上的選擇/讀呼叫 (如果連接已關閉, 讀取的值肯定是不可用的, 在重聯後, 除了爲從機/主機)。此模式還將在某些情況下基於當前響應超時 (例如, 選擇調用超時) 後的延遲運行刷新請求。如果網絡到遠程目標單元已關閉, 重新連接嘗試可能會掛起幾秒鐘。

設置(MODBUS_ERROR_RECOVERY_PROTOCOL)時, 將使用睡眠和沖洗序列來清理正在進行的通信, 這可能發生在消息長度無效時, TID錯誤或接收的函數代碼不是預期的。響應超時延遲將用於睡眠。

模式是掩碼值, 因此它們是互補的。

建議不要爲從機/主機啓用錯誤恢復。

返回值:成功返回0,否則返回-1並吧errno設爲:The value of the argument error_recovery is not positive.

 

設置環境套接字(socket )int modbus_set_socket(modbus_t *ctx, int s);

int modbus_set_socket(modbus_t *ctx, int s);
//例子
ctx = modbus_new_tcp("127.0.0.1", 1502);
server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);

FD_ZERO(&rdset);
FD_SET(server_socket, &rdset);

/* .... */

if (FD_ISSET(master_socket, &rdset)) {
    modbus_set_socket(ctx, master_socket);
    rc = modbus_receive(ctx, query);
    if (rc != -1) {
        modbus_reply(ctx, query, rc, mb_mapping);
    }
}

在libmobus中設置環境套接字火文件描述符,對於管理到同一個主機的多個從機連接非常有效。

返回:成功返回0,否則返回-1並設置errno。

 

獲取環境套接字(socket) int modbus_get_socket(modbus_t *ctx);

int modbus_get_socket(modbus_t *ctx);

返回:成功則返回當前環境的套接字(socket)或文件描述符,否則返回-1並設置errno。

 

檢索當前標頭長度 int modbus_get_header_length(modbus_t *ctx);

int modbus_get_header_length(modbus_t *ctx);

從後端檢索當前報頭長度。此函數便於操作消息, 因此它僅限於低級操作。

返回:整形標頭長度值。


libmodbus的環境是線程安全的,可以在必要時共享儘可能多的應用程序線程, 而調用方不需要任何額外的鎖定。

用於數據操作的宏

MODBUS_GET_HIGH_BYTE(data) 獲取高位字節

MODBUS_GET_LOW_BYTE(data) 獲取低位字節

MODBUS_GET_INT32_FROM_INT16(tab_int16, index) 從兩個int16數據建立一個int32數據,從tab_int16[index]開始。

MODBUS_GET_INT16_FROM_INT8(tab_int8, index)從兩個int8數據建立一個int16數據,從tab_int8[index]開始。

MODBUS_SET_INT16_TO_INT8(tab_int8, index, value)將一個int16數據設置爲從tab_int8[index]開始的兩個int8數據。

MODBUS_SET_INT32_TO_INT16(tab_int16, index, value)將一個int32數據設置爲從tab_int16[index]開始的兩個int16數據。

MODBUS_SET_INT64_TO_INT16(tab_int16, index, value)將一個int64數據設置爲從tab_int16[index]開始的四個int16數據。

 

用於操作位和字節的函數(3.1.4版本修改)

從單個字節值設置多個位void modbus_set_bits_from_byte(uint8_t *dest, int index, const uint8_t value);

void modbus_set_bits_from_byte(uint8_t *dest, int index, const uint8_t value);

從單個字設置多個位,value字節中所有8位都會被寫到dest數組中從index索引開始的位置。

 

從字節數組設置多個位void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte);

void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte);

通過讀取字節數組來設置位,從tab_byte數組第一個開始的所有字節都會被寫到dest數組中從index索引開始的位置。

從多個位獲取數值uint8_t modbus_get_byte_from_bits(const uint8_t *src, int index, unsigned int nb_bits);

uint8_t modbus_get_byte_from_bits(const uint8_t *src, int index, unsigned int nb_bits);

從多個位提取一個值,從srcindex位置開始的的nb_bits位都會被讀取爲一個單獨的值,爲了獲取一個完整的字節,把nb_bits設置爲8。

返回:返回一個讀取後的字節。

 

設置或獲取浮點數

ABCD順序獲取浮點值float modbus_get_float_abcd(const uint16_t *src);

float modbus_get_float_abcd(const uint16_t *src);

從4個字節獲取浮點值。src數組必須是兩個16位數值的指針。例如第一個值爲0x0020,第二個值爲0xF147,則浮點值被讀爲123456.0。

返回:浮點值。

ABCD順序存儲浮點值void modbus_set_float_abcd(float f, uint16_t *dest);

void modbus_set_float_abcd(float f, uint16_t *dest);

f浮點數存儲到dest數組所指的兩個16位值得指針。

 

BADC順序獲取浮點值float modbus_get_float_badc(const uint16_t *src);

float modbus_get_float_badc(const uint16_t *src);

從4個字節獲取浮點值。src數組必須是兩個16位數值的指針。例如第一個值爲0x2000,第二個值爲0x47F1,則浮點值被讀爲123456.0。

返回:浮點值。

BADC順序存儲浮點值void modbus_set_float_badc(float f, uint16_t *dest);

void modbus_set_float_badc(float f, uint16_t *dest);

f浮點數存儲到dest數組所指的兩個16位值得指針。

CDAB順序獲取浮點值float modbus_get_float_cdab(const uint16_t *src);

float modbus_get_float_cdab(const uint16_t *src);

從4個字節獲取浮點值。src數組必須是兩個16位數值的指針。例如第一個值爲0x0020,第二個值爲0xF147,則浮點值被讀爲123456.0。

返回:浮點值。

CDAB順序存儲浮點值void modbus_set_float_cdab(float f, uint16_t *dest);

void modbus_set_float_cdab(float f, uint16_t *dest);

f浮點數存儲到dest數組所指的兩個16位值得指針

DCBA順序獲取浮點值float modbus_get_float_dcba(const uint16_t *src);

float modbus_get_float_dcba(const uint16_t *src);

從4個字節獲取浮點值。src數組必須是兩個16位數值的指針。例如第一個值爲0x47F1,第二個值爲0x2000,則浮點值被讀爲123456.0。

返回:浮點值。

DCBA順序存儲浮點值void modbus_set_float_dcba(float f, uint16_t *dest);

void modbus_set_float_dcba(float f, uint16_t *dest);

f浮點數存儲到dest數組所指的兩個16位值得指針


連接

建立連接 int modbus_connect(modbus_t *ctx);

int modbus_connect(modbus_t *ctx);
//例子
modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

使用參數給定的環境信息,建立與主機、網絡或總線的連接。

返回:成功返回0,錯誤返回-1並將errno設置爲底層平臺的系統呼叫。

關閉連接 void modbus_close(modbus_t *ctx);

void modbus_close(modbus_t *ctx);
//例子
modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_close(ctx);
modbus_free(ctx);

關閉與下級建立的連接。

返回值:無

沖洗未連接數據int modbus_flush(modbus_t *ctx);

int modbus_flush(modbus_t *ctx);

用於丟棄已接收到的單未讀取到與ctx環境相匹配的套接字(socket)或文件描述符。

返回:成功返回0或刷新字節數,否則返回-1並設置errno。


主機(客戶端Client)

讀取數據

讀取位(讀取線圈狀態) int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

用於讀遠程設備的 addr 地址開始的共nb 位(線圈)的狀態,讀取的結果以無符號的字節 (8 位) 設置爲TRUE或FALSE存儲在目的數組dest中。

您必須注意分配足夠的內存以將結果存儲在dest位置,至少是nb* sizeof (uint8_t) 的內存大小。

 該函數使用0x01功能碼(讀取線圈狀態)。

返回:成功返回讀取位的數目即nb,失敗返回-1並設置errno爲Too many bits requested。

譯者注:即取得一組邏輯線圈的當前狀態(1/0)。

讀取輸入位(讀取輸入狀態) int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

用於讀遠程設備的 addr 地址開始的共nb 位(輸入)的狀態。讀取的結果以無符號的字節 (8 位) 設置爲TRUE或FALSE存儲在目的數組dest中。

您必須注意分配足夠的內存以將結果存儲在dest位置,至少是nb* sizeof (uint8_t) 的內存大小。

該函數使用0x02 功能碼(讀取輸入狀態)。

返回:成功返回讀取輸入位的數目即nb,失敗返回-1並設置errno爲Too many discrete inputs requested。

譯者注:即取得一組開關輸入的當前狀態(1/0)。

讀取保持寄存器 int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
//例子
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;

ctx = modbus_new_tcp("127.0.0.1", 1502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}

for (i=0; i < rc; i++) {
    printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}

modbus_close(ctx);
modbus_free(ctx);

 用於讀遠程設備的 addr 地址開始的共nb 位(保持寄存器)的狀態。讀取結果以uint (16 位) 的形式存儲在dest數組中。

您必須注意分配足夠的內存以將結果存儲在dest位置,至少是nb* sizeof (uint16_t) 的內存大小。

該函數使用0x03 功能碼 (讀取保持寄存器)。

返回:成功返回讀取輸入位的數目即nb,失敗返回-1並設置errno爲Too many registers requested。

 

讀取輸入寄存器int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

 用於讀遠程設備的 addr 地址開始的共nb 位(輸入寄存器)的狀態。讀取結果以uint (16 位) 的形式存儲在dest數組中。

您必須注意分配足夠的內存以將結果存儲在dest位置,至少是nb* sizeof (uint16_t) 的內存大小。

該函數使用0x04 函數代碼 (讀取輸入寄存器)。保持寄存器和輸入寄存器具有曾經具有不同的意義, 但現在通常只使用保持寄存器。

返回:成功返回讀取輸入位的數目即nb,失敗返回-1並設置errno爲Too many bits requested。

 

讀取控制器(controller)描述  int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);

int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);
//例子
uint8_t tab_bytes[MODBUS_MAX_PDU_LENGTH];

...

rc = modbus_report_slave_id(ctx, MODBUS_MAX_PDU_LENGTH, tab_bytes);
if (rc > 1) {
    printf("Run Status Indicator: %s\n", tab_bytes[1] ? "ON" : "OFF");
}

用於向控制器發送請求以獲取控制器描述。

存儲在dest中的響應包括:

從機(slave)ID ,此ID實際上完全不是唯一的,所以不能靠它來知道信息在響應中如何打包。

運行指示器狀態(0x00 = OFF, 0xFF = ON)

特定於每個控制器的附加數據,例如: libmodbus 以字符串形式返回庫的版本號。

此函數返回最多max_dest字節數據)到dest,所以要確保dest空間足夠。

返回:成功讀取數據的數量,如果輸出因爲max_dest限制而被截斷,則返回值會返回若dest空間足夠情況下應該會寫入到dest的字節數,因此,大於max_dest的返回值意味着響應數據被截斷。失敗返回-1並設置errno。

寫數據

寫一位數據(強置單線圈)int modbus_write_bit(modbus_t *ctx, int addr, int status);

int modbus_write_bit(modbus_t *ctx, int addr, int status);

用於寫遠程設備addr地址處的狀態,值必須是TRUE或者FLASE。

該函數使用0x05功能碼(強置單線圈)。

返回:成功返回1,失敗返回-1並設置errno。

寫單寄存器(預置單寄存器)int modbus_write_register(modbus_t *ctx, int addr, int value);

int modbus_write_register(modbus_t *ctx, int addr, int value);

用於寫遠程設備addr地址處的數值,設置爲value。

該函數使用0x06功能碼(預置單寄存器)。

返回:成功返回1,失敗返回-1並設置errno。

寫多位數據(強置多線圈)int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);

int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);

nb位 (線圈) 的狀態從src中寫入遠程設備地址addr,src數組必須包含設置爲TRUEFALSE的字節.

該函數使用0x0F功能碼(強置多線圈)

返回:成功返回寫入位數nb,失敗返回-1並設置errno。

寫多寄存器(預置多寄存器)int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);

int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);

用於將src數組中的內容寫到遠程設備addr地址處的一組nb個寄存器

該函數使用0x16功能碼(預置多寄存器)。

返回:成功返回寫入寄存器個數nb,失敗返回-1並設置errno。

寫和讀數據

在單個處理中寫入和讀取多個寄存器int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb, const uint16_t *dest);

int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb, const uint16_t *dest);

src數組中的內容寫到遠程設備write_addr地址處的一組write_nb個寄存器,然後讀取read_addr處的一組read_nb個寄存器內容並保存到dest數組。

該函數使用0x17 函數代碼 (寫/讀寄存器)。

返回:如果成功, 該函數應返回讀取寄存器的數目。否則, 將返回-1 並設置 errno爲:Too many registers requested, Too many registers to write。

原始請求

發送原始請求 int modbus_send_raw_request (modbus_t *ctx, uint8_t *raw_req, int raw_req_length);

int modbus_send_raw_request (modbus_t *ctx, uint8_t *raw_req, int raw_req_length);
//例子
modbus_t *ctx;
/* Read 5 holding registers from address 1 */
uint8_t raw_req[] = { 0xFF, MODBUS_FC_READ_HOLDING_REGISTERS, 0x00, 0x01, 0x0, 0x05 };
int req_length;
uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];

ctx = modbus_new_tcp("127.0.0.1", 1502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

req_length = modbus_send_raw_request(ctx, raw_req, 6 * sizeof(uint8_t));
modbus_receive_confirmation(ctx, rsp);

modbus_close(ctx);
modbus_free(ctx);

通過在ctx環境下的套接口(socket)發送請求,此函數只用於調試,你必須小心的提出有效的請求,此函數只會添加到消息、所選後端的報頭或者CRC(the header or CRC of the selected backend),, 因此raw_req必須啓動幷包含至少一個從站/單元的ID和一個函數代碼。此函數可用於發送未由庫處理的請求。

libmodbus 的公共標頭提供了支持的MODBUS_FC_函數代碼的列表, 前綴爲MODBUS_FC_READ_HOLDING_REGISTERS, 以幫助建立原始請求。

返回:完整的消息長度,計算與後端有關的額外數據。否則,它將返回- 1並設置errno。

收到確認請求 int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);

int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);
//例子
uint8_t rsp[MODBUS_MAX_ADU_LENGTH];
rc = modbus_receive_confirmation(ctx, rsp);

通過在ctx環境下的套接口(socket)接受請求,此函數只用於調試,因爲不會根據初試請求檢查接受到的響應,此函數可用於接受未由庫處理的請求。

響應的最大大小取決於使用的後端, 在 RTU 中,rsp必須是MODBUS_RTU_MAX_ADU_LENGTH字節, 在 TCP 中必須是MODBUS_TCP_MAX_ADU_LENGTH字節。如果要編寫與兩者兼容的代碼, 可以使用常量MODBUS_MAX_ADU_LENGTH (所有 libmodbus 後臺的最大值)。注意分配足夠的內存以存儲響應以避免服務器崩潰。

返回:將確認請求存儲於rsp中,並在成功是返回響應長度,如果忽略指示請求,返回的請求長度可以是0(例如,在RTU模式下對另一個從機slave的查詢)。否則返回-1並設置errno。

回覆異常

發送一個異常響應*int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

*int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

基於參數中的exception_code發送異常響應。

libmodbus 提供了以下異常代碼:

MODBUS_EXCEPTION_ILLEGAL_FUNCTION (1)

MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS (2)

MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE (3)

MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE (4)

MODBUS_EXCEPTION_ACKNOWLEDGE (5)

MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY (6)

MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE (7)

MODBUS_EXCEPTION_MEMORY_PARITY (8)

MODBUS_EXCEPTION_NOT_DEFINED (9)

MODBUS_EXCEPTION_GATEWAY_PATH (10)

MODBUS_EXCEPTION_GATEWAY_TARGET (11)

建立有效的響應需要初始請求req

返回:成功則返回發送響應的長度,否則返回-1並設置errno爲The exception code is invalid。


從機(服務器server)

服務器(server)等待來自於客戶端(client)的請求,並且必須在收到請求的時候回答,libmodbus 提供以下功能來處理請求:

數據映射

分配位(線圈)和寄存器的數組modbus_mapping_t modbus_mapping_new (int nb_bits, int nb_input_bits, int nb_registers, intnb_input_registers);

modbus_mapping_t modbus_mapping_new (int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers);

//例子
/* The fist value of each array is accessible from the 0 address. */
mb_mapping = modbus_mapping_new(BITS_ADDRESS + BITS_NB,
                                INPUT_BITS_ADDRESS + INPUT_BITS_NB,
                                REGISTERS_ADDRESS + REGISTERS_NB,
                                INPUT_REGISTERS_ADDRESS + INPUT_REGISTERS_NB);
if (mb_mapping == NULL) {
    fprintf(stderr, "Failed to allocate the mapping: %s\n",
            modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

分配四數組來存儲位(譯者:線圈)、輸入位、(保持)寄存器和輸入寄存器。指針存儲在 modbus_mapping_t 結構中。數組的所有值都初始化爲零。

如果沒有必要爲特定類型的數據分配數組, 則可以在參數中傳遞零值, 關聯的指針將賦值爲 NULL。

此函數便於處理在服務器/從機中的請求。(譯者注:在modbus中,server(服務器)和slave(從站)含義相同,client(客戶端)和master(主站)含義相同)。

返回:成功,則返回新分配的結構,否則返回NULL並設置errno爲Not enough memory。

釋放modbus_mapping_t 結構void modbus_mapping_free(modbus_mapping_t *mb_mapping);

void modbus_mapping_free(modbus_mapping_t *mb_mapping);

釋放 mb_mapping_t 結構的4個數組, 最後由mb_mapping引用的 mb_mapping_t。

接收

收到指示請求 int modbus_receive(modbus_t *ctx, uint8_t *req);

int modbus_receive(modbus_t *ctx, uint8_t *req);

從ctx環境socket接收指示請求,該函數由服務器接收並分析主機/客戶端發送的指示請求。

如果需要使用其他套接字或文件描述符, 而不是在ctx環境中定義的, 請參閱函數modbus_set_socket (3).

返回:將指示請求存儲到req中,並返回請求長度。否則返回-1並設置errno。

回覆

響應收到的請求int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);

int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);

對收到的請求進行響應,分析給定的req請求,然後使用ctx環境信息建立一個響應併發送。

如果請求指示讀取或寫入一個值,則操作會根據操作的數據類型在mb_mapping映射中執行。

如果發生錯誤, 將發送異常響應。

此功能是爲 "服務器(從機)" 設計的。

返回:成功則返回響應的長度。否則返回-1並設置errno爲Sending has failed,另外請參閱the errors returned by the syscall used to send the response (eg. send or write).

發送異常響應int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);

基於參數中的exception_code發送異常響應。

libmodbus 提供了以下異常代碼:

MODBUS_EXCEPTION_ILLEGAL_FUNCTION (1)

MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS (2)

MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE (3)

MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE (4)

MODBUS_EXCEPTION_ACKNOWLEDGE (5)

MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY (6)

MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE (7)

MODBUS_EXCEPTION_MEMORY_PARITY (8)

MODBUS_EXCEPTION_NOT_DEFINED (9)

MODBUS_EXCEPTION_GATEWAY_PATH (10)

MODBUS_EXCEPTION_GATEWAY_TARGET (11)

建立有效的響應需要初始請求要求。

返回:成功則返回發送的響應的長度,否則返回-1並設置errno爲The exception code is invalid。

錯誤處理

libmodbus功能使用POSIX系統上的標準約定處理錯誤。一般來說,這意味着一旦發生故障,libmodbus函數將返回一個NULL值(如果返回一個指針)或一個負值(如果返回一個整數),並且實際的錯誤代碼將被存儲在errno變量中。

提供modbus_strerror()函數將libmodbus特定的錯誤代碼轉換爲錯誤消息字符串;

返回錯誤信息const char *modbus_strerror(int errnum);

const char *modbus_strerror(int errnum);
//例子
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    abort();
}

會返回一個指向與errnum參數指定的錯誤號對應的錯誤消息字符串的指針。由於 libmodbus 定義了超出操作系統定義的其他錯誤號, 因此應用程序應該使用modbus_strerror ()來優先於標準strerror ()函數發送錯誤消息。

返回:返回一個指向錯誤消息字符串的指針。


雜項

該LIBMODBUS_VERSION_STRING表示libmodbus版本的程序已編譯對應版本。變量libmodbus_version_major, libmodbus_version_minor,libmodbus_version_micro給出程序鏈接的版本。

作者

libmodbus 文檔作者

Stéphane Raimbault<[email protected]>

資源

主頁:http://www.libmodbus.org/

提交問題http://github.com/stephane/libmodbus/issues.

版權協議

根據GNU通用公共許可證(LGPLv2.1 +)的條款,免​​費使用此軟件。有關詳細信息,請參閱COPYING.LESSERlibmodbus發行版隨附的文件。


如有翻譯錯誤,歡迎私信、評論指正,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章