msousa@0: /* msousa@0: * Copyright (c) 2001-2003,2016 Mario de Sousa (msousa@fe.up.pt) msousa@0: * msousa@0: * This file is part of the Modbus library for Beremiz and matiec. msousa@0: * msousa@0: * This Modbus library is free software: you can redistribute it and/or modify msousa@0: * it under the terms of the GNU Lesser General Public License as published by msousa@0: * the Free Software Foundation, either version 3 of the License, or msousa@0: * (at your option) any later version. msousa@0: * msousa@0: * This program is distributed in the hope that it will be useful, but msousa@0: * WITHOUT ANY WARRANTY; without even the implied warranty of msousa@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser msousa@0: * General Public License for more details. msousa@0: * msousa@0: * You should have received a copy of the GNU Lesser General Public License msousa@0: * along with this Modbus library. If not, see . msousa@0: * msousa@0: * This code is made available on the understanding that it will not be msousa@0: * used in safety-critical situations without a full and competent review. msousa@0: */ msousa@0: msousa@0: msousa@0: /* mb_master.h */ msousa@0: msousa@0: msousa@0: #ifndef MODBUS_MASTER_H msousa@0: #define MODBUS_MASTER_H msousa@0: msousa@0: #include /* struct timespec data structure */ msousa@0: msousa@0: #include "mb_types.h" /* get the data types */ msousa@0: #include "mb_addr.h" /* get definition of common variable types and error codes */ msousa@0: msousa@0: msousa@0: msousa@0: /*********************************************************************** msousa@0: msousa@0: Note: All functions used for sending or receiving data via msousa@0: modbus return these return values. msousa@0: msousa@0: msousa@0: Returns: string_length if OK msousa@0: -1 on internal error or port failure msousa@0: -2 on timeout msousa@0: -3 if a valid yet un-expected frame is received! msousa@0: -4 for modbus exception errors msousa@0: (in this case exception code is returned in *error_code) msousa@0: msousa@0: ***********************************************************************/ msousa@0: msousa@0: msousa@0: /* FUNCTION 0x01 - Read Coils msousa@0: * Bits are stored on an int array, one bit per int. msousa@0: */ andrej@1: int read_output_bits(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 *dest, andrej@1: int dest_size, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define read_coils(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \ msousa@0: read_output_bits(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) msousa@0: msousa@0: msousa@0: /* FUNCTION 0x01 - Read Coils msousa@0: * Bits are stored on an u32 array, 32 bits per u32. msousa@0: * Unused bits in last u32 are set to 0. msousa@0: */ andrej@1: int read_output_bits_u32(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u32 *dest, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_coils_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_output_bits_u32(p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x02 - Read Discrete Inputs msousa@0: * Bits are stored on an int array, one bit per int. msousa@0: */ andrej@1: int read_input_bits(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 *dest, andrej@1: int dest_size, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define read_discrete_inputs(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \ msousa@0: read_input_bits (p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) msousa@0: msousa@0: msousa@0: /* FUNCTION 0x02 - Read Discrete Inputs msousa@0: * Bits are stored on an u32 array, 32 bits per u32. msousa@0: * Unused bits in last u32 are set to 0. msousa@0: */ andrej@1: int read_input_bits_u32(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u32 *dest, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_discrete_inputs_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_input_bits_u32 (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x03 - Read Holding Registers */ andrej@1: int read_output_words(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 *dest, andrej@1: int dest_size, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define read_holding_registers(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \ msousa@0: read_output_words (p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) msousa@0: msousa@0: msousa@0: /* FUNCTION 0x03 - Read Holding Registers msousa@0: * u16 registers are stored in array of u32, two registers per u32. msousa@0: * Unused bits of last u32 element are set to 0. msousa@0: */ andrej@1: int read_output_words_u32(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u32 *dest, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_holding_registers_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_output_words_u32 (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: /* FUNCTION 0x03 - Read Holding Registers msousa@0: * return the array with the data to the calling function msousa@0: */ andrej@1: int read_output_words_u16_ref(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 **dest, andrej@1: int ttyfd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_holding_registers_u16_ref(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_output_words_u16_ref (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x04 - Read Input Registers */ andrej@1: int read_input_words(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 *dest, andrej@1: int dest_size, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define read_input_registers(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \ msousa@0: read_input_words (p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x04 - Read Input Registers msousa@0: * u16 registers are stored in array of u32, two registers per u32. msousa@0: * Unused bits of last u32 element are set to 0. msousa@0: */ andrej@1: int read_input_words_u32(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u32 *dest, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_input_registers_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_input_words_u32 (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x04 - Read Input Registers msousa@0: * return the array with the data to the calling function msousa@0: */ andrej@1: int read_input_words_u16_ref(u8 slave, andrej@1: u16 start_addr, andrej@1: u16 count, andrej@1: u16 **dest, andrej@1: int ttyfd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout); msousa@0: #define read_input_registers_u16_ref(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: read_input_words_u16_ref (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x05 - Force Single Coil */ andrej@1: int write_output_bit(u8 slave, andrej@1: u16 coil_addr, andrej@1: u16 state, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define force_single_coil(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: write_output_bit (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x06 - Write Single Register */ andrej@1: int write_output_word(u8 slave, andrej@1: u16 reg_addr, andrej@1: u16 value, andrej@1: int fd, andrej@1: int send_retries, andrej@1: u8 *error_code, andrej@1: const struct timespec *response_timeout, andrej@1: pthread_mutex_t *data_access_mutex); msousa@0: #define write_single_register(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: write_output_word (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x0F - Force Multiple Coils */ msousa@0: int write_output_bits(u8 slave, msousa@0: u16 start_addr, msousa@0: u16 coil_count, msousa@0: u16 *data, msousa@0: int fd, msousa@0: int send_retries, msousa@0: u8 *error_code, msousa@0: const struct timespec *response_timeout, msousa@0: pthread_mutex_t *data_access_mutex); msousa@0: #define force_multiple_coils(p1,p2,p3,p4,p5,p6,p7,p8,p9) \ msousa@0: write_output_bits (p1,p2,p3,p4,p5,p6,p7,p8,p9) msousa@0: msousa@0: msousa@0: /* FUNCTION 0x0F - Force Multiple Coils msousa@0: * Bits should be stored on an u32 array, 32 bits per u32. msousa@0: * Unused bits in last u32 should be set to 0. msousa@0: */ msousa@0: int write_output_bits_u32(u8 slave, msousa@0: u16 start_addr, msousa@0: u16 coil_count, msousa@0: u32 *data, msousa@0: int fd, msousa@0: int send_retries, msousa@0: u8 *error_code, msousa@0: const struct timespec *response_timeout); msousa@0: #define force_multiple_coils_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: write_output_bits_u32 (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x10 - Force Multiple Registers */ msousa@0: int write_output_words(u8 slave, msousa@0: u16 start_addr, msousa@0: u16 reg_count, msousa@0: u16 *data, msousa@0: int fd, msousa@0: int send_retries, msousa@0: u8 *error_code, msousa@0: const struct timespec *response_timeout, msousa@0: pthread_mutex_t *data_access_mutex); msousa@0: #define force_multiple_registers(p1,p2,p3,p4,p5,p6,p7,p8,p9) \ msousa@0: write_output_words (p1,p2,p3,p4,p5,p6,p7,p8,p9) msousa@0: msousa@0: msousa@0: msousa@0: /* FUNCTION 0x10 - Force Multiple Registers msousa@0: * u16 registers are stored in array of u32, two registers per u32. msousa@0: * Unused bits of last u32 element are set to 0. msousa@0: */ msousa@0: int write_output_words_u32(u8 slave, msousa@0: u16 start_addr, msousa@0: u16 reg_count, msousa@0: u32 *data, msousa@0: int fd, msousa@0: int send_retries, msousa@0: u8 *error_code, msousa@0: const struct timespec *response_timeout); msousa@0: msousa@0: #define force_multiple_registers_u32(p1,p2,p3,p4,p5,p6,p7,p8) \ msousa@0: write_output_words_u32 (p1,p2,p3,p4,p5,p6,p7,p8) msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* Initialise the Modbus Library to work as Master only */ msousa@0: int mb_master_init(int nd_count); msousa@0: /* Shut down the Modbus Library */ msousa@0: int mb_master_done(void); msousa@0: msousa@0: msousa@0: msousa@0: /* Establish a connection to a remote server/slave. msousa@0: * The address type (naf_tcp, naf_rtu, naf_ascii) specifies the lower msousa@0: * layer to use for the newly opened node. msousa@0: */ msousa@0: int mb_master_connect(node_addr_t node_addr); msousa@0: /* Shut down a connection to a remote server/slave */ msousa@0: int mb_master_close(int nd); msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: /* Tell the library that communications will be suspended for some time. */ msousa@0: /* RTU and ASCII versions ignore this function msousa@0: * TCP version closes all the open tcp connections (connections are automatically msousa@0: * re-established the next time an IO function to the slave is requested). msousa@0: * To be more precise, the TCP version makes an estimate of how long msousa@0: * the silence will be based on previous invocations to this exact same msousa@0: * function, and will only close the connections if this silence is msousa@0: * expected to be longer than 1 second! msousa@0: */ msousa@0: int mb_master_tcp_silence_init(void); msousa@0: msousa@0: msousa@0: msousa@0: #endif /* MODBUS_MASTER_H */ msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: msousa@0: