imx6ull交叉编译libmodbus
目录
- 版本和开发环境说明
- 操作步骤
- 源码的修改
- 开放串口发送任意数据的API
- 轮询modbus接收数据时不阻塞
- 项目代码示例
版本和开发环境说明
libmodbus的官网上面有源码与文档,建议从上面获取一手资料。
- libmodbus版本为 3.1.6
- 交叉编译host为 Ubuntu16.04
- 交叉编译target为 arm A7内核的imx6ull
- 交叉编译器为 arm-linux-gnueabihf-gcc
操作步骤
交叉编译libmodbus的流程相对简单:
#use alias setcc to config cross compile environment
setcc
cd ./libmodbus-3.1.6
./configure --host=arm-linux-gnueabihf --prefix=$(pwd)/install
make & make install
- 如果需要静态库,则./configure加上选项:
–enable-static - 如果需要动态库,则./configure加上选项:
–enable-shared
编译完成后,在install生成三个目录: include, lib, share,里面是我们需要用到的库文件与头文件。
lib文件夹下的libmodbus.so.5.1.0即为可以被调用的库文件,在实际编程的时候需要包含头文件:#include"modbus.h"
源码的修改
本章节是笔者在进行libmodbus开发时,根据项目需求对源码进行修改以获得新的功能特性。由于libmodbus已经对串口进行了较为完善的封装,我们无法利用这个库发送自定义格式的一些数据(某些设备或者从机在某些情况下并不是采用标准的modbus协议,需要我们自己自定义每一帧的数据)。因此,本章节的修改主要目的在于开放串口发送任意数据的API,已增加库的扩展性与通用性。同时,笔者需要在轮询modbus接收数据的时候不造成阻塞,开放了结构体 modbus_t的内部,以获得串口文件句柄,然后借助select机制将读取串口数据变为不阻塞的。
开放串口发送任意数据的API
进入到./libmodbus-3.1.6/src/中,修改modbus.c与modbus.h文件:
在modbus.c中定义函数:
int modbus_send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
{return ctx->backend->send(ctx, msg, msg_length);
}
在modbus.h中添加声明:
MODBUS_API int modbus_send_msg(modbus_t *ctx, uint8_t *msg, int msg_length);
即可在项目代码中调用modbus_send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)函数发送任意数据。
轮询modbus接收数据时不阻塞
在modbus-rtu.c中,函数:
static ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
{#if defined(_WIN32)return win32_ser_read(&((modbus_rtu_t *)ctx->backend_data)->w_ser, rsp, rsp_length);
#elsereturn read(ctx->s, rsp, rsp_length);
#endif
}
由于采用了read机制,会使得程序在轮询接收数据的时候(在modbus.c中),造成阻塞。
int modbus_receive(modbus_t *ctx, uint8_t *req)
{if (ctx == NULL){errno = EINVAL;return -1;}return ctx->backend->receive(ctx, req);
}
修改代码,开放***typedef struct _modbus modbus_t***的内部,以获得串口文件句柄,然后借助select机制将读取串口数据变为不阻塞的。具体操作如下:
将modbus-private.h中关于_modbus结构体的定义、_modbus_backend结构体、_sft结构体的定义直接复制到已经编译好的库“./install/include/modbus/modbus.h”中。不需要修改源码,亦不影响编译过程。
/* This structure reduces the number of params in functions and so* optimizes the speed of execution (~ 37%). */
typedef struct _sft {int slave;int function;int t_id;
} sft_t;typedef struct _modbus_backend {unsigned int backend_type;unsigned int header_length;unsigned int checksum_length;unsigned int max_adu_length;int (*set_slave) (modbus_t *ctx, int slave);int (*build_request_basis) (modbus_t *ctx, int function, int addr,int nb, uint8_t *req);int (*build_response_basis) (sft_t *sft, uint8_t *rsp);int (*prepare_response_tid) (const uint8_t *req, int *req_length);int (*send_msg_pre) (uint8_t *req, int req_length);ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);int (*receive) (modbus_t *ctx, uint8_t *req);ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length);int (*check_integrity) (modbus_t *ctx, uint8_t *msg,const int msg_length);int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req,const uint8_t *rsp, int rsp_length);int (*connect) (modbus_t *ctx);void (*close) (modbus_t *ctx);int (*flush) (modbus_t *ctx);int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);void (*free) (modbus_t *ctx);
} modbus_backend_t;struct _modbus {/* Slave address */int slave;/* Socket or file descriptor */int s;int debug;int error_recovery;struct timeval response_timeout;struct timeval byte_timeout;struct timeval indication_timeout;const modbus_backend_t *backend;void *backend_data;
};
modbus_t的成员s即串口文件句柄(Socket or file descriptor)
项目代码示例
在实际项目中(以C++/Qt4.8为例)可以通过以下方式轮询modbus,将接收数据变为不阻塞:
modbus_mapping_t *mb_mapping;
modbus_t *ctx;void ModbusThread::run()
{int rc;fd_set set;timeval timeout;timeout.tv_sec = 0;timeout.tv_usec = 1000;// int use_backend;//初始化modbus rtuctx = modbus_new_rtu(SLAVE_PORT, 9600, 'N', 8, 1);//设定从设备地址modbus_set_slave(ctx, SLAVE_ADDR);//modbus连接modbus_connect(ctx);//qDebug()<<"serial port fd is: "<<ctx->s;//寄存器map初始化mb_mapping = modbus_mapping_new(MODBUS_MAX_WRITE_BITS, MODBUS_MAX_READ_BITS , MODBUS_MAX_WR_WRITE_REGISTERS, MODBUS_MAX_READ_REGISTERS);if (mb_mapping == NULL){fprintf(stderr, "Failed to allocate the mapping: %s\n",modbus_strerror(errno));modbus_free(ctx);return;}if (isRemoteMonitoringUsed_dialog == true){qDebug()<<"isRemoteMonitoringUsed_dialog:"<<isRemoteMonitoringUsed_dialog;mainWidget->timer_uploadDataToCloud.start(10000);qDebug()<<"Remote Monitoring is used.";}else {qDebug()<<"isRemoteMonitoringUsed_dialog:"<<isRemoteMonitoringUsed_dialog;qDebug()<<"Remote Monitoring is not used.";}while(true){uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];SyncModbusRegisters();FD_ZERO(&set);FD_SET(ctx->s, &set); //此处将读取的串口fd加入队列select(ctx->s+1,&set,NULL,NULL,&timeout); //此次判断读取的队列if(!FD_ISSET(ctx->s, &set)){continue;}//轮询接收数据,并做相应处理QMutexLocker locker1(&modbusPortLock);rc = modbus_receive(ctx, query);locker1.unlock();if (rc > 0){//QString receivedData = "";//for(int i=0; i< rc ; i++)//{// receivedData.append(QString::number(query[i],16)).append(" ");//}//qDebug()<<receivedData;modbus_reply(ctx, query, rc, mb_mapping);ModbusSyncAction();}else if (rc == -1){//qDebug()<<"Modbus connection closed by the client or error.";//break;}else{}QMutexLocker locker(&m_lock);if(!isThreadLoop){qDebug()<<"isThreadLoop:"<<isThreadLoop;break;}}printf("Modbus thread is terminated: %s\n", modbus_strerror(errno));modbus_mapping_free(mb_mapping);/* For RTU, skipped by TCP (no TCP connect) */modbus_close(ctx);modbus_free(ctx);
}
imx6ull交叉编译libmodbus相关推荐
- 中国ai chip初创公司_这个AI事实检查初创公司正在做Facebook和Twitter不会做的事情
中国ai chip初创公司 By Jared Newman 杰里德·纽曼(Jared Newman) In late April, an investigation by The Guardian t ...
- linux内核imx6,imx6ull之linux内核移植
imx6ull开发环境之系统安装请参考:https://www.cnblogs.com/gxlblogs/p/14382547.html imx6ull交叉编译工具链安装 请参数:https://ww ...
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十四)文字显示
文章目录 一.文字显示 1.1 字符的编码方式 1.1.1 编码和字体 a. ASCII b. ANSI c. UNICODE 1.1.2 UNICODE编码实现 1.2 ASCII字符点阵显示 1. ...
- Freetype 的安装与使用
4 交叉编译程序 4.1 程序运行的一些基础知识 编译程序时去哪找头文件? 系统目录:就是交叉编译工具链里的某个 include 目录: 也可以自己指定:编译时用 " -I dir &quo ...
- 【iMX6ULL】触觉 imx6ull开发板交叉编译环境搭建
开发IMX6ULL需要有一个安装了交叉编译器的linux操作系统的开发环境,用于编译开发板的uboot.kernel.文件系统和应用软件.下面以触觉智能imx6ull开发板为例. 1.开发环境说明 ...
- 交叉编译 arm-poky-linux-gnueabi-gcc libmodbus库笔记
1:修改makefile CC = arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -m ...
- NXP IMX6ULL的官方文档、官方BSP、交叉编译工具链下载
目录 1 官网下载BSP以及相关文档 1.1 文档下载 1.2 NXP 官方uboot和kernel源码下载 1.3 官方评估板硬件资料下载 1.4 官方BSP下载 2 官网SDK下载 3 交叉编译工 ...
- imx6ull项目也是封装成脚本安装 Poky 交叉编译工具链类似ATK-STM32MP157交叉编译
[正点原子MP157连载]第六章 ATK-STM32MP157交叉编译篇 学习 2021-05-29 10:20887阅读 · 25喜欢 · 3评论 粉丝:17.3万文章:122 关注 正点原子提供了 ...
- QT4.8.6的交叉编译 - 编译平台:Ubuntu 20.04 LTS,目标平台:linux/imx6ull
版本记录表 开发环境 编译环境: 64位Ubuntu 20.04 LTS 交叉编译工具链: arm-linux-gnueabihf-GCC 4.9.1 本地编译器:gcc version 7.5.0 ...
最新文章
- Python使用matplotlib可视化散点图、并在可视化图像的底部和右边添加边缘直方图、自定义边缘直方图的色彩(Marginal Histogram)
- Github霸榜月余,原来是阿里技术官的千亿级并发系统设计手册上线了
- 如何让 python 处理速度翻倍?内含代码
- ctrl f显示查找计算机,请教:快捷方式查找Ctrl+F失效,怎么办 – 手机爱问
- 海信电视root工具_中国企业的远见:用一项自主技术,打败日韩电视,成为行业引领者...
- Spring : Spring容器之SmartLifeCycle的简单使用
- YunOS互联网汽车:妥协下的创新
- 给PhotoShop安装Portraiture插件
- EasyUI DataGrid 可编辑列级联操作
- 纳加服务器授权文件,VJSAC(纳加VJMS3服务管理终端)
- 统计学常用的数据分析方法总结
- 利用 Erdas 软件将矿区拐点坐标转换为经纬度坐标
- TypesScript + Nodejs + Express + Mongoose 实现 RESTful API 实战视频教程(33 个视频)
- Word 2010版本
- 马尔可夫链(Markov chain)的性质
- docker安装konga
- JAVA中JButton常用设置
- OMAP4 pandaboard ES开发资料总结
- 基于历史K线数据比较的量化选股方法及其系统分享
- 联想服务器提示系统初始化,联想服务器故障
热门文章
- 算法美学!从欧拉公式到傅里叶动画!
- 豌豆荚手机精灵试用测试
- Windows Server 2012 R2 此更新不适用于你的计算机 问题解决
- HTML基础——header, nav, footer, article, section, aside
- 【计算机网络】实验四 应用层和传输层协议分析(PacketTracer)
- python中字典的使用
- 过秦楼 . 碧玉连空
- (6)Scrum Master的七种武器之碧玉刀多情环
- 在网上如何找靠谱的兼职?
- MySQL数据库安装教程(windows)