Example #1
0
/**
 * Send a Modbus write multiple registers command.
 *
 * @param modbus Previously initialized Modbus device structure.
 * @param address The Modbus address of the first register to write.
 * @param nb_registers The number of registers to write.
 * @param registers Buffer holding all the registers values to write.
 *
 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments,
 *         SR_ERR_DATA upon invalid data, or SR_ERR on failure.
 */
SR_PRIV int sr_modbus_write_multiple_registers(struct sr_modbus_dev_inst*modbus,
        int address, int nb_registers, uint16_t *registers)
{
    uint8_t request[6 + (2 * nb_registers)], reply[5];
    int ret;

    if (address < 0 || address > 0xFFFF
            || nb_registers < 1 || nb_registers > 123 || !registers)
        return SR_ERR_ARG;

    W8(request + 0, MODBUS_WRITE_MULTIPLE_REGISTERS);
    WB16(request + 1, address);
    WB16(request + 3, nb_registers);
    W8(request + 5, 2 * nb_registers);
    memcpy(request + 6, registers, 2 * nb_registers);

    ret = sr_modbus_request_reply(modbus, request, sizeof(request),
                                  reply, sizeof(reply));
    if (ret != SR_OK)
        return ret;
    if (sr_modbus_error_check(reply))
        return SR_ERR_DATA;
    if (memcmp(request, reply, sizeof(reply)))
        return SR_ERR_DATA;

    return SR_OK;
}
Example #2
0
/**
 * Send a Modbus read holding registers command and receive the corresponding
 * registers values.
 *
 * @param modbus Previously initialized Modbus device structure.
 * @param address The Modbus address of the first register to read, or -1 to
 *                read the reply of a previouly sent read registers command.
 * @param nb_registers The number of registers to read.
 * @param registers Buffer to store all the received registers values,
 *                  or NULL to send the read holding registers command
 *                  without reading the reply.
 *
 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments,
 *         SR_ERR_DATA upon invalid data, or SR_ERR on failure.
 */
SR_PRIV int sr_modbus_read_holding_registers(struct sr_modbus_dev_inst *modbus,
        int address, int nb_registers, uint16_t *registers)
{
    uint8_t request[5], reply[2 + (2 * nb_registers)];
    int ret;

    if (address < -1 || address > 0xFFFF
            || nb_registers < 1 || nb_registers > 125)
        return SR_ERR_ARG;

    W8(request + 0, MODBUS_READ_HOLDING_REGISTERS);
    WB16(request + 1, address);
    WB16(request + 3, nb_registers);

    if (address >= 0) {
        ret = sr_modbus_request(modbus, request, sizeof(request));
        if (ret != SR_OK)
            return ret;
    }

    if (registers) {
        ret = sr_modbus_reply(modbus, reply, sizeof(reply));
        if (ret != SR_OK)
            return ret;
        if (sr_modbus_error_check(reply))
            return SR_ERR_DATA;
        if (reply[0] != request[0] || R8(reply + 1) != (uint8_t)(2 * nb_registers))
            return SR_ERR_DATA;
        memcpy(registers, reply + 2, 2 * nb_registers);
    }

    return SR_OK;
}
Example #3
0
/**
 * Send a Modbus read coils command and receive the corresponding coils values.
 *
 * @param modbus Previously initialized Modbus device structure.
 * @param address The Modbus address of the first coil to read, or -1 to read
 *                the reply of a previouly sent read coils command.
 * @param nb_coils The number of coils to read.
 * @param coils Buffer to store all the received coils values (1 bit per coil),
 *              or NULL to send the read coil command without reading the reply.
 *
 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments,
 *         SR_ERR_DATA upon invalid data, or SR_ERR on failure.
 */
SR_PRIV int sr_modbus_read_coils(struct sr_modbus_dev_inst *modbus,
                                 int address, int nb_coils, uint8_t *coils)
{
    uint8_t request[5], reply[2 + (nb_coils + 7) / 8];
    int ret;

    if (address < -1 || address > 0xFFFF || nb_coils < 1 || nb_coils > 2000)
        return SR_ERR_ARG;

    W8(request + 0, MODBUS_READ_COILS);
    WB16(request + 1, address);
    WB16(request + 3, nb_coils);

    if (address >= 0) {
        ret = sr_modbus_request(modbus, request, sizeof(request));
        if (ret != SR_OK)
            return ret;
    }

    if (coils) {
        ret = sr_modbus_reply(modbus, reply, sizeof(reply));
        if (ret != SR_OK)
            return ret;
        if (sr_modbus_error_check(reply))
            return SR_ERR_DATA;
        if (reply[0] != request[0] || R8(reply + 1) != (uint8_t)((nb_coils + 7) / 8))
            return SR_ERR_DATA;
        memcpy(coils, reply + 2, (nb_coils + 7) / 8);
    }

    return SR_OK;
}
Example #4
0
static int maynuo_m97_cmd(struct sr_modbus_dev_inst *modbus,
		enum maynuo_m97_mode cmd)
{
	uint16_t registers[1];
	WB16(registers, cmd);
	return sr_modbus_write_multiple_registers(modbus, CMD, 1, registers);
}
Example #5
0
/**
 * Send a Modbus write coil command.
 *
 * @param modbus Previously initialized Modbus device structure.
 * @param address The Modbus address of the coil to write.
 * @param value The new value to assign to this coil.
 *
 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments,
 *         SR_ERR_DATA upon invalid data, or SR_ERR on failure.
 */
SR_PRIV int sr_modbus_write_coil(struct sr_modbus_dev_inst *modbus,
                                 int address, int value)
{
    uint8_t request[5], reply[5];
    int ret;

    if (address < 0 || address > 0xFFFF)
        return SR_ERR_ARG;

    W8(request + 0, MODBUS_WRITE_COIL);
    WB16(request + 1, address);
    WB16(request + 3, value ? 0xFF00 : 0);

    ret = sr_modbus_request_reply(modbus, request, sizeof(request),
                                  reply, sizeof(reply));
    if (ret != SR_OK)
        return ret;
    if (sr_modbus_error_check(reply))
        return SR_ERR_DATA;
    if (memcmp(request, reply, sizeof(reply)))
        return SR_ERR_DATA;

    return SR_OK;
}