#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 "iap.h" #include "common_gpio.h" #include #include #include #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; eMBParity par; UCHAR mb_addr = gpio_get_mbaddr(); unsigned int stop_bits = 1; const UCHAR ucSlaveID[] = {0xAA, 0xBB, 0xCC}; iap_init(); mb_init_params(); settings_set_modbus_params(settings.com_settings.mb_port); baud = settings_get_mb_baud(&mb_port_settings); par = settings_get_mb_par(&mb_port_settings); 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 // ------------------------------------------------------------------- // // 04 (0x04) Read Input Registers eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) { return MB_ENOREG; } // 03 (0x03) Read Holding Registers // 16 (0x10) Write Multiple registers #if 0 eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) { return MB_ENOREG; } #endif // 17 (0x11) Report Slave ID (Serial Line only) eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ) { return MB_EX_ILLEGAL_FUNCTION; } // чтение/запись значений из нескольких регистров флагов (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 eMBException eMBSetAddrIdCB( UCHAR * pucFrame, USHORT * usLen ) { return MB_EX_ILLEGAL_FUNCTION; } // 0x43 eMBException eMBSetAddrSerialCB( UCHAR * pucFrame, USHORT * usLen ) { return MB_EX_ILLEGAL_FUNCTION; } // 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; }