WIP write multiple registers

This commit is contained in:
Duke NUCem 2021-10-11 17:05:54 +02:00
parent 12cd3df5a3
commit 0bfc93d3ea
4 changed files with 74 additions and 7 deletions

View File

@ -107,6 +107,7 @@ typedef enum {
typedef enum {
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 1,
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2,
MODBUS_EXCEPTION_ILLEGAL_REGISTER_QUANTITY = 2,
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3,
MODBUS_EXCEPTION_SLAVE_DEVICE_FAILURE = 4,
MODBUS_EXCEPTION_ACKNOWLEDGE = 5,

View File

@ -291,6 +291,10 @@ int main(void)
/* TODO: Process data and light a desired color of LED */
/* TODO: Add hystheresis */
/* Reset the TIM21 Elapsed Period Flag */
tim21_elapsed_period = 0;
}
/* TEST END */
if (sensor_config.led_on) {
if (CO2 <= sensor_config.led_co2_alert_limit1) {
/* 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_B_GPIO_Port, LED_B_Pin);
}
/* Reset the TIM21 Elapsed Period Flag */
tim21_elapsed_period = 0;
}
/* TEST END */
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */

View File

@ -58,6 +58,7 @@ int8_t modbus_copy_reply_to_buffer(uint8_t *buffer, uint8_t *msg_len, modbus_tra
uint16_t crc16;
uint8_t byte_count;
// TODO use relative indices (increments) instead of absolute
buffer[0] = modbus_slave_address;
buffer[1] = transaction->function_code;
*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];
*msg_len = 8;
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 */
@ -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)
{
/*
* 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:
* it wraps all necessary buffers and variables */
modbus_transaction_t transaction;
int8_t callback_result;
uint8_t buffer_pos = 0;
uint8_t byte_count;
if (len < MODBUS_MINIMAL_FRAME_LEN) {
/* frame too short; return error */
@ -188,11 +203,22 @@ int8_t modbus_slave_process_msg(const uint8_t *buffer, int len)
return MODBUS_ERROR;
}
transaction.register_address = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
// TODO check length!
if (flags & MODBUS_FLAG_WRITE) {
if (flags & MODBUS_FLAG_SINGLE) {
transaction.holding_registers[0] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];
} 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 {
transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++];

View 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)