kopia lustrzana https://github.com/SP8EBC/ParaTNC
few more bugfixes in serial driver and serial crc callback for modbus rtu
rodzic
4756d9c341
commit
3a55ebadcb
|
@ -5,7 +5,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-231650764009955027" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-229988544573987027" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-267504706212265789" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-265842486776297789" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
|
@ -87,6 +87,8 @@ void SysTick_Handler(void) {
|
|||
srl_keep_timeout(main_kiss_srl_ctx_ptr);
|
||||
srl_keep_timeout(main_wx_srl_ctx_ptr);
|
||||
|
||||
srl_keep_tx_delay(main_wx_srl_ctx_ptr);
|
||||
|
||||
i2cKeepTimeout();
|
||||
|
||||
delay_decrement_counter();
|
||||
|
|
|
@ -349,6 +349,7 @@ int main(int argc, char* argv[]){
|
|||
|
||||
srl_init(main_kiss_srl_ctx_ptr, USART1, srl_usart1_rx_buffer, RX_BUFFER_1_LN, srl_usart1_tx_buffer, TX_BUFFER_1_LN, main_target_kiss_baudrate, 1);
|
||||
srl_init(main_wx_srl_ctx_ptr, USART2, srl_usart2_rx_buffer, RX_BUFFER_2_LN, srl_usart2_tx_buffer, TX_BUFFER_2_LN, main_target_wx_baudrate, _RTU_SLAVE_STOP_BITS);
|
||||
srl_switch_tx_delay(main_wx_srl_ctx_ptr, 1);
|
||||
|
||||
main_modbus_rtu_master_enabled = 1;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define SEPARATE_RX_BUFF
|
||||
#define SEPARATE_TX_BUFF
|
||||
|
||||
#define SRL_TX_DELAY_IN_MS 10
|
||||
#define SRL_DEFAULT_RX_TIMEOUT_IN_MS 400
|
||||
|
||||
#define SRL_TIMEOUT_ENABLE 1
|
||||
|
@ -33,10 +34,17 @@ typedef enum srlRxState {
|
|||
typedef enum srlTxState {
|
||||
SRL_TX_NOT_CONFIG,
|
||||
SRL_TX_IDLE,
|
||||
SRL_TX_WAITING,
|
||||
SRL_TXING,
|
||||
SRL_TX_ERROR
|
||||
}srl_tx_state_t;
|
||||
|
||||
typedef enum srl_timeout_mode {
|
||||
SRL_TIMEOUT_OFF,
|
||||
SRL_TIMEOUT_INSTANT,
|
||||
SRL_TIMEOUT_TRIGGERED
|
||||
}srl_timeout_mode_t;
|
||||
|
||||
typedef struct srl_context_t {
|
||||
USART_TypeDef *port;
|
||||
|
||||
|
@ -58,9 +66,11 @@ typedef struct srl_context_t {
|
|||
uint8_t srl_triggered_start;
|
||||
uint8_t srl_triggered_stop;
|
||||
|
||||
uint8_t srl_start_trigger; // znak oznaczaj<61>cy pocz<63>tek istotnych danych do odbebrania
|
||||
uint8_t srl_stop_trigger; // znak oznaczaj<61>cy koniec istotnych danych do odebrania
|
||||
uint8_t srl_start_trigger;
|
||||
uint8_t srl_stop_trigger;
|
||||
|
||||
// temporary storage for reading the 'DR' register during waiting for the first byte
|
||||
// of the protocol data to be received
|
||||
volatile uint8_t srl_garbage_storage;
|
||||
|
||||
uint8_t srl_rx_timeout_enable;
|
||||
|
@ -71,6 +81,15 @@ typedef struct srl_context_t {
|
|||
uint32_t srl_rx_start_time;
|
||||
uint32_t srl_rx_waiting_start_time;
|
||||
|
||||
// this is a time when srl_start_tx or srl_send_data initiated the transfer. If this is set to 0xFFFFFFFF
|
||||
// the transmission will start immediately. If it is set to any other value the transmission
|
||||
// (first and any consecutive byte) will be delayed by value defined by 'SRL_TX_DELAY_IN_MS'.
|
||||
//
|
||||
// This is a workaround of garbage occurring on RS485 bus when TE/RE pin of MAX485 is switched.
|
||||
// A delay will separate this artificial 0xFF (when TE/RE are switched) from the rest of data
|
||||
// what should make Modbus-RTU working again -> this 0xFF will be ignored.
|
||||
uint32_t srl_tx_start_time;
|
||||
|
||||
srl_rx_state_t srl_rx_state;
|
||||
srl_tx_state_t srl_tx_state;
|
||||
|
||||
|
@ -129,6 +148,8 @@ uint8_t srl_receive_data_with_instant_timeout(srl_context_t *ctx, int num, char
|
|||
uint8_t srl_receive_data_with_callback(srl_context_t *ctx, srl_rx_termination_callback_t cbk);
|
||||
uint16_t srl_get_num_bytes_rxed(srl_context_t *ctx);
|
||||
uint8_t* srl_get_rx_buffer(srl_context_t *ctx);
|
||||
void srl_keep_tx_delay(srl_context_t *ctx);
|
||||
void srl_switch_tx_delay(srl_context_t *ctx, uint8_t disable_enable);
|
||||
void srl_keep_timeout(srl_context_t *ctx);
|
||||
void srl_switch_timeout(srl_context_t *ctx, uint8_t disable_enable, uint32_t value);
|
||||
void srl_switch_timeout_for_waiting(srl_context_t *ctx, uint8_t disable_enable);
|
||||
|
|
|
@ -15,8 +15,10 @@ inline uint16_t rtu_crc_stream(uint16_t previous_crc, uint8_t current_data) {
|
|||
|
||||
previous_crc ^= (uint16_t)current_data;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (previous_crc & 1)
|
||||
if (previous_crc & 1) {
|
||||
previous_crc = (previous_crc >> 1);
|
||||
previous_crc = (previous_crc) ^ 0xA001;
|
||||
}
|
||||
else
|
||||
previous_crc = (previous_crc >> 1);
|
||||
}
|
||||
|
|
|
@ -8,23 +8,21 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
int srlBRRegValue = 0x09C4 ; // dla symulacji ---- baudrate 9600bps
|
||||
//int SrlBRRegValue = 0x0209; // dla realnego uk<75><6B>du
|
||||
|
||||
#ifdef SEPARATE_TX_BUFF
|
||||
uint8_t srl_usart1_tx_buffer[TX_BUFFER_1_LN] = {'\0'}; // dane do wys<79>ania do zdalnego urz<72>dzenia
|
||||
uint8_t srl_usart1_tx_buffer[TX_BUFFER_1_LN] = {'\0'};
|
||||
#endif
|
||||
|
||||
#ifdef SEPARATE_RX_BUFF
|
||||
uint8_t srl_usart1_rx_buffer[RX_BUFFER_1_LN] = {'\0'}; // dane odebrane od zdalnego urz<72>dzenia
|
||||
uint8_t srl_usart1_rx_buffer[RX_BUFFER_1_LN] = {'\0'};
|
||||
#endif
|
||||
|
||||
#ifdef SEPARATE_TX_BUFF
|
||||
uint8_t srl_usart2_tx_buffer[TX_BUFFER_2_LN] = {'\0'}; // dane do wys<79>ania do zdalnego urz<72>dzenia
|
||||
uint8_t srl_usart2_tx_buffer[TX_BUFFER_2_LN] = {'\0'};
|
||||
#endif
|
||||
|
||||
#ifdef SEPARATE_RX_BUFF
|
||||
uint8_t srl_usart2_rx_buffer[RX_BUFFER_2_LN] = {'\0'}; // dane odebrane od zdalnego urz<72>dzenia
|
||||
uint8_t srl_usart2_rx_buffer[RX_BUFFER_2_LN] = {'\0'};
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -56,6 +54,8 @@ void srl_init(
|
|||
ctx->te_port = 0;
|
||||
ctx->te_pin = 0;
|
||||
|
||||
ctx->srl_tx_start_time = 0xFFFFFFFFu;
|
||||
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
|
@ -219,20 +219,27 @@ uint8_t srl_start_tx(srl_context_t *ctx, short leng) {
|
|||
ctx->srl_tx_bytes_counter = 1;
|
||||
|
||||
// setting a pointer to transmit buffer to the internal buffer inside the driver
|
||||
ctx->srl_tx_buf_pointer = srl_usart1_tx_buffer;
|
||||
//ctx->srl_tx_buf_pointer = srl_usart1_tx_buffer;
|
||||
|
||||
if (ctx->te_port != 0)
|
||||
GPIO_SetBits(ctx->te_port, ctx->te_pin);
|
||||
|
||||
ctx->port->CR1 |= USART_CR1_TE;
|
||||
ctx->port->SR &= (0xFFFFFFFF ^ USART_SR_TC);
|
||||
ctx->port->DR = ctx->srl_tx_buf_pointer[0];
|
||||
// check if delay should be applied to transmission
|
||||
if (ctx->srl_tx_start_time == 0xFFFFFFFFu) {
|
||||
ctx->port->CR1 |= USART_CR1_TE;
|
||||
ctx->port->SR &= (0xFFFFFFFF ^ USART_SR_TC);
|
||||
ctx->port->DR = ctx->srl_tx_buf_pointer[0];
|
||||
|
||||
ctx->srl_tx_state = SRL_TXING;
|
||||
ctx->srl_tx_state = SRL_TXING;
|
||||
|
||||
ctx->port->CR1 |= USART_CR1_TXEIE; // przerwanie zg<7A>aszane kiedy rejsetr DR jest pusty
|
||||
ctx->port->CR1 |= USART_CR1_TCIE; // przerwanie zg<7A>aszane po transmisji bajtu
|
||||
// je<6A>eli rejestr DR jest nadal pusty
|
||||
ctx->port->CR1 |= USART_CR1_TXEIE;
|
||||
ctx->port->CR1 |= USART_CR1_TCIE;
|
||||
|
||||
}
|
||||
else {
|
||||
ctx->srl_tx_state = SRL_TX_WAITING;
|
||||
ctx->srl_tx_start_time = main_get_master_time();
|
||||
}
|
||||
|
||||
return SRL_OK;
|
||||
}
|
||||
|
@ -479,6 +486,24 @@ void srl_irq_handler(srl_context_t *ctx) {
|
|||
// storing received byte into buffer
|
||||
ctx->srl_rx_buf_pointer[ctx->srl_rx_bytes_counter] = (uint8_t)ctx->port->DR;
|
||||
|
||||
// check if termination callback pointer has been set
|
||||
if (ctx->srl_rx_term != NULL) {
|
||||
// if yes call it
|
||||
stop_rxing = ctx->srl_rx_term( ctx->srl_rx_buf_pointer[ctx->srl_rx_bytes_counter],
|
||||
ctx->srl_rx_buf_pointer,
|
||||
ctx->srl_rx_bytes_counter);
|
||||
|
||||
// and check the return value
|
||||
if (stop_rxing == 1) {
|
||||
// if this was the last byte of transmission switch the state
|
||||
// of receiving part to done
|
||||
ctx->srl_rx_state = SRL_RX_DONE;
|
||||
|
||||
ctx->srl_triggered_stop = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// checking if this byte in stream holds the protocol information about
|
||||
// how many bytes needs to be received.
|
||||
if (ctx->srl_rx_lenght_param_addres == ctx->srl_rx_bytes_counter) {
|
||||
|
@ -500,23 +525,6 @@ void srl_irq_handler(srl_context_t *ctx) {
|
|||
// moving buffer pointer forward
|
||||
ctx->srl_rx_bytes_counter++;
|
||||
|
||||
// check if termination callback pointer has been set
|
||||
if (ctx->srl_rx_term != NULL) {
|
||||
// if yes call it
|
||||
stop_rxing = ctx->srl_rx_term( ctx->srl_rx_buf_pointer[ctx->srl_rx_bytes_counter],
|
||||
ctx->srl_rx_buf_pointer,
|
||||
ctx->srl_rx_bytes_counter);
|
||||
|
||||
// and check the return value
|
||||
if (stop_rxing == 1) {
|
||||
// if this was the last byte of transmission switch the state
|
||||
// of receiving part to done
|
||||
ctx->srl_rx_state = SRL_RX_DONE;
|
||||
|
||||
ctx->srl_triggered_stop = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if the user want the driver to stop receiving after certain is received
|
||||
|
@ -632,6 +640,46 @@ uint8_t* srl_get_rx_buffer(srl_context_t *ctx) {
|
|||
return ctx->srl_rx_buf_pointer;
|
||||
}
|
||||
|
||||
void srl_keep_tx_delay(srl_context_t *ctx) {
|
||||
if (ctx != 0) {
|
||||
|
||||
// check if pre tx delay is enabled by an user
|
||||
if (ctx->srl_tx_start_time != 0xFFFFFFFFu) {
|
||||
|
||||
// if it is enabled then check if the serial port is currently set to waiting state
|
||||
if (ctx->srl_tx_state == SRL_TX_WAITING) {
|
||||
|
||||
// check if a delay has expired
|
||||
if (main_get_master_time() - ctx->srl_tx_start_time >= SRL_TX_DELAY_IN_MS) {
|
||||
|
||||
// if yes start the transmission
|
||||
ctx->port->CR1 |= USART_CR1_TE;
|
||||
ctx->port->SR &= (0xFFFFFFFF ^ USART_SR_TC);
|
||||
ctx->port->DR = ctx->srl_tx_buf_pointer[0];
|
||||
|
||||
ctx->srl_tx_state = SRL_TXING;
|
||||
|
||||
ctx->port->CR1 |= USART_CR1_TXEIE;
|
||||
ctx->port->CR1 |= USART_CR1_TCIE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void srl_switch_tx_delay(srl_context_t *ctx, uint8_t disable_enable) {
|
||||
if (ctx != 0) {
|
||||
|
||||
if (disable_enable == 1) {
|
||||
ctx->srl_tx_start_time = 0x0u;
|
||||
}
|
||||
else {
|
||||
ctx->srl_tx_start_time = 0xFFFFFFFFu;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void srl_switch_timeout(srl_context_t *ctx, uint8_t disable_enable, uint32_t value) {
|
||||
if (disable_enable == 1)
|
||||
ctx->srl_rx_timeout_enable = 1;
|
||||
|
|
|
@ -16,7 +16,7 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
|
|||
uint16_t data = 0;
|
||||
|
||||
// iterator through input table and registers table
|
||||
int i = 0, j = 6;
|
||||
int i = 0, j = 4;
|
||||
|
||||
// 7 bytes is the shortest meaningful Modbus RTU frame
|
||||
// with a value of single register
|
||||
|
@ -31,12 +31,12 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
|
|||
output->slave_address = data;
|
||||
|
||||
// fetch function code
|
||||
data = *(input + 2) << 8 | *(input + 3);
|
||||
data = *(input + 2);
|
||||
|
||||
// check if the function code is correct or not
|
||||
if (data == 0x03 || data == 0x04) {
|
||||
// fetch the function result lenght in bytes
|
||||
data = *(input + 4) << 8 | *(input + 5);
|
||||
data = *(input + 3);
|
||||
|
||||
// store amount of registers in this response
|
||||
output->number_of_registers = data / 2;
|
||||
|
@ -49,6 +49,8 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
|
|||
j += 2;
|
||||
}
|
||||
|
||||
retval = MODBUS_RET_OK;
|
||||
|
||||
}
|
||||
else {
|
||||
// if not exit with an error as this isn't
|
||||
|
|
|
@ -34,6 +34,9 @@ typedef enum rtu_pool_state {
|
|||
|
||||
rtu_pool_state_t rtu_pool = RTU_POOL_STOP;
|
||||
|
||||
/**
|
||||
* Timestamp of last received modbus RTU response with good CRC
|
||||
*/
|
||||
uint32_t rtu_time_of_last_receive = 0;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +45,14 @@ uint32_t rtu_time_of_last_receive = 0;
|
|||
uint16_t rtu_serial_previous_crc = 0xFFFF;
|
||||
|
||||
/**
|
||||
* A callback for stream CRC calculation
|
||||
* Cleared by 'rtu_serial_callback' when first byte from range 0x1..0xF7 is received
|
||||
*/
|
||||
uint8_t rtu_waiting_for_slave_addr = 0x1;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The callback for stream CRC calculation
|
||||
*/
|
||||
uint8_t rtu_serial_callback(uint8_t current_data, const uint8_t * const rx_buffer, uint16_t rx_bytes_counter) {
|
||||
|
||||
|
@ -50,17 +60,36 @@ uint8_t rtu_serial_callback(uint8_t current_data, const uint8_t * const rx_buffe
|
|||
|
||||
uint16_t new_crc = 0;
|
||||
|
||||
// calculate new crc
|
||||
new_crc = rtu_crc_stream(rtu_serial_previous_crc, current_data);
|
||||
// check if the callback still waits for first 'valid' byte to be received from RTU slave
|
||||
if (rtu_waiting_for_slave_addr == 0x1) {
|
||||
|
||||
// if the new CRC value equals 0x0000 it means that this was MSB
|
||||
// of CRC from correctly received Modbus-RTU frame
|
||||
if (new_crc == 0) {
|
||||
// return '1' to terminate the transmission
|
||||
retval = 1;
|
||||
// check if the byte which was received from the slave is valid address
|
||||
if (current_data >= 0x01 && current_data <= 0xF7) {
|
||||
// clear this flag to start CRC calculation and data receiving
|
||||
rtu_waiting_for_slave_addr = 0;
|
||||
}
|
||||
else {
|
||||
// RTU slave cannot respond with the broadcast address (0x00), also 0xF8..0xFF
|
||||
// are not valid RTU address
|
||||
;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rtu_serial_previous_crc = new_crc;
|
||||
|
||||
// the second 'if' clause checks if the slave response has began
|
||||
if (rtu_waiting_for_slave_addr == 0x0) {
|
||||
|
||||
// calculate new crc
|
||||
new_crc = rtu_crc_stream(rtu_serial_previous_crc, current_data);
|
||||
|
||||
// if the new CRC value equals 0x0000 it means that this was MSB
|
||||
// of CRC from correctly received Modbus-RTU frame
|
||||
if (new_crc == 0) {
|
||||
// return '1' to terminate the transmission
|
||||
retval = 1;
|
||||
}
|
||||
else {
|
||||
rtu_serial_previous_crc = new_crc;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -179,6 +208,8 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
|
|||
|
||||
rtu_serial_previous_crc = 0xFFFF;
|
||||
|
||||
rtu_waiting_for_slave_addr = 1;
|
||||
|
||||
// if serial transmission has been starter
|
||||
if (result == SRL_OK) {
|
||||
// proceed to the next state (transmitting)
|
||||
|
@ -200,13 +231,14 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
|
|||
case RTU_POOL_TRANSMITTING: {
|
||||
|
||||
// if transmission is still pending
|
||||
if (serial_context->srl_tx_state == SRL_TXING) {
|
||||
if (serial_context->srl_tx_state == SRL_TXING || serial_context->srl_tx_state == SRL_TX_WAITING) {
|
||||
// wait until it will finish
|
||||
;
|
||||
}
|
||||
else {
|
||||
// trigger reception
|
||||
srl_receive_data_with_callback(serial_context, rtu_serial_callback);
|
||||
//srl_receive_data(serial_context, 8, 0, 0, 0, 0, 0);
|
||||
|
||||
// switch the state
|
||||
rtu_pool = RTU_POOL_RECEIVING;
|
||||
|
|
Ładowanie…
Reference in New Issue