我试图写一个程序,将运行在我的开放wrt路由器上,从一个modbus设备读取一些寄存器。我发现这样做的唯一方法是用C语言编写程序。我编写了一个简单的Python应用程序,用于从我的PC与Modbus RTU从设备通信:

#!/usr/bin/env python

import minimalmodbus
import serial

m = minimalmodbus.Instrument('/dev/ttyUSB0', 2) # port name, slave address (in decimal)
m.serial.baudrate = 19200
m.serial.bytesize = 8
m.serial.stopbits = 2
m.serial.parity   = serial.PARITY_NONE

data = m.read_registers(0, 2, 3) # 3 = Read holding register

print "Value A = ", data[0]
print "Value B = ", data[1]

if (data[0] < 20):
    send = 1
else:
    send = 0

m.write_register(2, send, 0, 16) # 16 = Write multiple registers

现在我需要使用libmodbus或其他一些C modbus库将代码重写为C。我不能将Python安装到设备上,因为它只有4MB的空间,所以我唯一的选择是使用C/C++。
我发现了树莓Pi的this example代码,但代码仅用于RPi:
// Access from ARM Running Linux
#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
void *gpio_map;
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
// Note: Revision2.0 RaspberryPis, GPIO Pins are: 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, with 28, 29, 30, 31 additionally available on the P5 header)
// for pinout info see http://elinux.org/RPi_Low-level_peripherals#GPIO_Driving_Example_.28C.29
// define GPIO number for each pin (using rev2 of pi)
// T= Top row of pins

我的设备不是RPi。
你知道一些例子吗?除了一个简单的Hello World程序之外,我不知道C。抱歉问了这么愚蠢的问题。

最佳答案

我为你感到。。。就它支持的编程语言而言,它看起来像是卡在C/C++或Lua上。因为你试图用你的电脑为你的路由器编译代码,你将不得不考虑交叉编译。原因(如果您不知道)是您的PC运行在(很可能)x86_64或32位体系结构(arch)CPU上,当您正常编译代码时,它将编译为仅在此arch上运行的机器代码。您的路由器可能运行在ARM或MIPS32或类似的架构上(您应该可以在DD wrt或Open wrt数据库中找到这一点),因此您必须让计算机编译器将代码编译为机器代码,这些代码将运行在不同的架构上,这可能很棘手。我不是交叉编译专家,也不是开放式wrt专家,也不是一般的modding routers(PITA)专家,但是如果你在Google上搜索,你应该可以找到一些好的教程。
有一个关于嵌入式Linuxhere交叉编译的不错的教程。
here是一个很好的教程,看起来它可以指导您完成专门针对Open wrt C项目的交叉编译过程:
另外,只是检查,但我假设你的路由器要么有一个串行端口,要么你计划使用ModbusTCP到RTU网关,在这种情况下,你必须将你的程序设置为TCP模式。
根据我在任何语言中使用modbus的经验,如果您对协议本身以及您试图与之通信的设备没有一个有效的理解,那么使用modbus可能会有点吓人(通常这些设备都很棘手,需要对它们的文档进行两次和三次检查)此外,每个实现都有一点不同,有些可能需要大量的阅读、调整和调试才能得到一个有效的测试,其他的则是现成的(比如用于python的minimalmodbus库)。
这里有一个链接(没有足够的rep so和复制粘贴并添加一个“h”)到libmodbus的文档:ttp://libmodbus.org/docs/v3.1.1/
我已经有一段时间没有写C代码了,但是我已经从文档中剪贴了这段代码,并试图添加一些注释。它处理基本的RTU连接以及从寄存器中读取数据。

#include <modbus.h>
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;
// create your modbus device object
/*modbus_t *modbus_new_rtu(
    const char *device, int baud, char parity, int data_bit, int stop_bit);*/
ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
// check if object was created successfully
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}
//int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
// read a register value from modbus object into value 'rc'
rc = modbus_read_registers(ctx, 2, 3, tab_reg);
// check to make sure read was successful
if (rc == -1) {
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}
// i'm guessing on this one, but convert a bytes vale into an integer... probably?
for (i=0; i < rc; i++) {
    printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
// close port and free memory
modbus_close(ctx);
modbus_free(ctx);

我建议你找到一个很好的教程或书,例如来自O'ReLyLi的实用C++(这是我最初使用的),或者谷歌搜索“C编程教程”(我没有足够的RP来发布更多的链接,而且我对C也不太了解,而不能发布好的链接),并且在其他任何事情之前学习一点语言。
如果在阅读完文档后需要更多关于libmodbus包的帮助,可以在freenode#libmodbus上尝试Stephanes IRC频道,也可以一直在这里尝试。但是,如果你有一个问题是具体的,这是很值得投资一点时间,以确保你的问题是一样的信息需要。
祝你好运!:-)

关于python - 使用libmodbus C为Open-WRT路由器编写Modbus程序(将Python应用重写为C),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26878114/

10-11 08:07