Modbus库
【1】库的安装
库的安装配置
- 在linux中解压压缩包
将库压缩包复制到linux下,进行解压
tar -xvf libmodbus-3.1.7.tar.gz
- 进入源码目录,创建文件夹(存放头文件、库文件)
cd libmodbus-3.1.7
mkdir install
- 执行脚本configure,进行安装配置(指定安装目录)
./configure --prefix=$PWD/install
- 执行make和make install
make//编译
make install//安装
执行完成后会在install文件夹下生产对应的头文件、库文件件夹install,用于存放产生的头文件、库文件等
库的使用
要想编译方便,可以将头文件和库文件放到系统路径下
sudo cp install/include/modbus/*.h /usr/include
sudo cp install/lib/* -r /lib -d
后期编译时,可以直接
gcc xx.c -lmodbus
头文件默认搜索路径:
/usr/include 、/usr/local/include
库文件默认搜索路径:
/lib、/usr/lib
【2】函数接口
modbus_t* modbus_new_tcp(const char *ip, int port)
功能:以TCP方式创建Modbus实例,并初始化
参数:
ip :ip地址
port:端口号
返回值:成功:Modbus实例
失败:NULL
int modbus_set_slave(modbus_t *ctx, int slave)
功能:设置从机ID
参数:
ctx :Modbus实例
slave:从机ID
返回值:成功:0
失败:-1
int modbus_connect(modbus_t *ctx)
功能:和从机(slave)建立连接
参数:
ctx:Modbus实例
返回值:成功:0
失败:-1
void modbus_free(modbus_t *ctx)
功能:释放Modbus实例
参数:ctx:Modbus实例
void modbus_close(modbus_t *ctx)
功能:关闭套接字
参数:ctx:Modbus实例
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01)
参数:
ctx :Modbus实例
addr :寄存器起始地址
nb :寄存器个数
dest :得到的状态值
int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02)
参数:
ctx :Modbus实例
addr :寄存器起始地址
nb :寄存器个数
dest :得到的状态值
返回值:成功:返回nb的值
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03)
参数:
ctx :Modbus实例
addr :寄存器起始地址
nb :寄存器个数
dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
失败:-1
int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04)
参数:
ctx :Modbus实例
addr :寄存器起始地址
nb :寄存器个数
dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
失败:-1
int modbus_write_bit(modbus_t *ctx, int addr, int status);
功能:写入单个线圈的状态(对应功能码为0x05)
参数:
ctx :Modbus实例
addr :线圈地址
status:线圈状态
返回值:成功:0
失败:-1
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
功能:写入多个连续线圈的状态(对应功能码为15)
参数:
ctx :Modbus实例
addr :线圈地址
nb :线圈个数
src :多个线圈状态
返回值:成功:0
失败:-1
int modbus_write_register(modbus_t *ctx, int addr, int value);
功能: 写入单个寄存器(对应功能码为0x06)
参数:
ctx :Modbus实例
addr :寄存器地址
value :寄存器的值
返回值:成功:0
失败:-1
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
功能:写入多个连续寄存器(对应功能码为16)
参数:
ctx :Modbus实例
addr :寄存器地址
nb :寄存器的个数
src :多个寄存器的值
返回值:成功:0
失败:-1
追源码方法:
按住ctrl 单击要追的内容
退回方法:
alt + 键盘左键
【3】编程流程
1.创建实例
modbus_new_tcp
2.设置从机ID
modbus_set_slave
3.和从机连接
modbus_connect
4.寄存器操作
功能码对应函数
5.关闭套接字
modbus_close
6.释放实例
modbus_free
任务:编程实现采集传感器数据和控制硬件设备(传感器和硬件通过slave模拟) 传感器:2个,光线传感器、加速度传感器(x\y\z)
硬件设备:2个,led灯、蜂鸣器 要求:
1.多任务编程:多线程、多进程
2.循环1s采集一次数据,并将数据打印至终端
3.同时从终端输入指令控制硬件设备 0 1 :led灯打开 0 0:led灯关闭 1 1:蜂鸣器开 1 0 : 蜂鸣器关
#include <stdio.h>
#include<string.h>
#include <stdlib.h> // atoi
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include<modbus.h>
int main(int argc, char const *argv[])
{
int slave_id;
int mb_read;
int mb_write;
uint16_t dest[64]={0};
uint8_t src[12]={0};
uint8_t dest1[12]={0};
//创建实例并初始化
modbus_t *ctx=NULL;
ctx=modbus_new_tcp("192.168.50.13",502);
if(ctx == NULL){
fprintf(stderr,"modbus_new_tcp err\n");
return -1;
}
设置从机ID
slave_id=modbus_set_slave(ctx,1);
printf("从机id\n");
//和从机连接
if(modbus_connect(ctx) == -1){
fprintf(stderr,"Connection failed\n");
modbus_free(ctx);
return -1;
}
pid_t pid = fork();
if (pid < 0)
{
perror("fork err.");
return -1;
}
else if (pid == 0)//子进程--read保持寄存器
{
while (1)
{printf("开始读\n");
mb_read = modbus_read_registers(ctx, 0, 4, dest);
// if (mb_read < 0)
// {
// perror("modbus_read_registers err.");
// return -1;
// }
printf("成功读到 %d 个寄存器数据",mb_read);//成功,返回寄存器个数
for (int i = 0; i < 4; i++)
printf("%#x ", dest[i]);
printf("\n");
sleep(5);
}
}
else
{
//5.循环发送
while (1)
{
char buf[32]={};
fgets(buf, sizeof(buf), stdin);
printf("key:%s\n", buf);
modbus_read_bits(ctx,0,2,dest1);
printf("线圈置位前:\n");
printf("LED: %#x ;蜂鸣器:%#x \n",dest1[0],dest1[1]);
if(buf[0]=='0'){
if(buf[2]=='0'){
src[0] = 0x00;
//src[1] = dest[1];
}
if(buf[2]=='1'){
src[0] = 0xff;
//src[1] = dest[1];
}
mb_write=modbus_write_bits(ctx, 0, 2,src);
}
if(buf[0]=='1'){
if(buf[2]=='0'){
src[1] = 0x00;
}
if(buf[2]=='1'){
src[1] = 0xff;
}
mb_write=modbus_write_bits(ctx, 0, 2,src);
}
printf("线圈置位后:\n");
printf("LED: %#x ;蜂鸣器:%#x \n",src[0],src[1]);
sleep(1);
}
}
//5.关闭套接字
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
基于Modbus协议实现远程控制和数据检测