zoukankan      html  css  js  c++  java
  • 玩转Libmodbus(二) 写代码体验

    libmodbus在线文档

     https://www.jianshu.com/p/d93c17485c0a

    原创篇

    参考上一篇转载的博客,我的ubuntu上的最终生成的动态库的路径,下图所示

    我的linux板子上( 权限最好 777):

    我的ubuntu主机上的C语言源代码的路径,四个头文件modbus.h、modbus-rtu.h、modbus-tcp.h、modbus-version.h也都放在了这里

     我的C源代码:

    /*************************
    **
    ** modbus-rtu-test.c 
    ** 移植libmodbus库到ARM开发板,并测试成功
    **
    **************************/
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include "modbus.h"  //modbus动态库文件
     
    unsigned char log[6] = {0x11,0x12,0x13,0x14,0x15,0x16}; 
    #define Path_dat "/root/Test_Data_Dir/record.dat"
     
    #define Path_log1 "/root/Test_Data_Dir/log1.dat"
    #define Path_log2 "/root/Test_Data_Dir/log2.dat"
    #define Path_log3 "/root/Test_Data_Dir/log3.dat"
    #define Path_log4 "/root/Test_Data_Dir/log4.dat"
    
    /*
    int read_data_hex(unsigned char *buf, int length, char *string)
    {
        FILE *fp;
        fp = fopen(string, "rb");
        if (NULL == fp)
        {
            // printf("read: file open Fail!
    ");
            return -1;
        }
        fread(buf, sizeof(unsigned char), length, fp);
    
        fclose(fp);
        fp = NULL;
        return 0;
    } 
    */
     
    int write_data_hex(unsigned char *my_array, int length, char *string)
    {
        int i = 0;
        FILE *fp;
        fp = fopen(string, "wb+"); // b 二进制操作
        if (NULL == fp)
        {
            // printf("write: file open Fail!
    ");
            return -1;
        }
        while (i < length)
        {
            fwrite(&my_array[i], sizeof(unsigned char), 1, fp);
            i++;
        }
    
        fclose(fp);
        fp = NULL;
        return 0;
    } 
     
     
    //如果手边只有一根USB转串口线,那么只能连接板子的modbus串口和PC机,就不能
    //连接PC机和板子的串口调试口了。如何调试?使用write_data_hex()写log观察过程。
    
    int main(int argc, char *argv[])
    {
        struct timeval t;
        uint16_t tab_reg[64] = {0}; //定义存放数据的数组
        modbus_t *ctx = NULL;
     
        int rc;
        int i;
                    //以串口的方式创建libmodbus实例,并设置参数
                    //ttySAC0         /dev/ttyS1            
        ctx = modbus_new_rtu("/dev/ttySAC0", 115200, 'N', 8, 1);                    
        if (ctx == NULL)               
        {
            fprintf(stderr, "Unable to allocate libmodbus contex
    ");
            return -1;
        }
        
        printf("MY_Debug: usleep begin! 
    ");
        
        //这里我给了40秒延时,在这个时间内:你把串口线从板子的串口调试口转为
        //连接到板子的modbus串口,打开一个事先设置好串口参数的PC机上的模拟modbus从机的软件
        //(我使用的是和modsim32)
        //注意:如果前后接的是同一个电脑com口,注意还要把之前的串口调试口对应的上位机软件
        //      关闭一下,以便modsim32能够顺利打开该com口。
        usleep(40000000); 
        
        modbus_set_debug(ctx, 0);      //设置1可看到调试信息
        modbus_set_slave(ctx, 1);      //设置slave ID
        
        t.tv_sec = 0;
        t.tv_usec = 50000;
        // 50ms超时时间,下位机回复帧的限制时间:主机发完后,下位机需要在50ms内回应
        //   *** 必须设置从站的响应超时 小于 主站的响应超时 *** 
        //   总之,在确保速度满足你所需应用的情况下,把主站的响应超时适当设置大一点,是保险措施
        modbus_set_response_timeout(ctx,&t); 
        
    
        if (modbus_connect(ctx) == -1) //连接设备
         {
            write_data_hex(&log[0], 1, Path_log1);
            printf("MY_Debug: modbus_connect Fail! 
    ");
            fprintf(stderr, "Connection failed:%s
    ", modbus_strerror(errno));
            
            modbus_close(ctx);  //关闭modbus连接
            modbus_free(ctx);   //释放modbus资源,libmodbus需要释放掉
         }
        else{
            printf("MY_Debug: modbus_connect Success! 
    ");
        }
        
        
        while (1)
        {
            printf("
     这里的代码只执行一次 return -1,或者 break 
    ");
            
            rc = modbus_read_registers(ctx, 0, 10, tab_reg);
            if (rc == -1)    //读取保持寄存器的值,可读取多个连续输入保持寄存器
            {
                write_data_hex(&log[1], 1, Path_log2);
                fprintf(stderr,"%s
    ", modbus_strerror(errno));
                printf("MY_Debug: modbus_read_registers Fail! 
    ");
                return -1;
            }
            
            // 这里保存为文件,如果你只有一根串口线,方便你观察结果。
            write_data_hex(&log[2], 1, Path_log3);
            
            write_data_hex(tab_reg, 10, Path_dat);
            
            for (i=0; i<10; i++)
            {
                printf("reg[%d] = %d(0x%x)
    ", i, tab_reg[i], tab_reg[i]);
            }
            
            break;
        }
        
        write_data_hex(&log[3], 1, Path_log4);    //标记代码已顺利结束
        modbus_close(ctx);  //关闭modbus连接
        modbus_free(ctx);   //释放modbus资源,使用完libmodbus需要释放掉
     
        return 0;
    }

    我的makefile:

    CC = arm-none-linux-gnueabi-gcc
    
    #CFLAGS    += -I../include -std=gnu99 -lm -lpthread -O3 -lstdc++
    
    LIBS    += -L /home/aston/LibModbus_Study/installHere/lib -lmodbus
    
    TARGET=main.out
    
    SRCS =     Lib_Modbus_test.c 
    
    OBJS = $(SRCS:.c=.o)
    
    $(TARGET):$(OBJS)
        $(CC) $(LDFLAGS) $^ -o $@ $(LIBS)    
    
    clean:
        rm -rf $(TARGET) $(OBJS)
    
    
        
        

    我使用到的工具软件: ModSim32 

    D:Study_2019LibModbus使用到的工具软件ModSim32 v1.A00-04

    软件使用介绍:

    先点击New, 就可以出现‘’2’的界面,并配置好参数,以便后面使用

    待linux板子上的程序跑起来以后,用USB转串口线连接好板子的MODBUS串口和PC机的USB口,再点击下图所示的‘3’的Connect

    代码中读取到的寄存器的值展示:

    实验成功。注意,modbus一个寄存器占两个字节。大小端有区分。

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    Supermap/Cesium 开发心得----获取三维视角的四至范围
    Supermap/Cesium 开发心得----定位
    GIS面试小知识点
    Oracle数据库小知识点整理
    利用 uDig 生成 GeoServer 可用的 SLD 渲染文件
    Geoserver设置style
    图片按宽高比1:1响应,窗口大小如何变化,图片宽高始终相等
    简单树
    递归渲染树
    div等高布局
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/11301863.html
Copyright © 2011-2022 走看看