diff --git a/Modbus/Inc/modbus_config.h b/Modbus/Inc/modbus_config.h index caa8f3e..ac93b0b 100644 --- a/Modbus/Inc/modbus_config.h +++ b/Modbus/Inc/modbus_config.h @@ -41,12 +41,12 @@ // Модули modbus #define MODBUS_ENABLE_SLAVE ///< Включить обработку МАСТЕР режима -//#define MODBUS_ENABLE_MASTER ///< Включить обработку СЛЕЙВ режима +#define MODBUS_ENABLE_MASTER ///< Включить обработку СЛЕЙВ режима #define MODBUS_ENABLE_COILS ///< Включить обработку коилов #define MODBUS_ENABLE_HOLDINGS ///< Включить обработку регистров хранения #define MODBUS_ENABLE_INPUTS ///< Включить обработку входных регистров -#define MODBUS_ENABLE_DEVICE_IDENTIFICATORS ///< Включить обработку идентификаторы устройства +#define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства #define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас diff --git a/Modbus/Src/modbus_coils.c b/Modbus/Src/modbus_coils.c index 8c629a9..f47d872 100644 --- a/Modbus/Src/modbus_coils.c +++ b/Modbus/Src/modbus_coils.c @@ -99,6 +99,12 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta if(modbus_msg == NULL || coil_state == NULL) return 0; + // Проверяем что ответ связан с коилами + if(modbus_msg->Func_Code != MB_R_COILS) + { + return 0; + } + // Проверяем что coil_addr в пределах запрошенного диапазона if(coil_addr < modbus_msg->Addr || coil_addr >= modbus_msg->Addr + modbus_msg->Qnt) return 0; @@ -108,15 +114,19 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta // Вычисляем байт и бит uint8_t byte_index = coil_index / 8; - uint8_t bit_index = coil_index % 8; + uint8_t data_index = coil_index / 16; + uint8_t bit_index = coil_index % 16; // Проверяем что байт существует в данных if(byte_index >= modbus_msg->ByteCnt) return 0; - // Получаем байт и проверяем бит - uint8_t coil_byte = modbus_msg->DATA[byte_index] & 0xFF; - *coil_state = (coil_byte >> bit_index) & 0x01; + // Получаем байт и проверяем бит + if(bit_index < 8) + *coil_state = (modbus_msg->DATA[data_index] >> (bit_index+8)) & 0x01; + else + *coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 0x01; + return 1; } diff --git a/Modbus/Src/modbus_devid.c b/Modbus/Src/modbus_devid.c index 9d08bfb..608d05a 100644 --- a/Modbus/Src/modbus_devid.c +++ b/Modbus/Src/modbus_devid.c @@ -28,6 +28,16 @@ MB_DeviceIdentificationsTypeDef MB_DEVID; ///< Глобальная струк */ int MB_GetNumberOfObjects(RS_MsgTypeDef *modbus_msg) { + if(modbus_msg == NULL) + { + return 0; + } + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + return modbus_msg->DevId.NumbOfObj; } @@ -44,6 +54,12 @@ int MB_FindObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, if((modbus_msg == NULL) || (obj_data == NULL)) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + uint8_t *data = (uint8_t*)modbus_msg->DATA; unsigned ind = 0; @@ -89,6 +105,12 @@ int MB_GetObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, c if((modbus_msg == NULL) || (obj_data == NULL)) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + if(index >= modbus_msg->DevId.NumbOfObj) return 0; diff --git a/Modbus/Src/modbus_diag.c b/Modbus/Src/modbus_diag.c index b0d656d..cb7f9a3 100644 --- a/Modbus/Src/modbus_diag.c +++ b/Modbus/Src/modbus_diag.c @@ -47,6 +47,14 @@ int MB_GetDiagnosticResponse(RS_MsgTypeDef *modbus_msg, uint16_t *data) if(modbus_msg == NULL || data == NULL) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DIAGNOSTIC) + { + return 0; + } + + + *data = modbus_msg->DATA[1]; return 1; } diff --git a/Modbus/Src/modbus_master.c b/Modbus/Src/modbus_master.c index 90cb7dd..a391426 100644 --- a/Modbus/Src/modbus_master.c +++ b/Modbus/Src/modbus_master.c @@ -28,6 +28,14 @@ int MB_GetRegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t * if(modbus_msg == NULL || reg_value == NULL) return 0; + // Проверяем что ответ связан с регистрами + if((modbus_msg->Func_Code != MB_R_DISC_IN) && + (modbus_msg->Func_Code != MB_R_HOLD_REGS) && + (modbus_msg->Func_Code != MB_R_IN_REGS)) + { + return 0; + } + // Проверяем что reg_addr в пределах запрошенного диапазона if(reg_addr < modbus_msg->Addr || reg_addr >= modbus_msg->Addr + modbus_msg->Qnt) return 0; @@ -302,173 +310,173 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe /** @brief Сформировать запрос на чтение коилов */ RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на чтение дискретных регистров */ RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на чтение холдинг регистров */ RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на чтение инпут регистров */ RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на запись одного коила */ RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value) { - RS_MsgTypeDef msg = {slave_addr, MB_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на запись одного регистра */ RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) { - RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0}; + return msg; } /** @brief Сформировать запрос на запись нескольких регистров */ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data) { - RS_MsgTypeDef msg = {slave_addr, MB_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; - - // Calculate byte count and prepare data - uint8_t byte_count = (quantity + 7) / 8; - msg.ByteCnt = byte_count; - - // Copy coil data to message DATA array - for(int i = 0; i < byte_count; i++) { - if(i < DATA_SIZE) { - msg.DATA[i] = coils_data[i]; - } + RS_MsgTypeDef msg = {slave_addr, MB_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + + // Calculate byte count and prepare data + uint8_t byte_count = (quantity + 7) / 8; + msg.ByteCnt = byte_count; + + // Copy coil data to message DATA array + for(int i = 0; i < byte_count; i++) { + if(i < DATA_SIZE) { + msg.DATA[i] = coils_data[i]; } - - return msg; + } + + return msg; } /** @brief Сформировать запрос на запись нескольких коилов */ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data) { - RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; - - msg.ByteCnt = quantity * 2; // Each register is 2 bytes - - // Copy register data to message DATA array - for(int i = 0; i < quantity && i < DATA_SIZE; i++) { - msg.DATA[i] = regs_data[i]; - } - - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + + msg.ByteCnt = quantity * 2; // Each register is 2 bytes + + // Copy register data to message DATA array + for(int i = 0; i < quantity && i < DATA_SIZE; i++) { + msg.DATA[i] = regs_data[i]; + } + + return msg; } //---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ----------- RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DIAGNOSTIC, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DIAGNOSTIC, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; + return msg; } RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000); } RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data); } RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000); } RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000); } RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000); } //---------ИДЕНТИФИКАТОРЫ МОДБАС----------- RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + return msg; } diff --git a/STM32F103_Example/Core/Src/main.c b/STM32F103_Example/Core/Src/main.c index aac0e0d..e0460f5 100644 --- a/STM32F103_Example/Core/Src/main.c +++ b/STM32F103_Example/Core/Src/main.c @@ -56,7 +56,16 @@ void SystemClock_Config(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ - +int coil_to_toggle = 0; +int coil_state = 0; +int coil_real_state = 0; +void master_callback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *msg) +{ + if(MB_GetCoilState(msg, coil_to_toggle, &coil_real_state)) + { + coil_state = coil_real_state; + } +} /* USER CODE END 0 */ /** @@ -94,7 +103,6 @@ int main(void) MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); #ifdef MODBUS_MODE_MASTER MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); - MODBUS_MSG = MB_REQUEST_READ_COILS(1, 0, 10); #else MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); MODBUS_SlaveStart(&hmodbus1, NULL); @@ -105,6 +113,14 @@ int main(void) /* USER CODE BEGIN WHILE */ while (1) { +#ifdef MODBUS_MODE_MASTER + HAL_Delay(1000); + MODBUS_MSG = MB_REQUEST_READ_COILS(1, 0, 5); + MODBUS_MasterRequest(&hmodbus1, &MODBUS_MSG, &master_callback); + HAL_Delay(1000); + MODBUS_MSG = MB_REQUEST_WRITE_SINGLE_COIL(1, coil_to_toggle, !coil_state); + MODBUS_MasterRequest(&hmodbus1, &MODBUS_MSG, &master_callback); +#endif /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/STM32F103_Example/MDK-ARM/Modbus_example.uvoptx b/STM32F103_Example/MDK-ARM/Modbus_example.uvoptx index 6c2043f..273a294 100644 --- a/STM32F103_Example/MDK-ARM/Modbus_example.uvoptx +++ b/STM32F103_Example/MDK-ARM/Modbus_example.uvoptx @@ -145,27 +145,10 @@ 0 ST-LINKIII-KEIL_SWO - -U005600373433510237363934 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131123 -TC8000000 -TT10000000 -TP21 -TDS8000 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL010000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2 + -U005600373433510237363934 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131123 -TC8000000 -TT10000000 -TP21 -TDS8003 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL010000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2 - - - 0 - 0 - 227 - 1 -
134230452
- 0 - 0 - 0 - 0 - 0 - 1 - E:\.WORK\STM32\STM32_Modbus\Modbus\modbus.c - - \\Modbus_example\../../Modbus/modbus.c\227 -
-
+ 0 @@ -175,7 +158,52 @@ 1 1 - RS_Buffer + RS_Buffer,0x10 + + + 2 + 1 + MODBUS_MSG,0x10 + + + 3 + 1 + coil_to_toggle + + + 4 + 1 + coil_real_state + + + 5 + 1 + (uint8_t *)modbus_msg->DATA + + + 6 + 1 + coil_word >> (bit_index+8) + + + 7 + 1 + bit_index+8,0x0A + + + 8 + 1 + modbus_uart_buff[ind] + + + 9 + 1 + msg + + + 10 + 1 + MODBUS_MSG.DATA[0] @@ -227,20 +255,6 @@ - - - System Viewer\DBG - 35903 - - - System Viewer\TIM3 - 35904 - - - System Viewer\USART1 - 35905 - - 1 0