玩转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!\n");
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!\n");
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\n");
return -1;
} printf("MY_Debug: usleep begin! \n"); //这里我给了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! \n");
fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno)); modbus_close(ctx); //关闭modbus连接
modbus_free(ctx); //释放modbus资源,libmodbus需要释放掉
}
else{
printf("MY_Debug: modbus_connect Success! \n");
} while (1)
{
printf("\n 这里的代码只执行一次 return -1,或者 break \n"); rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) //读取保持寄存器的值,可读取多个连续输入保持寄存器
{
write_data_hex(&log[1], 1, Path_log2);
fprintf(stderr,"%s\n", modbus_strerror(errno));
printf("MY_Debug: modbus_read_registers Fail! \n");
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)\n", 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_2019\LibModbus\使用到的工具软件\ModSim32 v1.A00-04
软件使用介绍:
先点击New, 就可以出现‘’2’的界面,并配置好参数,以便后面使用

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

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


实验成功。注意,modbus一个寄存器占两个字节。大小端有区分。
玩转Libmodbus(二) 写代码体验的更多相关文章
- 让 AI 为你写代码 - 体验 Github Copilot
前几天在群里看到有大神分享 Copoilot AI 写代码,看了几个截图有点不敢相信自己的眼睛.今天赶紧自己也来体验一下 Copoilot AI 写代码到底有多神奇. 申请 现在 Copoilot 还 ...
- [转]<版本二>写代码的小女孩
天冷极了,下着雪,又快黑了.这是一年的最后一天——大年夜.在这又冷又黑的晚上,一个乖巧的小女孩在机房里调试程序.她从家里出来的时候还穿着一件外套,但是有什么用呢?那是一双很大的外套——那么大,不知是哪 ...
- 亮瞎你狗眼的写代码体验狂拽酷炫效果 activate-power-mode
年末了,整理一些收藏的资料,没想到发现一个敲代码的装逼神器; 话不多说上图 我是用idea装的,其他编辑器请自行查找 Preferences -> Plugins -> Install p ...
- vs2022+resharper C++ = 拥有一个不输clion的代码体验
这篇文章详细讲一下resharper C++在vs2022中的配置,让他拥有跟clion一样好用的代码补全功能. 为什么clion写代码体验很好好用为啥还要用vs呢,因为网上很多教程都是基于visua ...
- 如何结合整洁架构和MVP模式提升前端开发体验(二) - 代码实现篇
上一篇文章介绍了整体架构,接下来说说怎么按照上图的分层结构实现下面的增删改查的功能. 代码结构 vue userManage └── List ├── api.ts ├── EditModal │ ├ ...
- SQL强化(二) 在Oracle 中写代码
一 : 关于查询中的转换 -- 字符串转换 一 : decode 函数 转换 SELECT DECODE ( PROTYPE.PRO_TYPE_DATE, 'L', '长', 'm', '短', ' ...
- 有个AI陪你一起写代码,是种怎样的体验?| 附ICLR论文
从前,任何程序的任何功能,都需要一行一行敲出来. 后来,程序猿要写的代码越来越多,世界上便有了各种各样的API,来减少大家的工作量.有些功能,可以让API来帮我们实现. 不过,人类写下的话,API并不 ...
- Qt侠:像写诗一样写代码,玩游戏一样的开心心情,还能领工资!
[软]上海-Qt侠 2017/7/12 16:11:20我完全是兴趣主导,老板不给我钱,我也要写好代码!白天干,晚上干,周一周五干,周末继续干!编程已经深入我的基因,深入我的骨髓,深入我的灵魂!当我解 ...
- 手写MVC框架(二)-代码实现和使用示例
--------上一篇:手写MVC框架(一)-再出发----- 背景 书接上文,之前整理了实现MVC框架需要写哪些东西.这周粗看了一下,感觉也没多少工作量,所以就计划一天时间来完成.周末的时间,哪会那 ...
随机推荐
- 【洛谷日报#26】GCC自带位运算系列函数
文章转自 洛谷 谈到GCC的黑科技,大家想到的一定是这句: #pragma GCC optimize (3)//吸氧 抑或是这句: #pragma GCC diagnostic error " ...
- Laravel Reponse 响应客户端
Laravel Response 响应客户端 本篇文章逻辑较长,只说明和响应生命周期相关的必要代码. 本文主要内容顺序为: 1.执行上文管道中的then方法指定的闭包,路由的分发 2.在路由器中(Ro ...
- Unity NGUI C#性能优化
建议读者先看这篇博文:http://blog.csdn.net/zzxiang1985/article/details/43339273,有些技术已经变了,比如第1招,unity5的打包机制已经变许多 ...
- C++STL中vector的初始化
vector的初始化有很多方式,在N维初始化时还会一些容易出现错误的地方.下面进行总结 以下的总结均以int作为模板参数 一维vector的初始化 vector的构造函数通常来说有五种,如下: vec ...
- Q200510-02-02: 重复的DNA序列 SQL解法
重复的DNA序列所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”.在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数来 ...
- 20190923-02Linux文件目录类 000 010
pwd 显示当前工作目录的绝对路径 pwd:print working directory 打印工作目录 1.基本语法 pwd (功能描述:显示当前工作目录的绝对路径) 2.案例实操 (1)显示当前工 ...
- 一个SQL查询连续三天的流量100以上的数据值【SQql Server】
题目 有一个商场,每日人流量信息被记录在这三列信息中:序号 (id).日期 (date). 人流量 (people).请编写一个查询语句,找出高峰期时段,要求连续三天及以上,并且每天人流量均不少于10 ...
- Cassandra Vnodes在Cassandra 2.0-4.0中的演进
Vnodes简短历史 Vnodes又叫Virtual Nodes.是Cassandra在1.2版本里引入的功能,已经在生产环境中使用了近8年了.从2.0版本开始,因为默认配置里num_tokens一般 ...
- Kubernetes笔记(五):了解Pod(容器组)
Kubernetes 中, 容器总是以 Pod(容器组)的方式进行调度与运行.因此对 Pod 的理解与掌握是学习 Kubernetes 的基础. 理解 Pod Pod(容器组)是 Kubernetes ...
- selenium常用webdriver api汇总
1.driver.current_url:用于获得当前页面的URL 2.driver.title:用于获取当前页面的标题 3.driver.page_source:用于获取页面html源代码 4.dr ...