kopia lustrzana https://github.com/SP8EBC/ParaTNC
modbus rtu exception handling
rodzic
bad16f5a44
commit
5ab37f1bba
|
@ -29,6 +29,7 @@
|
|||
|
||||
#ifdef _MODBUS_RTU
|
||||
#include "modbus_rtu/rtu_register_data_t.h"
|
||||
#include "modbus_rtu/rtu_exception_t.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -107,6 +108,10 @@ extern davis_loop_t rte_wx_davis_loop_content;
|
|||
extern rtu_register_data_t rte_wx_modbus_rtu_f4;
|
||||
#endif
|
||||
|
||||
extern rtu_exception_t rte_wx_last_modbus_exception;
|
||||
extern uint32_t rte_wx_last_modbus_rx_error_timestamp;
|
||||
extern uint32_t rte_wx_last_modbus_exception_timestamp;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -76,6 +76,10 @@ davis_loop_t rte_wx_davis_loop_content;
|
|||
rtu_register_data_t rte_wx_modbus_rtu_f4;
|
||||
#endif
|
||||
|
||||
rtu_exception_t rte_wx_last_modbus_exception;
|
||||
uint32_t rte_wx_last_modbus_exception_timestamp;
|
||||
uint32_t rte_wx_last_modbus_rx_error_timestamp;
|
||||
|
||||
#endif
|
||||
|
||||
void rte_wx_init(void) {
|
||||
|
@ -91,6 +95,10 @@ void rte_wx_init(void) {
|
|||
for (i = 0; i < 4; i++) {
|
||||
rte_wx_pressure_history[i] = 0.0f;
|
||||
}
|
||||
|
||||
rte_wx_last_modbus_exception_timestamp = 0;
|
||||
rte_wx_last_modbus_rx_error_timestamp = 0;
|
||||
rte_wx_last_modbus_exception = RTU_EXCEPTION_OK;
|
||||
}
|
||||
|
||||
void rte_wx_update_last_measuremenet_timers(uint16_t parameter_type) {
|
||||
|
|
|
@ -268,6 +268,12 @@ void wx_pool_anemometer(void) {
|
|||
|
||||
uint16_t scaled_windspeed = 0;
|
||||
|
||||
#if defined(_UMB_MASTER)
|
||||
rte_wx_average_winddirection = umb_get_winddirection();
|
||||
rte_wx_average_windspeed = umb_get_windspeed();
|
||||
rte_wx_max_windspeed = umb_get_windgusts();
|
||||
#else
|
||||
|
||||
#ifdef _ANEMOMETER_ANALOGUE
|
||||
// this windspeed is scaled * 10. Example: 0.2 meters per second is stored as 2
|
||||
scaled_windspeed = analog_anemometer_get_ms_from_pulse(rte_wx_windspeed_pulses);
|
||||
|
@ -278,11 +284,9 @@ void wx_pool_anemometer(void) {
|
|||
rte_wx_winddirection_last = tx20_get_wind_direction();
|
||||
#endif
|
||||
|
||||
#if defined(_UMB_MASTER)
|
||||
rte_wx_average_winddirection = umb_get_winddirection();
|
||||
rte_wx_average_windspeed = umb_get_windspeed();
|
||||
rte_wx_max_windspeed = umb_get_windgusts();
|
||||
#else
|
||||
#ifdef _MODBUS_RTU
|
||||
|
||||
#endif
|
||||
|
||||
// check how many times before the pool function was called
|
||||
if (wx_wind_pool_call_counter < WIND_AVERAGE_LEN) {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* rtu_exception_t.h
|
||||
*
|
||||
* Created on: 28.09.2020
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_
|
||||
#define INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum rtu_exception {
|
||||
|
||||
RTU_EXCEPTION_OK,
|
||||
|
||||
RTU_EXCEPTION_ILLEGAL_FUNCTION,
|
||||
RTU_EXCETPION_ILLEGAL_ADDRESS,
|
||||
RTU_EXCEPTION_ILLEGAL_VALUE,
|
||||
RTU_EXCEPTION_SLAVE_FAIL,
|
||||
RTU_EXCEPTION_ACK,
|
||||
RTU_EXCEPTION_BUSY,
|
||||
RTU_EXCEPTION_NACK,
|
||||
RTU_EXCEPTION_PARITY_ERR,
|
||||
RTU_EXCEPTION_GW_NAVAIBLE,
|
||||
RTU_EXCEPTION_GW_TARGET_NAVAIBLE
|
||||
|
||||
|
||||
} rtu_exception_t;
|
||||
|
||||
inline rtu_exception_t rtu_exception_from_frame_data(uint8_t in) {
|
||||
|
||||
rtu_exception_t out = RTU_EXCEPTION_OK;
|
||||
|
||||
if (in == 0x01) {
|
||||
out = RTU_EXCEPTION_ILLEGAL_FUNCTION;
|
||||
}
|
||||
else if (in == 0x02) {
|
||||
out = RTU_EXCETPION_ILLEGAL_ADDRESS;
|
||||
}
|
||||
else if (in == 0x03) {
|
||||
out = RTU_EXCEPTION_ILLEGAL_VALUE;
|
||||
}
|
||||
else if (in == 0x04) {
|
||||
out = RTU_EXCEPTION_SLAVE_FAIL;
|
||||
}
|
||||
else if (in == 0x05) {
|
||||
out = RTU_EXCEPTION_ACK;
|
||||
}
|
||||
else if (in == 0x06) {
|
||||
out = RTU_EXCEPTION_BUSY;
|
||||
}
|
||||
else if (in == 0x07) {
|
||||
out = RTU_EXCEPTION_NACK;
|
||||
}
|
||||
else if (in == 0x08) {
|
||||
out = RTU_EXCEPTION_PARITY_ERR;
|
||||
}
|
||||
else if (in == 0x0A) {
|
||||
out = RTU_EXCEPTION_GW_NAVAIBLE;
|
||||
}
|
||||
else if (in == 0x0B) {
|
||||
out = RTU_EXCEPTION_GW_TARGET_NAVAIBLE;
|
||||
}
|
||||
else {
|
||||
;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif /* INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_ */
|
|
@ -9,9 +9,10 @@
|
|||
#define INCLUDE_MODBUS_RTU_RTU_PARSER_H_
|
||||
|
||||
#include <modbus_rtu/rtu_register_data_t.h>
|
||||
#include <modbus_rtu/rtu_exception_t.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output);
|
||||
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output, rtu_exception_t* exception);
|
||||
|
||||
#endif /* INCLUDE_MODBUS_RTU_RTU_PARSER_H_ */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MODBUS_RTU_MAX_REGISTERS_AT_ONCE 16 // according to RTU standard 125
|
||||
#define MODBUS_RTU_MAX_REGISTERS_AT_ONCE 8 // according to RTU standard 125
|
||||
|
||||
typedef struct __attribute__((packed)) rtu_register_data {
|
||||
|
||||
|
|
|
@ -13,5 +13,6 @@
|
|||
#define MODBUS_RET_TOO_SHORT 1
|
||||
#define MODBUS_RET_WRONG_FUNCTION 2
|
||||
#define MODBUS_RET_REQUEST_GEN_ERR 3
|
||||
#define MODBUS_RET_GOT_EXCEPTION 4
|
||||
|
||||
#endif /* INCLUDE_MODBUS_RTU_RTU_RETURN_VALUES_H_ */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#define MODBUS_RTU_MIN_03_04_RESP_LN 7 // one register to read
|
||||
|
||||
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output) {
|
||||
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output, rtu_exception_t* exception) {
|
||||
uint32_t retval = MODBUS_RET_UNINITIALIZED;
|
||||
|
||||
uint16_t data = 0;
|
||||
|
@ -32,7 +32,7 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
|
|||
}
|
||||
else {
|
||||
// fetch slave address
|
||||
data = *input << 8 | *(input + 1);
|
||||
data = *input;
|
||||
|
||||
// store slave address
|
||||
output->slave_address = data;
|
||||
|
@ -40,8 +40,17 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
|
|||
// fetch function code
|
||||
data = *(input + 1);
|
||||
|
||||
// if the exception flag is set
|
||||
if ((data & 0x80) > 0) {
|
||||
// parse the exception value
|
||||
*exception = rtu_exception_from_frame_data(data);
|
||||
|
||||
// and set the return value
|
||||
retval = MODBUS_RET_GOT_EXCEPTION;
|
||||
}
|
||||
|
||||
// check if the function code is correct or not
|
||||
if (data == 0x03 || data == 0x04) {
|
||||
else if (data == 0x03 || data == 0x04) {
|
||||
// fetch the function result lenght in bytes
|
||||
data = *(input + 2);
|
||||
|
||||
|
|
|
@ -23,6 +23,23 @@
|
|||
|
||||
#define INTERFRAME_SP 20
|
||||
|
||||
|
||||
#ifndef _RTU_SLAVE_LENGHT_1
|
||||
#define _RTU_SLAVE_LENGHT_1 0x1
|
||||
#endif
|
||||
|
||||
#ifndef _RTU_SLAVE_LENGHT_2
|
||||
#define _RTU_SLAVE_LENGHT_2 0x1
|
||||
#endif
|
||||
|
||||
#ifndef _RTU_SLAVE_LENGHT_3
|
||||
#define _RTU_SLAVE_LENGHT_3 0x1
|
||||
#endif
|
||||
|
||||
#ifndef _RTU_SLAVE_LENGHT_4
|
||||
#define _RTU_SLAVE_LENGHT_4 0x1
|
||||
#endif
|
||||
|
||||
typedef enum rtu_pool_state {
|
||||
RTU_POOL_IDLE,
|
||||
RTU_POOL_TRANSMITTING,
|
||||
|
@ -111,7 +128,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
|
|||
|
||||
rte_wx_modbus_rtu_f1.slave_address = _RTU_SLAVE_ID_1;
|
||||
rte_wx_modbus_rtu_f1.base_address = _RTU_SLAVE_ADDR_1;
|
||||
rte_wx_modbus_rtu_f1.number_of_registers = 1;
|
||||
rte_wx_modbus_rtu_f1.number_of_registers = _RTU_SLAVE_LENGHT_1;
|
||||
#endif
|
||||
|
||||
#ifdef _RTU_SLAVE_ID_2
|
||||
|
@ -120,7 +137,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
|
|||
|
||||
rte_wx_modbus_rtu_f2.slave_address = _RTU_SLAVE_ID_2;
|
||||
rte_wx_modbus_rtu_f2.base_address = _RTU_SLAVE_ADDR_2;
|
||||
rte_wx_modbus_rtu_f2.number_of_registers = 1;
|
||||
rte_wx_modbus_rtu_f2.number_of_registers = _RTU_SLAVE_LENGHT_2;
|
||||
#endif
|
||||
|
||||
#ifdef _RTU_SLAVE_ID_3
|
||||
|
@ -129,7 +146,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
|
|||
|
||||
rte_wx_modbus_rtu_f3.slave_address = _RTU_SLAVE_ID_3;
|
||||
rte_wx_modbus_rtu_f3.base_address = _RTU_SLAVE_ADDR_3;
|
||||
rte_wx_modbus_rtu_f3.number_of_registers = 1;
|
||||
rte_wx_modbus_rtu_f3.number_of_registers = _RTU_SLAVE_LENGHT_3;
|
||||
#endif
|
||||
|
||||
#ifdef _RTU_SLAVE_ID_4
|
||||
|
@ -138,7 +155,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
|
|||
|
||||
rte_wx_modbus_rtu_f4.slave_address = _RTU_SLAVE_ID_4;
|
||||
rte_wx_modbus_rtu_f4.base_address = _RTU_SLAVE_ADDR_4;
|
||||
rte_wx_modbus_rtu_f4.number_of_registers = 1;
|
||||
rte_wx_modbus_rtu_f4.number_of_registers = _RTU_SLAVE_LENGHT_4;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -268,12 +285,13 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
|
|||
;
|
||||
}
|
||||
else if (serial_context->srl_rx_state == SRL_RX_DONE) {
|
||||
// parse the response from RTU slave
|
||||
// parse the response from RTU slave // here there is a problem with changing slave address
|
||||
if (queue->function_id[queue->it] == 0x03 || queue->function_id[queue->it] == 0x04) {
|
||||
result = rtu_parser_03_04_registers(
|
||||
serial_context->srl_rx_buf_pointer,
|
||||
serial_context->srl_rx_bytes_counter,
|
||||
((rtu_register_data_t*)queue->function_parameter[queue->it]));
|
||||
((rtu_register_data_t*)queue->function_parameter[queue->it]),
|
||||
&rte_wx_last_modbus_exception);
|
||||
}
|
||||
else {
|
||||
retval = MODBUS_RET_WRONG_FUNCTION;
|
||||
|
@ -287,6 +305,13 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
|
|||
// switch the state to inter-frame silence period
|
||||
rtu_pool = RTU_POOL_WAIT_AFTER_RECEIVE;
|
||||
}
|
||||
else if (result == MODBUS_RET_GOT_EXCEPTION) {
|
||||
// in case of an excetpion store the current timestamp
|
||||
rte_wx_last_modbus_exception_timestamp = main_get_master_time();
|
||||
|
||||
// switch the state to inter-frame silence period
|
||||
rtu_pool = RTU_POOL_WAIT_AFTER_RECEIVE;
|
||||
}
|
||||
else {
|
||||
// Receive error state will switch to the next function
|
||||
rtu_pool = RTU_POOL_RECEIVE_ERROR;
|
||||
|
@ -300,6 +325,8 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
|
|||
// in case of any error during data reception or the serial driver have fallen into unknown & unexpected
|
||||
// state
|
||||
else {
|
||||
rte_wx_last_modbus_rx_error_timestamp = main_get_master_time();
|
||||
|
||||
rtu_pool = RTU_POOL_RECEIVE_ERROR;
|
||||
}
|
||||
break;
|
||||
|
|
Ładowanie…
Reference in New Issue