利用Modbus库编程实现采集传感器数据和控制硬件设备

该程序通过ModbusTCP协议连接到模拟的从机,读取光线和加速度传感器数据,并以1秒间隔打印。同时,程序接收用户输入控制LED灯和蜂鸣器的状态。主程序采用多线程,一个线程负责数据采集,另一个线程处理用户指令。
摘要由CSDN通过智能技术生成

任务:

编程实现采集传感器数据和控制硬件设备(传感器和硬件通过slave模拟)

1.传感器:2个,光线传感器、加速度传感器(x\y\z)

2. 硬件设备:2个,led灯、蜂鸣器

要求:

1. 多任务编程:多线程、多进程
2.循环1s采集一次数据,并将数据打印至终端
3.同时从终端输入指令控制硬件设备
//             0 1 :led灯打开

//             0 0:led灯关闭

//            1 1:蜂鸣器开

//            1 0 : 蜂鸣器关

编程流程:

1. 创建实例

modbus_new_tcp

2. 设置从机ID

modbus_set_slave

3. 和从机进行连接

modbus_connect

4. 寄存器进行操作

功能码对应函数

5. 关闭套接字

modbus_close

6. 释放实例

modbus_free


函数接口(很重要!)

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

运行代码 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <modbus.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>


int sockfd;
uint16_t dest[64] = {};

int main()
{

    modbus_t *ctx;
    ctx = modbus_new_tcp("192.168.XX.XX", 502);
    if (ctx == NULL)
    {
        perror("error\n");
        return -1;
    }
    int a = modbus_set_slave(ctx, 1);
    int b = modbus_connect(ctx);

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork err");
        return -1;
    }
    else if (pid == 0)
    {
        while (1)
        {
            modbus_read_registers(ctx, 0, 4, dest);
            for (int i = 0; i < 4; i++)
            {
                if (i == 0)
                {
                    printf("光传感器:");
                    printf("%#x\n", dest[i]);
                }
                else if (i == 1)
                {
                    printf("加速度传感器x:%#x\n", dest[i]);
                }
                else if (i == 2)
                {
                    printf("加速度传感器y:%#x\n", dest[i]);
                }
                else if (i == 3)
                {
                    printf("加速度传感器z:%#x\n", dest[i]);
                }
                putchar(10);
                
            }
            sleep(5);
        }
        exit(0);
    }
    else
    {
        int a, b;
        while (1)
        {
            scanf("%d", &a);
            scanf("%d", &b);

            if (a == 0 && b == 1)
            {
                printf("led灯打开\n");
            }
            else if (a == 0 && b == 0)
            {
                printf("led灯关闭\n");
            }
            else if (a == 1 && b == 1)
            {
                printf("蜂鸣器开\n");
            }
            else if (a == 1 && b == 0)
            {
                printf("蜂鸣器关\n");
            }
            modbus_write_bit(ctx, a, b);
        }
        
        wait(NULL);
        // exit(0);
    }
    modbus_close(ctx);
    modbus_free(ctx);
    return 0;
}

 运行结果:

 

注意:在slave内设置上线圈与寄存器,连接上主机ip地址,同时在虚拟机内编译通过后执行时也连接主机ip地址就可以循环获取设备的数值和通过终端输入来设置线圈状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值