WIP write multiple registers
This commit is contained in:
parent
12cd3df5a3
commit
0bfc93d3ea
@ -107,6 +107,7 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 1,
|
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 1,
|
||||||
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2,
|
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2,
|
||||||
|
MODBUS_EXCEPTION_ILLEGAL_REGISTER_QUANTITY = 2,
|
||||||
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3,
|
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3,
|
||||||
MODBUS_EXCEPTION_SLAVE_DEVICE_FAILURE = 4,
|
MODBUS_EXCEPTION_SLAVE_DEVICE_FAILURE = 4,
|
||||||
MODBUS_EXCEPTION_ACKNOWLEDGE = 5,
|
MODBUS_EXCEPTION_ACKNOWLEDGE = 5,
|
||||||
|
@ -291,6 +291,10 @@ int main(void)
|
|||||||
/* TODO: Process data and light a desired color of LED */
|
/* TODO: Process data and light a desired color of LED */
|
||||||
/* TODO: Add hystheresis */
|
/* TODO: Add hystheresis */
|
||||||
|
|
||||||
|
/* Reset the TIM21 Elapsed Period Flag */
|
||||||
|
tim21_elapsed_period = 0;
|
||||||
|
}
|
||||||
|
/* TEST END */
|
||||||
if (sensor_config.led_on) {
|
if (sensor_config.led_on) {
|
||||||
if (CO2 <= sensor_config.led_co2_alert_limit1) {
|
if (CO2 <= sensor_config.led_co2_alert_limit1) {
|
||||||
/* CO2 is OK -> GREEN */
|
/* CO2 is OK -> GREEN */
|
||||||
@ -315,11 +319,6 @@ int main(void)
|
|||||||
LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
|
LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
|
||||||
LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
|
LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the TIM21 Elapsed Period Flag */
|
|
||||||
tim21_elapsed_period = 0;
|
|
||||||
}
|
|
||||||
/* TEST END */
|
|
||||||
/* USER CODE END WHILE */
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
/* USER CODE BEGIN 3 */
|
/* USER CODE BEGIN 3 */
|
||||||
|
@ -58,6 +58,7 @@ int8_t modbus_copy_reply_to_buffer(uint8_t *buffer, uint8_t *msg_len, modbus_tra
|
|||||||
uint16_t crc16;
|
uint16_t crc16;
|
||||||
uint8_t byte_count;
|
uint8_t byte_count;
|
||||||
|
|
||||||
|
// TODO use relative indices (increments) instead of absolute
|
||||||
buffer[0] = modbus_slave_address;
|
buffer[0] = modbus_slave_address;
|
||||||
buffer[1] = transaction->function_code;
|
buffer[1] = transaction->function_code;
|
||||||
*msg_len = 5;
|
*msg_len = 5;
|
||||||
@ -86,6 +87,13 @@ int8_t modbus_copy_reply_to_buffer(uint8_t *buffer, uint8_t *msg_len, modbus_tra
|
|||||||
buffer[5] = (uint8_t) transaction->holding_registers[0];
|
buffer[5] = (uint8_t) transaction->holding_registers[0];
|
||||||
*msg_len = 8;
|
*msg_len = 8;
|
||||||
break;
|
break;
|
||||||
|
case MODBUS_WRITE_MULTIPLE_REGISTERS:
|
||||||
|
buffer[2] = (uint8_t) (transaction->register_address >> 8);
|
||||||
|
buffer[3] = (uint8_t) transaction->register_address;
|
||||||
|
buffer[4] = (uint8_t) (transaction->register_count >> 8);
|
||||||
|
buffer[5] = (uint8_t) transaction->register_count;
|
||||||
|
*msg_len = 8;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crc16 = modbus_CRC16(buffer, *msg_len - 2); /* last two bytes is the checksum itself */
|
crc16 = modbus_CRC16(buffer, *msg_len - 2); /* last two bytes is the checksum itself */
|
||||||
@ -109,11 +117,18 @@ int8_t modbus_slave_set_address(uint8_t address)
|
|||||||
|
|
||||||
int8_t modbus_slave_process_msg(const uint8_t *buffer, int len)
|
int8_t modbus_slave_process_msg(const uint8_t *buffer, int len)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* TODO list:
|
||||||
|
*
|
||||||
|
* 1) check that errors and exceptions are handled according to Modbus_Application_Protocol_V1_1b.pdf
|
||||||
|
* 2) buffer overflow prevention: for each function code, check that buffer is long enough
|
||||||
|
*/
|
||||||
/* transaction holds message context and content:
|
/* transaction holds message context and content:
|
||||||
* it wraps all necessary buffers and variables */
|
* it wraps all necessary buffers and variables */
|
||||||
modbus_transaction_t transaction;
|
modbus_transaction_t transaction;
|
||||||
int8_t callback_result;
|
int8_t callback_result;
|
||||||
uint8_t buffer_pos = 0;
|
uint8_t buffer_pos = 0;
|
||||||
|
uint8_t byte_count;
|
||||||
|
|
||||||
if (len < MODBUS_MINIMAL_FRAME_LEN) {
|
if (len < MODBUS_MINIMAL_FRAME_LEN) {
|
||||||
/* frame too short; return error */
|
/* frame too short; return error */
|
||||||
@ -188,11 +203,22 @@ int8_t modbus_slave_process_msg(const uint8_t *buffer, int len)
|
|||||||
return MODBUS_ERROR;
|
return MODBUS_ERROR;
|
||||||
}
|
}
|
||||||
transaction.register_address = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
transaction.register_address = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
||||||
|
// TODO check length!
|
||||||
if (flags & MODBUS_FLAG_WRITE) {
|
if (flags & MODBUS_FLAG_WRITE) {
|
||||||
if (flags & MODBUS_FLAG_SINGLE) {
|
if (flags & MODBUS_FLAG_SINGLE) {
|
||||||
transaction.holding_registers[0] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
transaction.holding_registers[0] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
||||||
} else {
|
} else {
|
||||||
// write multiple register - TODO
|
/* Write multiple registers */
|
||||||
|
transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
||||||
|
byte_count = buffer[buffer_pos++];
|
||||||
|
if (transaction.register_count > 123 || 2*transaction.register_count != byte_count) {
|
||||||
|
/* Max number of register is defined by Modbus_Application_Protocol_V1_1b, section 6.12 */
|
||||||
|
transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_REGISTER_QUANTITY;
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < transaction.register_count; i++) {
|
||||||
|
transaction.holding_registers[i] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
|
||||||
|
41
tests/write_multiple_holding_registers_test.py
Executable file
41
tests/write_multiple_holding_registers_test.py
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from time import sleep
|
||||||
|
from sys import exit
|
||||||
|
import minimalmodbus
|
||||||
|
import serial
|
||||||
|
|
||||||
|
slave_address = 254
|
||||||
|
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', slave_address, close_port_after_each_call=True) # port name, slave address (in decimal)
|
||||||
|
|
||||||
|
instrument.serial.baudrate = 19200
|
||||||
|
instrument.serial.bytesize = 8
|
||||||
|
instrument.serial.parity = serial.PARITY_EVEN
|
||||||
|
instrument.serial.stopbits = 1
|
||||||
|
instrument.serial.timeout = 0.05 # seconds
|
||||||
|
instrument.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
|
||||||
|
instrument.clear_buffers_before_each_transaction = True
|
||||||
|
|
||||||
|
# holding register numbers
|
||||||
|
LED_on_register = 0
|
||||||
|
LED_brightness_register = 1
|
||||||
|
LED_smooth_register = 2
|
||||||
|
CO2_alert_limit_1_register = 3
|
||||||
|
CO2_alert_limit_2_register = 4
|
||||||
|
SCD4x_temperature_offset_register = 5
|
||||||
|
MODBUS_address_register = 6
|
||||||
|
baudrate_register = 7
|
||||||
|
# values
|
||||||
|
LED_on = 1
|
||||||
|
LED_brightness = 100
|
||||||
|
LED_smooth = 0
|
||||||
|
CO2_alert_limit_1 = 1000
|
||||||
|
CO2_alert_limit_2 = 2000
|
||||||
|
SCD4x_temperature_offset = 0
|
||||||
|
MODBUS_address = 254
|
||||||
|
baudrate = 0
|
||||||
|
registers = [LED_on, LED_brightness, LED_smooth, CO2_alert_limit_1, CO2_alert_limit_2, SCD4x_temperature_offset, MODBUS_address, baudrate]
|
||||||
|
# write to holding registers
|
||||||
|
print('---- Writing to multiple holding registers ----')
|
||||||
|
instrument.write_registers(LED_on_register, registers)
|
||||||
|
print('---- DONE ----')
|
||||||
|
exit(0)
|
Loading…
Reference in New Issue
Block a user