/** ******************************************************************************* * @file modbus.c * @brief Модуль для реализации MODBUS. ******************************************************************************* * @details Файл содержит реализацию функций работы с Modbus. @section mbapi Функции и макросы ### Инициализация: - MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM) - MODBUS_Config() — Конфигурацмя Modbus (ID, Timeout). - MODBUS_SlaveStart() — Запуск Modbus как Slave. - MODBUS_MasterRequest() — Отправить запрос в MODBUS как Master. ### Функции для работы с RS (UART): - RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения. - RS_Response() — Отправка ответа. ******************************************************************************/ #include "modbus.h" /* MODBUS HANDLES */ RS_HandleTypeDef hmodbus1; ///< Default Handle for Modbus RS_MsgTypeDef MODBUS_MSG; ///< Default Message Struct for Modbus static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg); //------------------------------------------------------------------- //-----------------------------FOR USER------------------------------ /** * @brief Инициализация периферии модбас. * @param hmodbus Указатель на хендлер RS * @param huart Указатель на хендлер UART * @param htim Указатель на хендлер TIM * @details Подключает хендлы периферии к hmodbus * Конфигурация выставляется по умолчанию из modbus_config.h */ HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim) { if((hmodbus == NULL) || (huart == NULL)) { return HAL_ERROR; } MB_DeviceInentificationInit(); //-----------SETUP MODBUS------------- // set up modbus: MB_RX_Size_NotConst and Timeout enable hmodbus->ID = MODBUS_DEVICE_ID; hmodbus->sRS_Timeout = MODBUS_TIMEOUT; hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT; // INIT hmodbus->RS_STATUS = RS_Init(hmodbus, huart, htim, 0); RS_EnableReceive(); if(hmodbus->RS_STATUS == RS_OK) return HAL_OK; else return HAL_ERROR; } /** * @brief Программная конфигурация модбас. * @param hmodbus указатель на хендлер RS * @param Timeout Время тишины между двумя байтами после которых перезапускается прием * @param master Режим мастер (пока не сделан) * @details Конфигурирует ID, таймаут и режим hmodbus */ HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master) { if(hmodbus == NULL) { return HAL_ERROR; } if(!master) { if((ID < 1) || (ID > 247)) { return HAL_ERROR; } hmodbus->ID = ID; } else hmodbus->ID = 0; hmodbus->sRS_Timeout = Timeout; if(master) hmodbus->sRS_Mode = RS_MASTER_REQUEST; else hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT; return HAL_OK; } /** * @brief Запуск слейв модбас. * @param hmodbus Указатель на хендлер RS. * @param modbus_msg Указатель на структуру сообщения. (NULL чтобы использовать дефолтную) * @details Конфигурирует ID, таймаут и режим hmodbus */ HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { if(hmodbus == NULL) { return HAL_ERROR; } if(hmodbus->sRS_Mode >= RS_MASTER_MODE_START) { return HAL_ERROR; } MB_DiagnosticsInit(); if(modbus_msg) hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, modbus_msg); else hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, &MODBUS_MSG); if(hmodbus->RS_STATUS == RS_OK) return HAL_OK; else return HAL_ERROR; } /** * @brief Реквест мастера модбас. * @param hmodbus Указатель на хендлер RS. * @param modbus_msg Указатель на структуру сообщения * @details Конфигурирует ID, таймаут и режим hmodbus */ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, void (*pClbk)(RS_HandleTypeDef*, RS_MsgTypeDef*)) { if(hmodbus == NULL) { return HAL_ERROR; } if(modbus_msg == NULL) { return HAL_ERROR; } if(hmodbus->sRS_Mode < RS_MASTER_MODE_START) { return HAL_ERROR; } if(hmodbus->f.RS_Busy) return HAL_BUSY; if(pClbk) // если задан используем пользовательский коллбек hmodbus->pCallback = (void (*)(void*, void*))(pClbk); else // иначе дефолтный hmodbus->pCallback = (void (*)(void*, void*))(&MB_DefaultCallback); hmodbus->RS_STATUS = RS_Transmit_IT(hmodbus, modbus_msg); if(hmodbus->RS_STATUS == RS_OK) return HAL_OK; else return HAL_ERROR; } //------------------------------------------------------------------- //-----------------------------INTERNAL------------------------------ /** * @brief Дефолтный коллбек для мастера. * @param hmodbus Указатель на хендлер RS * @param modbus_msg Указатель на структуру сообщения * @details В этот коллбек попадут все запросы, с NULL-коллбеком */ static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { __NOP(); return; } /* Реализация функций из rs_message.c для протокола */ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { if(hmodbus->sRS_Mode >= RS_MASTER_MODE_START) { return RS_ERR; } return MB_Slave_Response(hmodbus, modbus_msg); } RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) { if(hmodbus->sRS_Mode < RS_MASTER_MODE_START) { return MB_Slave_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff); } else { return MB_Master_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff); } } RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) { if(hmodbus->sRS_Mode < RS_MASTER_MODE_START) { return MB_Slave_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff); } else { return MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff); } }