1、简述
Modbus 协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为Modbus Master,从设备方使用的协议称为Modbus Slave。典型的主设备包括工控机和工业控制器等;典型的从设备如PLC可编程控制器等。Modbus通讯物理接口可以选用串口(包括RS232和RS485),也可以选择以太网口。其通信遵循以下的过程:
        •  主设备向从设备发送请求; 
        •  从设备分析并处理主设备的请求,然后向主设备发送结果; 
        •  如果出现任何差错,从设备将返回一个异常功能码。
英创公司提供的ARM9嵌入式主板系列产品,均带有丰富的串口、网络资源,同时具有强大的处理能力,非常适用于作为Modbus 主设备的开发应用,为了加快做这类应用的开发速度,英创公司特推出Linux下的Modbus主控软件,该软件的是以C函数静态库文件libmbusmaster.a的形式提供给客户。主要特征如下:
        •  非常适用于实时的工业应用,特别可以广泛应用于对于PLC的控制。 
        •  可以支持基于串口的Modbus协议或者基于TCP的Modbus协议。 
        •  支持RTU传输模式。 
        •  支持大多数的Modbus功能码操作,包括对线圈、离散开关输入的位操作,以及对寄存器的字节操作。 
        •  支持广播地址。 
        •  可以获取通讯中传输协议的错误代码的详细信息。
2、Modbus Master API函数简介
为了方便应用程序的使用,对不同的通讯介质保持一致的代码形式,英创所提供的ModBus主控软件包的API函数可以同时支持基于串口和TCP的Modbus Master协议,应用程序只需要在调用初始化函数时,用不同参数区分即可。有关Modbus通讯的具体使用方法,请参考Modbus标准文献以及被控设备的通讯接口数据手册。以下介绍英创Modbus主控软件的相关API函数,各个函数的定义如下:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述:通过串口或者网络TCP打开ModBus协议,连接到ModBus设备。对于串口方式,通过该函数打开串口,并设置相应串口的通讯参数,以满足数据和控制命令的通讯;对于TCP方式,通过该函数和ModBus设备建立基于Socket方式的TCP连接,利用该连接进行数据和控制命令的通讯。 
输入参数 pPortName: 
        该参数为CHAR类型的字符串,该字符串中包含了打开ModBus协议的需要设置的通讯参数信息。对于串口模式和TCP两种模式分别采用不同的格式的字符串。 
(1) 串口模式: 
        字符串必须以ttyS作为开头,后面再带上需要设置的串口通讯参数。格式为: ttySIdx:baudRate-dataBits-stopBits-parity 
        其中Idx为串口序号,':' 后为串口通讯参数,各个通讯参数均用整型数据来表示,依次为波特率、数据位、停止位、校验位,校验位 0-无校验 1-奇校验 2-偶校验。 
        如串口3作为通讯的协议口,波特率:9600bps、8为数据位、1个停止位、无校验。其格式如下: 
        'ttyS3:9600-8-1-0' ; 
        也可以直接就用 'ttyS3' 来表示,表明串口所用的为缺省参数:波特率 9600bps 数据位 8 停止位 1 无奇偶校验。 
(2) TCP模式: 
        字符串以IP地址作为开头,':'后为指定TCP连接的特殊端口号,ModBus协议中缺省端口为502。如果不需要指定特殊端口,可以不带此参数。格式如: 
        '192.168.201.178' ,使用端口号为502; 
        '192.168.201.178:2000' ,使用端口号为2000; 
返回值 = NULL: 连接ModBus设备失败。 
        != NULL: 连接ModBus设备成功,并返回相应的操作句柄。 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(1) HANDLE mbusMaster_OpenPortProtocol( char* pPortName );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: 关闭ModBus设备连接,同时释放使用的系统资源。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
