一、libmodbus簡(jiǎn)介
libmodbus是一個(gè)快速且可移植的Modbus庫宰衙,支持傳統(tǒng)的RS-232、RS-422睹欲、RS-485和以太網(wǎng)設(shè)備供炼。
二、安裝libmodbus
- Linux窘疮、MacOS袋哼、FreeBSD、WIN32等可直接通過包管理器安裝
libmodbus
-
源碼編譯安裝:
libmodbus官網(wǎng)下載:https://libmodbus.org/releases/libmodbus-3.1.6.tar.gz
github下載:https://github.com/stephane/libmodbus.git
//進(jìn)入解壓目錄
cd libmodbus-3.1.6
//配置編譯選項(xiàng)(以ARM為例闸衫,--build為系統(tǒng)構(gòu)架 --host為編譯對(duì)應(yīng)系統(tǒng)工具鏈涛贯,--prefix為輸出目錄,選項(xiàng)均是可選的)
./configure --build=i686 --host=arm-linux --enable-static --prefix=[install path]/
//編譯安裝
make && make install
三蔚出、簡(jiǎn)單示例
- RTU master
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "modbus.h"
int main(void)
{
int i = 0;
int regs = 0;
modbus_t *ctx = NULL;
uint16_t tab_reg[64] = {0};
//打開端口: 端口弟翘,波特率虫腋,校驗(yàn)位,數(shù)據(jù)位稀余,停止位
ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
//設(shè)置從機(jī)地址
modbus_set_slave(ctx, 1);
//設(shè)置串口模式(可選)
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
//設(shè)置RTS(可選)
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;
}
//設(shè)置應(yīng)答延時(shí)(可選)
modbus_set_response_timeout(ctx, 0, 1000000);
while (1)
{
memset(tab_reg, 0, sizeof(tab_reg));
//讀寄存器設(shè)置:寄存器地址悦冀、數(shù)量、數(shù)據(jù)緩沖
regs = modbus_read_registers(ctx, 0, 20, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
continue;
}
printf("[%4d][read num = %d]", num++, regs);
for (i = 0; i < 20; ++i)
{
printf("<%#x>", tab_reg[i]);
}
printf("\n");
sleep(1);
}
}
- RTU-Master流程總結(jié):
- 初始化 modbus 指針
- 設(shè)置從站ID
- 建立連接
- 讀取保持寄存器/輸入寄存器/離散輸入/線圈輸入
- 寫單個(gè)寄存器/多個(gè)寄存器/多位數(shù)據(jù)
- 關(guān)閉連接
- RTU slave
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include "modbus.h"
int main(void)
{
int i = 0;
int rc = 0;
modbus_t *ctx = NULL;
modbus_mapping_t *mb_mapping = NULL;
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
//打開端口: 端口睛琳,波特率盒蟆,校驗(yàn)位,數(shù)據(jù)位师骗,停止位
ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
//設(shè)置從機(jī)地址
modbus_set_slave(ctx, 1);
//設(shè)置串口模式
//modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
//設(shè)置RTS
//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;
}
mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
MODBUS_MAX_READ_REGISTERS, 0);
if (mb_mapping == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
//初始化幾個(gè)寄存器
mb_mapping->tab_registers[0] = 1;
mb_mapping->tab_registers[1] = 2;
mb_mapping->tab_registers[2] = 3;
mb_mapping->tab_registers[3] = 4;
mb_mapping->tab_registers[4] = 5;
mb_mapping->tab_registers[5] = 6;
while (1)
{
memset(query, 0, sizeof(query));
rc = modbus_receive(ctx, query);
if (rc > 0) {
modbus_reply(ctx, query, rc, mb_mapping);
} else if (rc == -1) {
//Connection closed by the client or error
break;
}
}
printf("Quit the loop: %s\n", modbus_strerror(errno));
modbus_mapping_free(mb_mapping);
if (s != -1) {
close(s);
}
modbus_close(ctx);
modbus_free(ctx);
}
RTU-Slave流程總結(jié):
- 初始化 modbus 指針;
- 設(shè)置從站ID;
- modbus_mapping_new初始化寄存器历等,返回一個(gè)modbus_mapping_t 指針;
- 建立連接;
- 調(diào)用 modbus_receive 函數(shù)判斷串口的接收數(shù)據(jù),負(fù)責(zé)接收處理及回復(fù)丧凤。
- TCP master
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include <sys/socket.h>
#include "modbus.h"
void main(void)
{
int i;
int regs = 0;
int num = 0;
modbus_t *ctx = NULL;
uint16_t tab_reg[64] = {0};
ctx = modbus_new_tcp("127.0.0.1",8000);
modbus_set_slave(ctx, 1);
modbus_connect(ctx);
modbus_set_response_timeout(ctx, 0, 1000000);
while (1)
{
memset(tab_reg, 0, sizeof(tab_reg));
regs = modbus_read_registers(ctx, 0, 20, tab_reg);
printf("[%4d][read num = %d]", num++, regs);
for (i = 0; i < 20; i++)
{
printf("<%#x>", tab_reg[i]);
}
printf("\n");
sleep(1);
}
modbus_close(ctx);
modbus_free(ctx);
}
- TCP slave
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include <sys/socket.h>
#include "modbus.h"
int main(void)
{
int i = 0;
int rc = 0;
modbus_t *ctx = NULL;
modbus_mapping_t *mb_mapping = NULL;
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
//打開端口: ip, port
ctx = modbus_new_tcp("127.0.0.1", 8000);
//設(shè)置從機(jī)地址
modbus_set_slave(ctx, 1);
//建立連接
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
MODBUS_MAX_READ_REGISTERS, 0);
if (mb_mapping == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
//初始化幾個(gè)寄存器
mb_mapping->tab_registers[0] = 1;
mb_mapping->tab_registers[1] = 2;
mb_mapping->tab_registers[2] = 3;
mb_mapping->tab_registers[3] = 4;
mb_mapping->tab_registers[4] = 5;
mb_mapping->tab_registers[5] = 6;
while (1)
{
memset(query, 0, sizeof(query));
rc = modbus_receive(ctx, query);
if (rc > 0) {
modbus_reply(ctx, query, rc, mb_mapping);
} else if (rc == -1) {
//Connection closed by the client or error
break;
}
}
printf("Quit the loop: %s\n", modbus_strerror(errno));
modbus_mapping_free(mb_mapping);
if (s != -1) {
close(s);
}
modbus_close(ctx);
modbus_free(ctx);
}