/** * 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; }
/** * 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; }
/** * 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; }
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); }
/** * 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; }