返回值 = FALSE: 关闭操作失败。 = TRUE: 关闭操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(2) int mbusMaster_ClosePortProtocol( HANDLE hPort ); 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: 设置ModBus通讯的超时时间,单位为毫秒。并返回实际设置的超时时间。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        milliseconds: ModBus通讯超时时间,单位为毫秒。 
返回值 < 0: 操作失败。 > 0: 实际设置的超时时间。 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(3) int mbusMaster_SetTimeout( HANDLE hPort, int milliseconds );
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: 读取ModBus从机设备的线圈值,实现ModBus功能码1。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要读取线圈的起始值,其范围为: 1~0x10000 
        bitArr: 存放读取线圈数据的数组 
        refCnt: 需要读取的线圈数量,其范围为: 1~2000 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(4) int mbusMaster_ReadCoils( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, int bitArr[], UINT16 refCnt);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: 读取ModBus从机设备离散量的输入值,实现ModBus功能码2。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要读取离散量的起始值,其范围为: 1~0x10000 
        bitArr: 存放读取离散量输入数据的数组 
        refCnt: 需要读取的离散量数量,其范围为: 1~2000 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(5) int mbusMaster_ReadInputDiscretes( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, int bitArr[], UINT16 refCnt);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: ModBus从机设备的单个线圈的写入操作,实现ModBus功能码5。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        bitAddr: 需要操作的线圈地址,其范围为: 1~0x10000 
        bitVal: 写入线圈的值, 1-置位(ON) 0-清(OFF) 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。= 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(6) int mbusMaster_WriteCoil( HANDLE hPort, UCHAR slaveAddr, UINT16 bitAddr, int bitVal );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: ModBus从机设备的多个线圈的写入操作,实现ModBus功能码15。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要设置的线圈起始值,其范围为: 1~0x10000 
        bitArr: 需要设置线圈数据的数组 
        refCnt: 需要设置的线圈数量,其范围为: 1~800 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(7) int mbusMaster_ForceMultipleCoils( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, int bitArr[], UINT16 refCnt); 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: 读取ModBus从机设备多个寄存器值,实现ModBus功能码3。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要读取寄存器的起始值,其范围为: 1~0x10000 
        regArr: 存放读取寄存器值的数组 
        refCnt: 需要读取的寄存器数量,其范围为: 1~125 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(8) int mbusMaster_ReadMultipleRegisters( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, UINT16 regArr[], UINT16 refCnt ); 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: 读取ModBus从机设备输入寄存器值,实现ModBus功能码4。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要读取输入寄存器的起始值,其范围为: 1~0x10000 
        regArr: 存放读取输入寄存器值的数组 
        refCnt: 需要读取的输入寄存器数量,其范围为: 1~125 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(9) int mbusMaster_ReadInputRegisters( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, UINT16 regArr[], UINT16 refCnt); 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: ModBus从机设备多个寄存器的写操作,实现ModBus功能码16。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        startRef: 需要读取寄存器的起始值,其范围为: 1~0x10000 
        regArr: 需写入寄存器值的数组 
        refCnt: 需要操作的寄存器数量,其范围为: 1~100 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(10) int mbusMaster_WriteMultipleRegisters( HANDLE hPort, UCHAR slaveAddr, UINT16 startRef, UINT16 regArr[], UINT16 refCnt);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: 对ModBus从机设备单个寄存器的写操作,实现ModBus功能码6。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        regAddr: 需要操作寄存器的地址,其范围为: 1~0x10000 
        regVal: 需写入寄存器的值 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(11) int mbusMaster_WriteSingleRegister( HANDLE hPort, UCHAR slaveAddr, UINT16 regAddr, UINT16 regVal );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 功能描述: 对ModBus从机设备屏蔽写寄存器,实现ModBus功能码22。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        regAddr: 需要操作寄存器的地址,其范围为: 1~0x10000 
        andMask: 屏蔽写与数据 
        orMask: 屏蔽写或数据 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(12) int mbusMaster_MaskWriteRegister( HANDLE hPort, UCHAR slaveAddr, UINT16 regAddr, UINT16 andMask, UINT16 orMask); 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
