|
@@ -0,0 +1,415 @@
|
|
|
+#include "at32f403a_407.h"
|
|
|
+#include "common_config.h"
|
|
|
+#include "modbus.h"
|
|
|
+#include "modbus_params.h"
|
|
|
+#include "FreeRTOS.h"
|
|
|
+#include "task.h"
|
|
|
+#include "mb.h"
|
|
|
+#include "mbport.h"
|
|
|
+#include "mbrtu.h"
|
|
|
+#include "tim_delay.h"
|
|
|
+#include "settings_api.h"
|
|
|
+#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
+#include <stdbool.h>
|
|
|
+
|
|
|
+#define REG_HOLDING_START ( 1 )
|
|
|
+#define REG_HOLDING_NREGS ( 5 )
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static USHORT usRegHoldingStart = REG_HOLDING_START;
|
|
|
+extern UCHAR rcvAddress;
|
|
|
+
|
|
|
+//osThreadId modbus_task_handle;
|
|
|
+static void modbus_task(void *params);
|
|
|
+//osThreadId modbus_params_handle;
|
|
|
+static void modbus_params(void *params);
|
|
|
+
|
|
|
+//osTimerId reset_timer_handle;
|
|
|
+//osTimerId settings_timer_handle;
|
|
|
+//osTimerId modbus_timer_handle;
|
|
|
+
|
|
|
+mb_delay_action_t mb_action = MB_NO_ACTION;
|
|
|
+uint8_t new_slave_addr;
|
|
|
+bool mb_package_flag = false;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+void mb_init(void)
|
|
|
+{
|
|
|
+ uint32_t baud = 115200;
|
|
|
+ eMBParity par = MB_PAR_NONE;
|
|
|
+ UCHAR mb_addr = 1;
|
|
|
+ unsigned int stop_bits = 1;
|
|
|
+ const UCHAR ucSlaveID[] = {0xAA, 0xBB, 0xCC};
|
|
|
+
|
|
|
+ mb_init_params();
|
|
|
+
|
|
|
+ settings_set_modbus_params(settings.com_settings.mb_port);
|
|
|
+
|
|
|
+ mb_helper_tim_init(baud);
|
|
|
+ eMBInit(MB_RTU, mb_addr, 4, baud, par, stop_bits);
|
|
|
+ eMBSetSlaveID(0x34, TRUE, ucSlaveID, 3);
|
|
|
+ eMBEnable();
|
|
|
+
|
|
|
+
|
|
|
+ xTaskCreate(modbus_task, "modbus_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
|
|
|
+
|
|
|
+ xTaskCreate(modbus_params, "modbus_params", 4*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
|
|
|
+
|
|
|
+
|
|
|
+#if 0
|
|
|
+ osTimerDef(vResetTimer, modbus_reset);
|
|
|
+ reset_timer_handle = osTimerCreate(osTimer(vResetTimer), osTimerOnce, NULL);
|
|
|
+
|
|
|
+ osTimerDef(vSettingsTimer, settings_timer);
|
|
|
+ settings_timer_handle = osTimerCreate(osTimer(vSettingsTimer), osTimerOnce, NULL);
|
|
|
+
|
|
|
+ osTimerDef(vModbusTimer, modbus_port_timer);
|
|
|
+ modbus_timer_handle = osTimerCreate(osTimer(vModbusTimer), osTimerOnce, NULL);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void modbus_task(void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+
|
|
|
+ for (;;)
|
|
|
+ {
|
|
|
+ eMBPoll();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void modbus_params(void *params)
|
|
|
+{
|
|
|
+ for (;;)
|
|
|
+ {
|
|
|
+ if (mb_action != MB_NO_ACTION)
|
|
|
+ {
|
|
|
+ switch (mb_action)
|
|
|
+ {
|
|
|
+ // Установка нового адреса
|
|
|
+ case MB_CHANGE_ADDR :
|
|
|
+
|
|
|
+ //settings.com_settings.mb_addr = new_slave_addr;
|
|
|
+ eMBSetSlaveAddr(new_slave_addr);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MB_CHANGE_PORT_SETTINGS :
|
|
|
+#if 0
|
|
|
+ osDelay(200);
|
|
|
+ eMBRTUStop();
|
|
|
+ settings_set_modbus_params(temp_modbus_port);
|
|
|
+ settings_init_mb_port(settings.com_settings.mb_addr);
|
|
|
+ MBDBG settings_print_modbus();
|
|
|
+ eMBRTUStart();
|
|
|
+ eMBEnable();
|
|
|
+ mb_package_flag = false;
|
|
|
+ osTimerStart(modbus_timer_handle, 9800);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ // Полное восстановление дефолтных настроек
|
|
|
+ case MB_DEF_SETTINGS :
|
|
|
+#if 0
|
|
|
+ settings_set_default(true);
|
|
|
+ settings_save();
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ // Частичное восстановление дефолтных настроек
|
|
|
+ case MB_PART_DEF_SETTINGS :
|
|
|
+#if 0
|
|
|
+ settings_set_default(false);
|
|
|
+ settings_save();
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ case MB_SAVE_SETTINGS :
|
|
|
+#if 0
|
|
|
+ settings_save();
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MB_SAVE_SYS_SETTINGS :
|
|
|
+#if 0
|
|
|
+ if (set_sys_settings_flag) {
|
|
|
+ memcpy(&sys_settings, &temp_sys_settings, sizeof(sys_settings));
|
|
|
+ sys_settings_save();
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MB_RESET :
|
|
|
+
|
|
|
+ vTaskDelay(100);
|
|
|
+ NVIC_SystemReset();
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default : break;
|
|
|
+ }
|
|
|
+
|
|
|
+ mb_action = MB_NO_ACTION;
|
|
|
+ }
|
|
|
+ vTaskDelay(10);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Отложенная перезагрузка в Bootloader
|
|
|
+void modbus_reset(void const * params)
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ MBDBG printf("Switch to bootloader!\r\n");
|
|
|
+ rtc_set_load_mode(1);
|
|
|
+ HAL_NVIC_SystemReset();
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Запуск таймера на изменение системных настроек
|
|
|
+void settings_timer(void const * params)
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ set_sys_settings_flag = false;
|
|
|
+ psw_ok = false;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Запуск таймера для изменение настроек modbus
|
|
|
+void modbus_port_timer(void const * params)
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ eMBRTUStop();
|
|
|
+
|
|
|
+ // Были транзакции по modbus с новыми настройками.
|
|
|
+ // Нужно сохранить новые настройки.
|
|
|
+ if (mb_package_flag)
|
|
|
+ {
|
|
|
+ settings.com_settings.mb_port = temp_modbus_port;
|
|
|
+ settings_set_modbus_params(settings.com_settings.mb_port);
|
|
|
+ settings_init_mb_port(settings.com_settings.mb_addr);
|
|
|
+ settings_save();
|
|
|
+
|
|
|
+ }
|
|
|
+ // Нужно вернуть старые настройки
|
|
|
+ else
|
|
|
+ {
|
|
|
+ temp_modbus_port = settings.com_settings.mb_port;
|
|
|
+ settings_set_modbus_params(settings.com_settings.mb_port);
|
|
|
+ settings_init_mb_port(settings.com_settings.mb_addr);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ MBDBG settings_print_modbus();
|
|
|
+ eMBRTUStart();
|
|
|
+ eMBEnable();
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+// ------------------------------------------------------------------- //
|
|
|
+// Modbus callback's
|
|
|
+// ------------------------------------------------------------------- //
|
|
|
+
|
|
|
+//
|
|
|
+// 65 (0x41) Read Input Registers
|
|
|
+eMBErrorCode
|
|
|
+eMBUpdateCB( UCHAR * pucFrame, USHORT * usLen)
|
|
|
+{
|
|
|
+ eMBErrorCode eStatus = MB_ENOERR;
|
|
|
+
|
|
|
+ mb_package_flag = true;
|
|
|
+
|
|
|
+ return eStatus;
|
|
|
+}
|
|
|
+
|
|
|
+eMBErrorCode
|
|
|
+eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
|
|
+{
|
|
|
+ return MB_ENOREG;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 03 (0x03) Read Holding Registers
|
|
|
+// чтение N регистров управления и уставок
|
|
|
+// 16 (0x10) Write Multiple registers
|
|
|
+// запись N регистров управления и уставок (0x10)
|
|
|
+eMBErrorCode
|
|
|
+eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
|
|
|
+{
|
|
|
+ eMBErrorCode eStatus = MB_ENOERR;
|
|
|
+
|
|
|
+ int iRegIndex;
|
|
|
+
|
|
|
+ mb_delay_action_t mb_act = MB_NO_ACTION;
|
|
|
+ uint16_t regs_cnt = usNRegs;
|
|
|
+ uint16_t index_param;
|
|
|
+ uint8_t *ptr_buf = pucRegBuffer;
|
|
|
+ uint16_t size;
|
|
|
+#if 0
|
|
|
+ printf("usAddress: 0x%X\r\n", usAddress);
|
|
|
+ printf("usNRegs: %u\r\n", usNRegs);
|
|
|
+ printf("eMode: %u\r\n", eMode);
|
|
|
+ printf("pucRegBuffer :%X\r\n", pucRegBuffer[0]);
|
|
|
+#endif
|
|
|
+ mb_package_flag = true;
|
|
|
+
|
|
|
+ iRegIndex = (int)(usAddress - usRegHoldingStart);
|
|
|
+
|
|
|
+#if 1
|
|
|
+ switch (eMode)
|
|
|
+ {
|
|
|
+ case MB_REG_READ :
|
|
|
+
|
|
|
+ while (regs_cnt)
|
|
|
+ {
|
|
|
+ // Поиск регистра
|
|
|
+ if (!mb_find_param(iRegIndex, &index_param, &size))
|
|
|
+ {
|
|
|
+ return MB_ENOREG; // нет запрашиваемого регистра
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
|
|
|
+ MBDBG printf("reg: %X\r\n", iRegIndex);
|
|
|
+ mb_get_param(ptr_buf, index_param); // Вызов функции записи
|
|
|
+ iRegIndex += size;
|
|
|
+ ptr_buf += 2*size;
|
|
|
+ regs_cnt -= size;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MB_REG_WRITE :
|
|
|
+
|
|
|
+ while (regs_cnt)
|
|
|
+ {
|
|
|
+ // Поиск регистра
|
|
|
+ if (!mb_find_param(iRegIndex, &index_param, &size))
|
|
|
+ {
|
|
|
+ return MB_ENOREG; // нет запрашиваемого регистра
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
|
|
|
+ mb_act = mb_set_param(ptr_buf, index_param); // Вызов функции записи
|
|
|
+
|
|
|
+ if (mb_act != MB_NO_ACTION)
|
|
|
+ mb_action = mb_act;
|
|
|
+
|
|
|
+ iRegIndex += size;
|
|
|
+ ptr_buf += 2*size;
|
|
|
+ regs_cnt -= size;
|
|
|
+
|
|
|
+ if (mb_act == MB_PAS_ERR)
|
|
|
+ return MB_EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ return eStatus;
|
|
|
+}
|
|
|
+
|
|
|
+// 17 (0x11) Report Slave ID (Serial Line only)
|
|
|
+// чтение информации об устройстве (0x11)
|
|
|
+eMBException
|
|
|
+eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ mb_package_flag = true;
|
|
|
+
|
|
|
+ *usLen = mb_get_info(&pucFrame[1]) + 3;
|
|
|
+#endif
|
|
|
+ return MB_EX_NONE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// чтение/запись значений из нескольких регистров флагов (Coil Status).
|
|
|
+// чтения N регистров параметров
|
|
|
+eMBErrorCode
|
|
|
+eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
|
|
|
+{
|
|
|
+ return MB_ENOREG;
|
|
|
+}
|
|
|
+
|
|
|
+eMBErrorCode
|
|
|
+eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
|
|
+{
|
|
|
+ return MB_ENOREG;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 0x42
|
|
|
+// Запрос на изменение адреса
|
|
|
+// Если запрос широковещательный, то нужно проверить присланный ID.
|
|
|
+eMBException
|
|
|
+eMBSetAddrIdCB( UCHAR * pucFrame, USHORT * usLen )
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ mb_package_flag = true;
|
|
|
+
|
|
|
+ if (rcvAddress == MB_ADDRESS_BROADCAST)
|
|
|
+ {
|
|
|
+ if (mb_set_addr_id(&pucFrame[1], &new_slave_addr))
|
|
|
+ mb_action = MB_CHANGE_ADDR;
|
|
|
+ }
|
|
|
+ // Адресный запрос. ID не проверяем
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (mb_set_addr(&pucFrame[1], &new_slave_addr))
|
|
|
+ {
|
|
|
+ pucFrame[1] = new_slave_addr;
|
|
|
+ mb_action = MB_CHANGE_ADDR;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
|
|
|
+ }
|
|
|
+
|
|
|
+ *usLen = 2;
|
|
|
+#endif
|
|
|
+ return MB_EX_NONE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 0x43
|
|
|
+eMBException
|
|
|
+eMBSetAddrSerialCB( UCHAR * pucFrame, USHORT * usLen )
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ mb_package_flag = true;
|
|
|
+
|
|
|
+ if (rcvAddress == MB_ADDRESS_BROADCAST)
|
|
|
+ {
|
|
|
+ if (mb_set_addr_serial(&pucFrame[1], &new_slave_addr))
|
|
|
+ mb_action = MB_CHANGE_ADDR;
|
|
|
+ }
|
|
|
+ // Адресный запрос. ID не проверяем
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (mb_set_addr(&pucFrame[1], &new_slave_addr))
|
|
|
+ {
|
|
|
+ pucFrame[1] = new_slave_addr;
|
|
|
+ mb_action = MB_CHANGE_ADDR;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
|
|
|
+ }
|
|
|
+
|
|
|
+ *usLen = 2;
|
|
|
+#endif
|
|
|
+ return MB_EX_NONE;
|
|
|
+}
|
|
|
+
|