diff --git a/Inc/modbus.h b/Inc/modbus.h index 7613ffa..329474e 100644 --- a/Inc/modbus.h +++ b/Inc/modbus.h @@ -29,7 +29,7 @@ //----------------Слейв модбас----------------// #include "modbus.h" - MODBUS_FirstInit(&hmodbus1, &huart1, &htim3, NULL); + MODBUS_FirstInit(&hmodbus1, &huart1, &htim3, NULL); // NULL, если управление RE/DE не нужно MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); MODBUS_SlaveStart(&hmodbus1, NULL); @endcode @@ -37,19 +37,24 @@ //----------------Мастер модбас----------------// #include "modbus.h" - MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); + MODBUS_FirstInit(&hmodbus1, &huart1, &htim3, NULL); // NULL, если управление RE/DE не нужно MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); + // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук + // При получении ответа вызовется функция callback_func() RS_MsgTypeDef msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func); void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { // MB_RespGet_... Чтобы достать нужные данные из ответа - if(hmodbus->RS_STATUS == RS_OK) + + + if(hmodbus->RS_STATUS == RS_OK) // Получен ответ без ошибок { for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) { + // Запись регистров из ответа в массив uint16_t value; if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) { @@ -57,6 +62,9 @@ } } } + else // Ответ получен с ошибкой или не получен вовсе + { + } } @endcode diff --git a/Inc/modbus_holdregs.h b/Inc/modbus_holdregs.h index 45cf0ad..d631422 100644 --- a/Inc/modbus_holdregs.h +++ b/Inc/modbus_holdregs.h @@ -3,9 +3,9 @@ * @file modbus_holdregs.h * @brief Работа с регистрами хранения Modbus ******************************************************************************* -@addtogroup MODBUS_INS Input Register Tools +@addtogroup MODBUS_HOLD Holding Registers Tools @ingroup MODBUS_INTERNAL -@brief Функции для работы с входными регистрами +@brief Функции для работы с регистрами хранения ******************************************************************************* * @details Модуль для доступа к регистрам внутри программы: diff --git a/Inc/modbus_inputregs.h b/Inc/modbus_inputregs.h index bcfcd22..a0e9fc1 100644 --- a/Inc/modbus_inputregs.h +++ b/Inc/modbus_inputregs.h @@ -3,9 +3,9 @@ * @file modbus_inputregs.h * @brief Работа с входными регистрами Modbus ******************************************************************************* -@addtogroup MODBUS_HOLD Holding Registers Tools +@addtogroup MODBUS_INS Input Register Tools @ingroup MODBUS_INTERNAL -@brief Функции для работы с регистрами хранения +@brief Функции для работы с входными регистрами ******************************************************************************* * @details Модуль для доступа к регистрам внутри программы: diff --git a/README.md b/README.md index b20d31b..ca03f7e 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,29 @@ Modbus/ │ inc/ modbus │ ├── modbus.h # Главный заголовочный файл modbus_slave │ ├── modbus_core.h # Базовые определения и структуры modbus_master -│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils +│ ├── modbus_coils.h # Работа с дискретными коилами ├── modbus_coils │ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs │ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs -│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid -│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag -├── src/ └── rs_message -│ ├── modbus.c # Основная логика Modbus │ -│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро) -│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config -│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data -│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs -│ ├── modbus_inputregs.c # Реализация входных регистров -│ ├── modbus_devid.c # Реализация идентификации устройства -│ ├── modbus_data.c # Функции доступа к данным +│ ├── modbus_devid.h # Идентификаторы устройства ├── modbus_devid +│ ├── modbus_master.h # Заголовочный файл Master режима ├── modbus_diag +│ ├── modbus_slave.h # Заголовочный файл Slave режима ├── modbus_oscil +│ ├── modbus_diag.h # Диагностика Modbus └── rs_message +│ ├── modbus_oscil.h # Осциллографирование данных │ +│ └── rs_message.h # Драйвер обмена по RS/UART └── modbus_core (единое ядро) +├── src/ ├── modbus_config +│ ├── modbus.c # Основная логика Modbus ├── modbus_data +│ ├── modbus_slave.c # Основная логика Slave Modbus └── __crc_algs +│ ├── modbus_master.c # Основная логика Master Modbus +│ ├── modbus_coils.c # Реализация работы с coils +│ ├── modbus_holdregs.c # Реализация регистров хранения +│ ├── modbus_inputregs.c # Реализация входных регистров +│ ├── modbus_devid.c # Реализация идентификации устройства +│ ├── modbus_diag.c # Диагностические функции и счетчики ошибок +│ ├── modbus_oscil.c # Сбор и хранение осциллограмм │ └── rs_message.c # Реализация драйвера RS ├── __modbus_config.h # Конфигурация Modbus (надо заменить) ├── __modbus_data.h # Структуры данных (надо заменить) -└── __modbus_data.c # Функции доступа (надо заменить) +└── __modbus_data.c # Функции доступа (надо заменить) ``` ## Инструкция по подключению @@ -97,7 +102,7 @@ int main(void) MX_TIM3_Init(); // Инициализация Modbus - MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); + MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim, SetTxDirectionFunc); MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); // Запуск приема Modbus @@ -113,25 +118,40 @@ int main(void) ```c #include "modbus.h" + +// Инициализация Modbus +MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim, SetTxDirectionFunc); +MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); + + // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук -RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); +// При получении ответа вызовется функция callback_func() +RS_MsgTypeDef msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); +MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func); + // коллбек, вызовется при получении ответа от слейва read_hold[10]; void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { // MB_RespGet_... Чтобы достать нужные данные из ответа - if(hmodbus->RS_STATUS == RS_OK) + + if(hmodbus->RS_STATUS == RS_OK) // Получен ответ без ошибок { for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) { - uint16_t value; - if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) - { - read_hold[i] = value; - } + // Запись регистров из ответа в массив + uint16_t value; + if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) + { + read_hold[i] = value; + } } } + else // Ответ получен с ошибкой или не получен вовсе + { + } } + int main(void) { // Инициализация HAL @@ -150,7 +170,7 @@ int main(void) } ``` - #### 3.5. Настройка карты данных + #### 3.5. Настройка карты данных (только для режима Slave) В `modbus_data.h` настройте регистры и coils под ваше устройство: @@ -195,7 +215,7 @@ typedef struct ``` #### 3.6. Доступ к данным в коде - В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля + В режиме **слейва** есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля ```c // Чтение входных регистров uint16_t temp = MB_DATA.InRegs.Temperature; @@ -204,15 +224,15 @@ uint16_t temp = MB_DATA.InRegs.Temperature; MB_DATA.HoldRegs.SetpointTemp = 2500; // Управление coils -MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1 -MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2 +MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить 0 бит в Coils +MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить 1 бит в Coils // Чтение coil if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) { // Pump включен } ``` - В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()` + В режиме **мастера** есть функции для получения информации из ответа `MB_RespGet_...()` ```c // Чтение регистров: Получить запрошенные регистры uint16_t value; diff --git a/__modbus_config.h b/__modbus_config.h index 9f65c31..a5c2450 100644 --- a/__modbus_config.h +++ b/__modbus_config.h @@ -40,8 +40,6 @@ // Периферия (опционально) #define mb_huart huart1 ///< Удобный дефайн для модбасовского uart #define mb_htim htim3 ///< Удобный дефайн для модбасовского таймера -//#define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485 -//#define RS_EnableTransmit() ///< Функция изменения направления передачи на ПЕРЕДАЧУ для RS-485 // Модули modbus @@ -54,10 +52,12 @@ #define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства #define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас + +#define MODBUS_ENABLE_OSCIL ///< Включить осциллограф Modbus //#define MODBUS_PROTOCOL_TCP ///< Включить TCP-протокол, иначе - RTU /** - * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) + * @brief Поменять комманды 0x03 и 0x04 местами * @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS * Поэтому чтобы считывать Input Regs - надо поменять их местами. */ diff --git a/__modbus_data.c b/__modbus_data.c index a333a82..5f1d2ca 100644 --- a/__modbus_data.c +++ b/__modbus_data.c @@ -80,6 +80,13 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u { *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр } +#if defined(MODBUS_ENABLE_OSCIL) && defined(R_HOLDING_OSCIL_ADDR) && defined(R_HOLDING_OSCIL_QNT) + else if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_OSCIL_ADDR, R_HOLDING_OSCIL_QNT) == ET_NO_ERRORS) + { + local_addr = Addr - R_HOLDING_OSCIL_ADDR; + *pRegs = MB_Set_Register_Ptr(&MB_INTERNAL.oscil , local_addr); // указатель на выбранный по Addr регистр + } +#endif // if address doesnt match any array - return illegal data address response else {