功能描述: 对ModBus从机设备读写多个寄存器操作,实现ModBus功能码23。 
输入参数 hPort: 连接ModBus设备返回的有效操作句柄。 
        slaveAddr: ModBus从机设备的地址,地址范围为: 1~255 
        readRef: 需要读取多个寄存器的起始值,其范围为: 1~0x10000 
        readArr: 存放读取寄存器值的数组 
        readCnt: 需要读取的寄存器数量,其范围为: 1~125 
        writeRef: 需要写入多个寄存器的起始值,其范围为: 1~0x10000 
        writeArr: 写入寄存器值的数组 
        writeCnt: 需要写入的寄存器数量,其范围为: 1~125 
返回值 != 0: 该功能操作失败,返回值为相应的出错代码。 = 0: 该功能操作成功。 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(13) int mbusMaster_ReadWriteRegisters( HANDLE hPort, UCHAR slaveAddr, UINT16 readRef,UINT16 readArr[],UINT16 readCnt, UINT16 writeRef, UINT16 writeArr[], UINT16 writeCnt);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: 获取ModBus软件包的版本信息。 
返回值 : CHAR类型的字符串,为ModBus软件包的版本信息。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(14) char * mbusMaster_GetPackageVersion( ); 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
功能描述: 根据错误代码获取错误文本信息。 
返回值 : CHAR类型的字符串,为错误文本信息。 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
(15) char * mbusMaster_GetErrorText( int errCode ); 
3、应用例程
对于应用来说,所建立的应用程序工程只需要包含modbus_Master.h、libmbusmaster.a文件即可方便实现对于modbus Master协议API函数的调用。以下代码为一个简单的调用例程:
        // MbusMasterTest.cpp : Defines the entry point for the application. 
        // 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 'modbus_Master.h' 
        //char *hostName = '192.168.201.178'; 
        //char *hostName = 'ttyS3:9600-8-1-0'; 
        char hostName[80]; 
        int main( int argc,char* argv[] ) 
        { 
                int i1, result; 
                int portno, baudRate; 
                UINT16 dataArr[8]; 
                char str[200]; 
                HANDLE hPort; 
                // 解析命令行参数:串口号 波特率 
                if( argc > 1 ) 
                        portno = atoi( argv[1] ); 
                else 
                        portno = 3; 
                if( argc > 2 ) 
                        baudRate = atoi( argv[2]); 
                else 
                        baudRate = 9600; 
                printf( 'port:%d baudrate:%d\n', portno, baudRate); 
                sprintf( hostName, 'ttyS%d:%d-8-1-0', portno, baudRate ); 
                // 启动ModBus协议,连接到Modbus设备 
                hPort = mbusMaster_OpenPortProtocol( hostName ); 
                if( hPort==INVALID_HANDLE_VALUE ) 
                { 
                        printf( 'Open fail!\n'); 
                        return -1; 
                } 
                //进入主循环 
                for( ; ; ) 
                { 
                        result = mbusMaster_ReadMultipleRegisters( hPort, 1, 1, dataArr, sizeof(dataArr) / 2); 
                        //result = mbusMaster_WriteCoil( hPort, 1, 1, 1 ); 
                        if (result == 0) 
                        { 
                                for (i1 = 0; i1 < int(sizeof(dataArr) / 2); i1++) 
                                { 
                                        printf('[%d]: %hd\n', i1 + 1, dataArr[i1]); 
                                } 
                        } 
                        else 
                        { 
                                strcpy( str,mbusMaster_GetErrorText( result ) ); 
                                i1 = strlen( str ); 
                                if( i1>0 ) 
                                { 
                                        printf( '%s!\n', str ); 
                                } 
                        } 
                        sleep(1); 
                } 
                mbusMaster_ClosePortProtocol( hPort ); 
                return 0; 
        }
该工程文件中用到专用静态库libmbusmaster.a,在eclipse环境对此程序编译时,需要设置相应的编译属性。在Project Explorer视窗下,选择需要设置的工程文件,然后点击鼠标右键,选择 Properties项,在窗口中选择C/C++ Build -> Settings -> Tool Settings -> Sourcery G++ C++ Linker -> Libraries,如下图所示。其中的一个窗口用于指定库文件的名称,一个用于指定库文件的路径。

成都英创信息技术有限公司 028-8618 0660