From 81d95635f938d60c6dabc2dab75208824d8fd0c0 Mon Sep 17 00:00:00 2001 From: andrey Date: Fri, 7 Nov 2025 16:22:00 +0300 Subject: [PATCH] comit_job ver new modbus --- .gitmodules | 4 + core/STM32_Modbus | 1 + john103C6T6/Core/Inc/main.h | 5 +- john103C6T6/Core/Src/main.c | 139 ++-- john103C6T6/Core/Src/stm32f1xx_it.c | 16 +- john103C6T6/Core/Src/tim.c | 2 +- john103C6T6/MDK-ARM/john103C6T6.uvoptx | 372 +++++---- john103C6T6/MDK-ARM/john103C6T6.uvprojx | 91 ++- john103C6T6/Modbus/crc_algs.c | 116 --- john103C6T6/Modbus/crc_algs.h | 9 - john103C6T6/Modbus/modbus.c | 970 ------------------------ john103C6T6/Modbus/modbus.h | 383 ---------- john103C6T6/Modbus/modbus_config.h | 69 +- john103C6T6/Modbus/modbus_data.c | 141 ++++ john103C6T6/Modbus/modbus_data.h | 37 +- john103C6T6/Modbus/rs_message.c | 566 -------------- john103C6T6/Modbus/rs_message.h | 259 ------- 17 files changed, 564 insertions(+), 2616 deletions(-) create mode 160000 core/STM32_Modbus delete mode 100644 john103C6T6/Modbus/crc_algs.c delete mode 100644 john103C6T6/Modbus/crc_algs.h delete mode 100644 john103C6T6/Modbus/modbus.c delete mode 100644 john103C6T6/Modbus/modbus.h create mode 100644 john103C6T6/Modbus/modbus_data.c delete mode 100644 john103C6T6/Modbus/rs_message.c delete mode 100644 john103C6T6/Modbus/rs_message.h diff --git a/.gitmodules b/.gitmodules index 56184dd..72cf83c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,7 @@ path = labview_proj url = https://git.arktika.cyou/Andrey/labview_proj.git branch = master +[submodule "core/STM32_Modbus"] + path = core/STM32_Modbus + url = https://git.arktika.cyou/set506/STM32_Modbus.git + branch = release diff --git a/core/STM32_Modbus b/core/STM32_Modbus new file mode 160000 index 0000000..cba1380 --- /dev/null +++ b/core/STM32_Modbus @@ -0,0 +1 @@ +Subproject commit cba13802b11fd15013b96e8465b70415f969c946 diff --git a/john103C6T6/Core/Inc/main.h b/john103C6T6/Core/Inc/main.h index 6389314..ecf574a 100644 --- a/john103C6T6/Core/Inc/main.h +++ b/john103C6T6/Core/Inc/main.h @@ -100,13 +100,14 @@ typedef struct { extern void handle_command(char* cmd); typedef void (*FunctionPointer)(void); -uint16_t handle_valves(TEMP_TypeDef* tmp_sense); -void init_setpoint_all_T_sense(void); +uint16_t handle_valves(TEMP_TypeDef* temp_sense[MAX_SENSE]); +void init_setpoint_all_T_sense(TEMP_TypeDef* temp_sense[MAX_SENSE]); void iwdg_refresh(void); void led_blink(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin,uint8_t iter,uint16_t delay); FuncStat Field_modbus(MB_DataStructureTypeDef* MB_DATA, Flags_TypeDef* flag); FuncStat packStruct(MB_DataStructureTypeDef* MB_DATA,int sizeARR); void Check_Tconnect(MB_DataStructureTypeDef* MB_DATA, Flags_TypeDef* flag ,DALLAS_HandleTypeDef* hdallas, int a[50]); +FuncStat value_control(void ); void reinit_t_sens(void); diff --git a/john103C6T6/Core/Src/main.c b/john103C6T6/Core/Src/main.c index a29d86b..2c6580b 100644 --- a/john103C6T6/Core/Src/main.c +++ b/john103C6T6/Core/Src/main.c @@ -40,7 +40,7 @@ #include "def.h" #include -#include "rs_message.h" +#include "modbus.h" #include "eeprom_emul.h" #include "stdio.h" @@ -68,7 +68,7 @@ uint8_t ralay_5v_on_var=0; /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ float temperature; - extern uint8_t roms[MAX_DEVICES][8]; + uint8_t roms[MAX_DEVICES][8]; Flags_TypeDef flag; //extern uint8_t devices_found ; uint8_t _debug_init=0; @@ -143,9 +143,13 @@ int main(void) /* USER CODE BEGIN 2 */ led_blink(GPIOC,13,rest_iter,reset_blink_delay); - MODBUS_FirstInit(); + MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); + MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); + + // Запуск приема Modbus + MODBUS_SlaveStart(&hmodbus1, NULL); uint8_t uart_byte = 0; - RS_Receive_IT(&hmodbus1, &MODBUS_MSG); + Dallas_BusFirstInit(&htim1); // ������������� �� ������� ��������� �������� // ������������� �� ������� (����������� ������ ���������� �������) @@ -162,7 +166,7 @@ int main(void) - if( hmodbus1.pMessagePtr->Func_Code&ERR_VALUES_START) + if( hmodbus1.pMessagePtr->FuncCode&FC_ERR_VALUES_START) { static int pause_Alarm_led; while (1) @@ -221,32 +225,8 @@ int main(void) { GPIOA->ODR&=~(1<<10); } - -//// if (sens[i].temperaturesens[i].set_temp+sens[i].hyst) -//// { -//// -//// MB_DATA.Coils.coils[0].all&=~(1<ODR|=1<<11; -//// } -//// else -//// { -//// GPIOB->ODR&=~(1<<11); -//// -//// } + value_control(); + } @@ -435,39 +415,74 @@ FuncStat Field_modbus(MB_DataStructureTypeDef* MB_DATA, Flags_TypeDef* flag) }; +FuncStat value_control(void ) + { + + for(int i=0;i<10;i++) + { + if (sens[i].temperaturesens[i].set_temp+sens[i].hyst) + { + + MB_DATA.Coils.coils[0].all&=~(1<ODR|=1<<11; + } + else + { + GPIOB->ODR&=~(1<<11); + + } + + + } + return FuncOK; + } + +uint16_t handle_valves(TEMP_TypeDef* temp_sense[MAX_SENSE] ) +{ + + if (temp_sense[0]->state==STATE_OPEN_VALVE) + { + GPIOC->ODR|=1<<14; + } + else + if (temp_sense[0]->state==STATE_CLOSE_VALVE) + { + GPIOC->ODR&=~(1<<14); + } + + return 1; + +} -//uint16_t handle_valves(TEMP_TypeDef* tmp_sense ) -//{ -// -// if (temp_sense[0].state==STATE_OPEN_VALVE) -// { -// GPIOC->ODR|=1<<14; -// } -// else -// if (temp_sense[0].state==STATE_CLOSE_VALVE) -// { -// GPIOC->ODR&=~(1<<14); -// } -// -// return 1; -// -//} - -//void init_setpoint _all_T_sense(void) -//{ -// //ds_search_devices(); -// for(int i=0;iRomCnt;i++) -//{ -// temp_sense[i].id[0]=roms[i][0]<<0|roms[i][1]<<8|roms[i][2]<<16|roms[i][3]<<24; -// temp_sense[i].id[1]=roms[i][4]<<0|roms[i][5]<<8|roms[i][6]<<16|roms[i][7]<<24; -// temp_sense[i].count =i+1; -// temp_sense[i].location=1; -// temp_sense[i].t_open=22; -// temp_sense[i].t_close=18; -// temp_sense[i].status_T_sense=1; -//} -//} +void init_setpoint_all_T_sense(TEMP_TypeDef* temp_sense[MAX_SENSE]) +{ + //ds_search_devices(); + for(int i=0;iRomCnt;i++) +{ + temp_sense[i]->id[0]=roms[i][0]<<0|roms[i][1]<<8|roms[i][2]<<16|roms[i][3]<<24; + temp_sense[i]->id[1]=roms[i][4]<<0|roms[i][5]<<8|roms[i][6]<<16|roms[i][7]<<24; + temp_sense[i]->count =i+1; + temp_sense[i]->location=1; + temp_sense[i]->t_open=22; + temp_sense[i]->t_close=18; + temp_sense[i]->status_T_sense=1; +} +} /* USER CODE END 4 */ /** diff --git a/john103C6T6/Core/Src/stm32f1xx_it.c b/john103C6T6/Core/Src/stm32f1xx_it.c index 88c4479..3ba5380 100644 --- a/john103C6T6/Core/Src/stm32f1xx_it.c +++ b/john103C6T6/Core/Src/stm32f1xx_it.c @@ -22,7 +22,7 @@ #include "stm32f1xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - #include "rs_message.h" + #include "modbus.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -281,11 +281,12 @@ void TIM1_CC_IRQHandler(void) void TIM2_IRQHandler(void) { /* USER CODE BEGIN TIM2_IRQn 0 */ - + RS_TIM_Handler(&hmodbus1); + return; /* USER CODE END TIM2_IRQn 0 */ HAL_TIM_IRQHandler(&htim2); /* USER CODE BEGIN TIM2_IRQn 1 */ -// RS_TIM_Handler(&hmodbus1); + //RS_TIM_Handler(&hmodbus1); /* USER CODE END TIM2_IRQn 1 */ } @@ -313,15 +314,12 @@ static uint8_t first_in=1; void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ -if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) - { - __HAL_UART_CLEAR_IDLEFLAG(&huart1); - RS_TIM_Handler(&hmodbus1); - } +RS_UART_Handler(&hmodbus1); + return; /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ - RS_UART_Handler(&hmodbus1); + //RS_UART_Handler(&hmodbus1); /* USER CODE END USART1_IRQn 1 */ diff --git a/john103C6T6/Core/Src/tim.c b/john103C6T6/Core/Src/tim.c index ddc37f6..2c78e95 100644 --- a/john103C6T6/Core/Src/tim.c +++ b/john103C6T6/Core/Src/tim.c @@ -83,7 +83,7 @@ void MX_TIM2_Init(void) /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; - htim2.Init.Prescaler = 7199; + htim2.Init.Prescaler = 72-1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; diff --git a/john103C6T6/MDK-ARM/john103C6T6.uvoptx b/john103C6T6/MDK-ARM/john103C6T6.uvoptx index ac12308..456aea0 100644 --- a/john103C6T6/MDK-ARM/john103C6T6.uvoptx +++ b/john103C6T6/MDK-ARM/john103C6T6.uvoptx @@ -125,7 +125,7 @@ 0 ST-LINKIII-KEIL_SWO - -U37FF71064E57343634C31443 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2 + -U002400343233511639363634 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2 0 @@ -148,118 +148,30 @@ (105=-1,-1,-1,-1,0) - - - 0 - 0 - 171 - 1 -
134247538
- 0 - 0 - 0 - 0 - 0 - 1 - ../Core/Src/main.c - - \\john103C6T6\../Core/Src/main.c\171 -
- - 1 - 0 - 173 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - ../Core/Src/main.c - - -
-
+ 0 1 - sens,0x0A + hiwdg 1 1 - hdallas,0x10 + DS18B20_DEVICE_AMOUNT 2 1 - DS + set_temp_old 3 1 - hmodbus1 - - - 4 - 1 - hiwdg - - - 5 - 1 - OW - - - 6 - 1 - _debug_init - - - 7 - 1 - htim1,0x0A - - - 8 - 1 - DS18B20_DEVICE_AMOUNT - - - 9 - 1 - set_temp_old - - - 10 - 1 - \\john103C6T6\../Modbus/modbus.c\MB_DATA,0x0A - - - 11 - 1 sTime - 12 - 1 - RS_Buffer - - - 13 - 1 - MODBUS_MSG - - - 14 - 1 - flag,0x0A - - - 15 + 4 1 sens[sens_num] @@ -273,7 +185,7 @@ 1 2 - init_sens,0x0A + hmodbus1 @@ -348,7 +260,7 @@ Application/MDK-ARM - 0 + 1 0 0 0 @@ -427,42 +339,6 @@ 0 0 0 - ..\Modbus\crc_algs.c - crc_algs.c - 0 - 0 - - - 2 - 7 - 1 - 0 - 0 - 0 - ..\Modbus\modbus.c - modbus.c - 0 - 0 - - - 2 - 8 - 1 - 0 - 0 - 0 - ..\Modbus\rs_message.c - rs_message.c - 0 - 0 - - - 2 - 9 - 1 - 0 - 0 - 0 ../Core/Src/main.c main.c 0 @@ -470,7 +346,7 @@ 2 - 10 + 7 1 0 0 @@ -482,7 +358,7 @@ 2 - 11 + 8 1 0 0 @@ -494,7 +370,7 @@ 2 - 12 + 9 1 0 0 @@ -506,7 +382,7 @@ 2 - 13 + 10 1 0 0 @@ -518,7 +394,7 @@ 2 - 14 + 11 1 0 0 @@ -530,7 +406,7 @@ 2 - 15 + 12 1 0 0 @@ -542,7 +418,7 @@ 2 - 16 + 13 1 0 0 @@ -554,7 +430,7 @@ 2 - 17 + 14 1 0 0 @@ -566,7 +442,7 @@ 2 - 18 + 15 1 0 0 @@ -578,7 +454,7 @@ 2 - 19 + 16 1 0 0 @@ -590,7 +466,7 @@ 2 - 20 + 17 1 0 0 @@ -602,7 +478,7 @@ 2 - 21 + 18 1 0 0 @@ -622,7 +498,7 @@ 0 3 - 22 + 19 1 0 0 @@ -634,7 +510,7 @@ 3 - 23 + 20 1 0 0 @@ -646,7 +522,7 @@ 3 - 24 + 21 1 0 0 @@ -658,7 +534,7 @@ 3 - 25 + 22 1 0 0 @@ -670,7 +546,7 @@ 3 - 26 + 23 1 0 0 @@ -682,7 +558,7 @@ 3 - 27 + 24 1 0 0 @@ -694,7 +570,7 @@ 3 - 28 + 25 1 0 0 @@ -706,7 +582,7 @@ 3 - 29 + 26 1 0 0 @@ -718,7 +594,7 @@ 3 - 30 + 27 1 0 0 @@ -730,7 +606,7 @@ 3 - 31 + 28 1 0 0 @@ -742,7 +618,7 @@ 3 - 32 + 29 1 0 0 @@ -754,7 +630,7 @@ 3 - 33 + 30 1 0 0 @@ -766,7 +642,7 @@ 3 - 34 + 31 1 0 0 @@ -778,7 +654,7 @@ 3 - 35 + 32 1 0 0 @@ -790,7 +666,7 @@ 3 - 36 + 33 1 0 0 @@ -802,7 +678,7 @@ 3 - 37 + 34 1 0 0 @@ -814,7 +690,7 @@ 3 - 38 + 35 1 0 0 @@ -826,7 +702,7 @@ 3 - 39 + 36 1 0 0 @@ -838,7 +714,7 @@ 3 - 40 + 37 1 0 0 @@ -850,7 +726,7 @@ 3 - 41 + 38 1 0 0 @@ -862,7 +738,7 @@ 3 - 42 + 39 1 0 0 @@ -882,7 +758,7 @@ 0 4 - 43 + 40 1 0 0 @@ -894,6 +770,170 @@ + + modbus + 1 + 0 + 0 + 0 + + 5 + 41 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\__crc_algs.c + __crc_algs.c + 0 + 0 + + + 5 + 42 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\__modbus_compat.c + __modbus_compat.c + 0 + 0 + + + 5 + 43 + 1 + 1 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus.c + modbus.c + 0 + 0 + + + 5 + 44 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_coils.c + modbus_coils.c + 0 + 0 + + + 5 + 45 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_core.c + modbus_core.c + 0 + 0 + + + 5 + 46 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_devid.c + modbus_devid.c + 0 + 0 + + + 5 + 47 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_diag.c + modbus_diag.c + 0 + 0 + + + 5 + 48 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_holdregs.c + modbus_holdregs.c + 0 + 0 + + + 5 + 49 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_inputregs.c + modbus_inputregs.c + 0 + 0 + + + 5 + 50 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_master.c + modbus_master.c + 0 + 0 + + + 5 + 51 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\modbus_slave.c + modbus_slave.c + 0 + 0 + + + 5 + 52 + 1 + 0 + 0 + 0 + ..\..\core\STM32_Modbus\Src\rs_message.c + rs_message.c + 0 + 0 + + + 5 + 53 + 1 + 0 + 0 + 0 + ..\Modbus\modbus_data.c + modbus_data.c + 0 + 0 + + + ::CMSIS 0 diff --git a/john103C6T6/MDK-ARM/john103C6T6.uvprojx b/john103C6T6/MDK-ARM/john103C6T6.uvprojx index 460b15f..dbc2d0e 100644 --- a/john103C6T6/MDK-ARM/john103C6T6.uvprojx +++ b/john103C6T6/MDK-ARM/john103C6T6.uvprojx @@ -135,11 +135,11 @@ 0 1 1 - 4101 + 4096 1 BIN\UL2CM3.DLL - + "" () @@ -341,7 +341,7 @@ USE_HAL_DRIVER,STM32F103x6 - ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Modbus;..\EEPROM_Emul\lib + ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Modbus;..\EEPROM_Emul\lib;..\..\core\STM32_Modbus\Inc @@ -415,21 +415,6 @@ 1 ..\Core\Src\ow_port.c - - crc_algs.c - 1 - ..\Modbus\crc_algs.c - - - modbus.c - 1 - ..\Modbus\modbus.c - - - rs_message.c - 1 - ..\Modbus\rs_message.c - main.c 1 @@ -1229,6 +1214,76 @@ + + modbus + + + __crc_algs.c + 1 + ..\..\core\STM32_Modbus\Src\__crc_algs.c + + + __modbus_compat.c + 1 + ..\..\core\STM32_Modbus\Src\__modbus_compat.c + + + modbus.c + 1 + ..\..\core\STM32_Modbus\Src\modbus.c + + + modbus_coils.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_coils.c + + + modbus_core.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_core.c + + + modbus_devid.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_devid.c + + + modbus_diag.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_diag.c + + + modbus_holdregs.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_holdregs.c + + + modbus_inputregs.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_inputregs.c + + + modbus_master.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_master.c + + + modbus_slave.c + 1 + ..\..\core\STM32_Modbus\Src\modbus_slave.c + + + rs_message.c + 1 + ..\..\core\STM32_Modbus\Src\rs_message.c + + + modbus_data.c + 1 + ..\Modbus\modbus_data.c + + + ::CMSIS diff --git a/john103C6T6/Modbus/crc_algs.c b/john103C6T6/Modbus/crc_algs.c deleted file mode 100644 index fcfa779..0000000 --- a/john103C6T6/Modbus/crc_algs.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "crc_algs.h" - - -uint32_t CRC_calc; -uint32_t CRC_ref; - -//uint16_t CRC_calc; -//uint16_t CRC_ref; - - -// left this global for debug -uint8_t uchCRCHi = 0xFF; -uint8_t uchCRCLo = 0xFF; -unsigned uIndex; - - -uint32_t crc32(uint8_t *data, uint32_t data_size) -{ - static const unsigned int crc32_table[] = -{ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; -unsigned int crc = 0xFFFFFFFF; - while (data_size--) - { - crc = (crc >> 8) ^ crc32_table[(crc ^ *data) & 255]; - data++; - } - return crc^0xFFFFFFFF; -} - - -uint16_t crc16(uint8_t *data, uint32_t data_size) -{ - /*Table of CRC values for high order byte*/ - static unsigned char auchCRCHi[]= - { - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, - 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, - }; - /*Table of CRC values for low order byte*/ - static char auchCRCLo[] = - { - 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04, - 0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8, - 0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC, - 0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10, - 0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4, - 0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38, - 0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C, - 0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0, - 0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4, - 0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68, - 0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C, - 0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0, - 0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54, - 0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98, - 0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C, - 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40, - }; - uchCRCHi = 0xFF; - uchCRCLo = 0xFF; - /* CRC Generation Function */ - while( data_size--) /* pass through message buffer */ - { - uIndex = uchCRCHi ^ *data++; /* calculate the CRC */ - uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; - uchCRCLo = auchCRCLo[uIndex]; - } - return uchCRCHi | uchCRCLo<<8; -} diff --git a/john103C6T6/Modbus/crc_algs.h b/john103C6T6/Modbus/crc_algs.h deleted file mode 100644 index 3502d6a..0000000 --- a/john103C6T6/Modbus/crc_algs.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "modbus_config.h" - -// extern here to use in bootloader.c -extern uint32_t CRC_calc; -extern uint32_t CRC_ref; - - -uint16_t crc16(uint8_t *data, uint32_t data_size); -uint32_t crc32(uint8_t *data, uint32_t data_size); diff --git a/john103C6T6/Modbus/modbus.c b/john103C6T6/Modbus/modbus.c deleted file mode 100644 index df8e769..0000000 --- a/john103C6T6/Modbus/modbus.c +++ /dev/null @@ -1,970 +0,0 @@ -/** -************************************************************************** -* @file modbus.c -* @brief Модуль для реализации MODBUS. -************************************************************************** -* @details Файл содержит реализацию функций работы с Modbus, включая: -* - доступ к coils и registers; -* - обработку команд протокола; -* - взаимодействие с RS (UART); -* - инициализацию. -* -* @section Функции и макросы -* -* ### Доступ к coils: -* - MB_Set_Coil_Local() — Установить coil по локальному адресу. -* - MB_Reset_Coil_Local() — Сбросить coil по локальному адресу. -* - MB_Toogle_Coil_Local() — Инвертировать coil по локальному адресу. -* - MB_Read_Coil_Local() — Прочитать coil по локальному адресу. -* - MB_Write_Coil_Global() — Установить/сбросить coil по глобальному адресу. -* - MB_Read_Coil_Global() — Прочитать coil по глобальному адресу. -* -* ### Обработка команд Modbus: -* - MB_DefineRegistersAddress() — Определить начальный адрес регистра. -* - MB_DefineCoilsAddress() — Определить начальный адрес coils. -* - MB_Check_Address_For_Arr() — Проверить, принадлежит ли адрес массиву. -* - Основные команды Modbus: -* - MB_Read_Coils() -* - MB_Read_Hold_Regs() -* - MB_Write_Single_Coil() -* - MB_Write_Miltuple_Coils() -* - MB_Write_Miltuple_Regs() -* -* ### Функции для работы с RS (UART): -* - RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения. -* - RS_Response() — Отправка ответа. -* - RS_Define_Size_of_RX_Message() — Определение размера принимаемого сообщения. -* - RS_Init() — Инициализация UART. -* -* ### Инициализация: -* - MODBUS_FirstInit() — Инициализация модуля Modbus. -* -* @section Структура данных Modbus -* -* #### Holding/Input Registers: -* - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. -* Таким образом, сами регистры могут представлять собой как массив так и структуру. -* -* #### Coils: -* - Coils — это биты, упакованные в 16-битные слова. Доступ к коилам осуществляется через указатель. -* Таким образом, сами коилы могут представлять собой как массив так и структуру. -* -* @section Инструкция по подключению -* Для корректной работы надо подключить обработчики RS_UART_Handler(), RS_TIM_Handler(), -* в соответствубщие низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler. После HAL'овского обработчика -* -* Также необходимо в modbus_config.h настроить дефайны для нужной работы UART -* После для запуска Modbus: -* @verbatim - //----------------Прием модбас----------------// - #include "rs_message.h" - MODBUS_FirstInit(); - RS_Receive_IT(&hmodbus1, &MODBUS_MSG); -* @endverbatim -* -******************************************************************************/ -//#pragma pack(push, pack_modbus, 1) - - - - -//#pragma pack(pop, pack_modbus) - -#include "modbus_data.h" -#include "rs_message.h" - -uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug -/* MODBUS HANDLES */ -extern UART_HandleTypeDef rs_huart; -extern TIM_HandleTypeDef rs_htim; -RS_HandleTypeDef hmodbus1; - -/* DEFINE REGISTERS/COILS */ -MB_DeviceIdentificationTypeDef MB_INFO; -MB_DataStructureTypeDef MB_DATA; -RS_MsgTypeDef MODBUS_MSG; - -//------------------------------------------------------------------- -//-----------------------------FOR USER------------------------------ -/** - * @brief First set up of MODBUS. - * @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас. - * @note This called from main - */ -void MODBUS_FirstInit(void) -{ - MB_DevoceInentificationInit(); - //-----------SETUP MODBUS------------- - // set up modbus: MB_RX_Size_NotConst and Timeout enable - hmodbus1.ID = MODBUS_DEVICE_ID; - hmodbus1.sRS_Timeout = MODBUS_TIMEOUT; - hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; - hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; - - // INIT - hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, &rs_htim, 0); - - RS_EnableReceive(); -} -/** - * @brief Set or Reset Coil at its global address. - * @param Addr - адрес коила. - * @param WriteVal - Что записать в коил: 0 или 1. - * @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. - * - * @details Позволяет обратиться к любому коилу по его глобальному адрессу. - Вне зависимости от того как коилы размещены в памяти. - */ -MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) -{ - //---------CHECK FOR ERRORS---------- - MB_ExceptionTypeDef Exception = NO_ERRORS; - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - - //------------WRITE COIL------------- - Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1); - if(Exception == NO_ERRORS) - { - switch(WriteVal) - { - case SET_COIL: - *coils |= (1<= R_ARR_ADDR) - { - // if quantity too big return error - if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) - { - return ILLEGAL_DATA_ADDRESS; // return exception code - } - // if all ok - return no errors - return NO_ERRORS; - } - // if address isnt from this array return error - else - return ILLEGAL_DATA_ADDRESS; // return exception code -} -/** - * @brief Define Address Origin for Input/Holding Registers - * @param pRegs - указатель на указатель регистров. - * @param Addr - адрес начального регистра. - * @param Qnt - количество запрашиваемых регистров. - * @param WriteFlag - флаг регистр нужны для чтения или записи. - * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. - * - * @details Определение адреса начального регистра. - * @note WriteFlag пока не используется. - */ -MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType) -{ - /* check quantity error */ - if (Qnt > 125) - { - return ILLEGAL_DATA_VALUE; // return exception code - } - - if(RegisterType == RegisterType_Holding) - { - // Default holding registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS) - { - *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // указатель на выбранный по Addr регистр - } - // if address doesnt match any array - return illegal data address response - else - { - return ILLEGAL_DATA_ADDRESS; - } - } - else if(RegisterType == RegisterType_Input) - { - // Default input registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS) - { - *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // указатель на выбранный по Addr регистр - } - // if address doesnt match any array - return illegal data address response - else - { - return ILLEGAL_DATA_ADDRESS; - } - } - else - { - return ILLEGAL_FUNCTION; - } - // if found requeried array return no err - return NO_ERRORS; // return no errors -} -/** - * @brief Define Address Origin for coils - * @param pCoils - указатель на указатель коилов. - * @param Addr - адресс начального коила. - * @param Qnt - количество запрашиваемых коилов. - * @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила. - * @param WriteFlag - флаг коилы нужны для чтения или записи. - * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. - * - * @details Определение адреса начального регистра запрашиваемых коилов. - * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. - */ -MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag) -{ - /* check quantity error */ - if (Qnt > 2000) - { - return ILLEGAL_DATA_VALUE; // return exception code - } - - // Default coils - if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == NO_ERRORS) - { - *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr); // указатель на выбранный по Addr массив коилов - } - // if address doesnt match any array - return illegal data address response - else - { - return ILLEGAL_DATA_ADDRESS; - } - - *start_shift = Addr % 16; // set shift to requested coil - // if found requeried array return no err - return NO_ERRORS; // return no errors -} - - -/** - * @brief Proccess command Read Coils (01 - 0x01). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Coils. - */ -uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------READING COIL------------ - // setup output message data size - modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8); - // create mask for coils - uint16_t mask_for_coils = 0; // mask for coils that've been chosen - uint16_t setted_coils = 0; // value of setted coils - uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen - uint16_t coil_cnt = 0; // counter for processed coils - - // cycle until all registers with requered coils would be processed - int shift = start_shift; // set shift to first coil in first register - int ind = 0; // index for coils registers and data - for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) - { - //----SET MASK FOR COILS REGISTER---- - mask_for_coils = 0; - for(; shift < 0x10; shift++) - { - mask_for_coils |= 1<<(shift); // choose certain coil - if(++coil_cnt >= modbus_msg->Qnt) - break; - } - shift = 0; // set shift to zero for the next step - - //-----------READ COILS-------------- - modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; - if(ind > 0) - modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; - - } - // т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты - for(; ind >= 0; --ind) - modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); - - return 1; -} - -/** - * @brief Proccess command Read Holding Registers (03 - 0x03). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Holding Registers. - */ -uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - // get origin address for data - uint16_t *pHoldRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - - //-----------READING REGS------------ - // setup output message data size - modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits - // read data - int i; - for (i = 0; iQnt; i++) - { - modbus_msg->DATA[i] = *(pHoldRegs++); - } - return 1; -} - -/** - * @brief Proccess command Read Input Registers (04 - 0x04). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Input Registers. - */ -uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - // get origin address for data - uint16_t *pInRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - - //-----------READING REGS------------ - // setup output message data size - modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits - // read data - int i; - for (i = 0; iQnt; i++) - { - if(*((int16_t *)pInRegs) > 0) - modbus_msg->DATA[i] = (*pInRegs++); - else - modbus_msg->DATA[i] = (*pInRegs++); - } - return 1; -} -/** - * @brief Proccess command Write Single Coils (05 - 0x05). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Single Coils. - */ -uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) - { - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; - return 0; - } - // define position of coil - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - - //----------WRITTING COIL------------ - if(modbus_msg->Qnt == 0xFF00) - *(coils) |= 1<Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------WRITTING REG------------ - *(pHoldRegs) = modbus_msg->Qnt; - return 1; -} - -/** - * @brief Proccess command Write Multiple Coils (15 - 0x0F). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Multiple Coils. - */ -uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) - { // if quantity too large OR if quantity and bytes count arent match - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; - return 0; - } - // define position of coil - uint16_t *coils; // pointer to coils - uint16_t start_shift = 0; // shift in coils register - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //----------WRITTING COILS----------- - // create mask for coils - uint16_t mask_for_coils = 0; // mask for coils that've been chosen - uint32_t setted_coils = 0; // value of setted coils - uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen - uint16_t coil_cnt = 0; // counter for processed coils - - // cycle until all registers with requered coils would be processed - int shift = start_shift; // set shift to first coil in first register - for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) - { - //----SET MASK FOR COILS REGISTER---- - mask_for_coils = 0; - for(; shift < 0x10; shift++) - { - mask_for_coils |= 1<<(shift); // choose certain coil - if(++coil_cnt >= modbus_msg->Qnt) - break; - } - shift = 0; // set shift to zero for the next step - - - - //-----------WRITE COILS------------- - // get current coils - temp_reg = *(coils+ind); - // set coils - setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; - if(ind > 0) - { - setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); - } - // write coils - - *(coils+ind) = setted_coils & mask_for_coils; - // restore untouched coils - *(coils+ind) |= temp_reg&(~mask_for_coils); - - - if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle - break; // *kind of unnecessary - } - - return 1; -} - -/** - * @brief Proccess command Write Multiple Registers (16 - 0x10). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Multiple Registers. - */ -uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) -{ - //---------CHECK FOR ERRORS---------- - if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt) - { // if quantity and bytes count arent match - modbus_msg->Except_Code = 3; - return 0; - } - // get origin address for data - uint16_t *pHoldRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------WRITTING REGS----------- - for (int i = 0; iQnt; i++) - { - *(pHoldRegs++) = modbus_msg->DATA[i]; - } - return 1; -} - -void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj) -{ - mbdata[(*ind)++] = obj->length; - for (int i = 0; i < obj->length; i++) - { - mbdata[(*ind)++] = obj->name[i]; - } -} -/** - * @brief Proccess command Read Device Identification (43/14 - 0x2B/0E). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Single Register. - */ -uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg) -{ - char *mbdata = (char *)modbus_msg->DATA; - unsigned ind = 0; - switch(modbus_msg->DevId.ReadDevId) - { - case MB_BASIC_IDENTIFICATION: - mbdata[ind++] = 0x00; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorName); - mbdata[ind++] = 0x01; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductCode); - mbdata[ind++] = 0x02; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.Revision); - modbus_msg->DevId.NumbOfObj = 3; - break; - case MB_REGULAR_IDENTIFICATION: - mbdata[ind++] = 0x03; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorUrl); - mbdata[ind++] = 0x04; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductName); - mbdata[ind++] = 0x05; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ModelName); - mbdata[ind++] = 0x06; - MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.UserApplicationName); - modbus_msg->DevId.NumbOfObj = 4; - break; - default: - return 0; - } - - modbus_msg->ByteCnt = ind; - return 1; -} - - -/** - * @brief Respond accord to received message. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о результате ответа на комманду. - * @details Обработка принятой комманды и ответ на неё. - */ -RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) -{ - RS_StatusTypeDef MB_RES = 0; - hmodbus->f.MessageHandled = 0; - hmodbus->f.EchoResponse = 0; - RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit - - if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing - { - switch (modbus_msg->Func_Code) - { - // Read Coils - case MB_R_COILS: - hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr); - break; - - // Read Hodling Registers - case MB_R_HOLD_REGS: - hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr); - break; - case MB_R_IN_REGS: - hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr); - break; - - - // Write Single Coils - case MB_W_COIL: - hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) - } - break; - - case MB_W_HOLD_REG: - hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) - } - break; - - // Write Multiple Coils - case MB_W_COILS: - hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) - } - break; - - // Write Multiple Registers - case MB_W_HOLD_REGS: - hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) - } - break; - - case MB_R_DEVICE_INFO: - hmodbus->f.MessageHandled = MB_Read_Device_Identification(hmodbus->pMessagePtr); - break; - - - /* unknown func code */ - default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */ - } - - if(hmodbus->f.MessageHandled == 0) - { - modbus_msg->Func_Code += ERR_VALUES_START; - } - else - { - } - - - } - - // if we need response - check that transmit isnt busy - if( RS_Is_TX_Busy(hmodbus) ) - RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free - - // Transmit right there, or sets (fDeferredResponse) to transmit response in main code - MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg); - - hmodbus->RS_STATUS = MB_RES; - return MB_RES; -} - -/** - * @brief Collect message in buffer to transmit it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения буфера. - * @details Заполнение буффера UART из структуры сообщения. - */ -RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) -{ - int ind = 0; // ind for modbus-uart buffer - - if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need - ind = hmodbus->RS_Message_Size; - else - { - //------INFO ABOUT DATA/MESSAGE------ - //-----------[first bytes]----------- - // set ID of message/user - modbus_uart_buff[ind++] = modbus_msg->MbAddr; - - // set dat or err response - modbus_uart_buff[ind++] = modbus_msg->Func_Code; - - if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur - { - // fill modbus header - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identification header - { - modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type; - modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId; - modbus_uart_buff[ind++] = modbus_msg->DevId.Conformity; - modbus_uart_buff[ind++] = modbus_msg->DevId.MoreFollows; - modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId; - modbus_uart_buff[ind++] = modbus_msg->DevId.NumbOfObj; - - if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE - { - return RS_COLLECT_MSG_ERR; - } - - - //---------------DATA---------------- - //-----------[data bytes]------------ - uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; - for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data - { // set data - modbus_uart_buff[ind++] = *tmp_data_addr; - tmp_data_addr++; - } - - } - else // modbus data header - { - // set size of received data - if (modbus_msg->ByteCnt <= DATA_SIZE*2) // if ByteCnt less than DATA_SIZE - modbus_uart_buff[ind++] = modbus_msg->ByteCnt; - else // otherwise return data_size err - { - return RS_COLLECT_MSG_ERR; - } - - //---------------DATA---------------- - //-----------[data bytes]------------ - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; - for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data - { // set data - if (i%2 == 0) // HI byte - modbus_uart_buff[ind++] = (*tmp_data_addr)>>8; - else // LO byte - { - modbus_uart_buff[ind++] = *tmp_data_addr; - tmp_data_addr++; - } - } - - } - - } - else // if some error occur - { // send expection code - modbus_uart_buff[ind++] = modbus_msg->Except_Code; - } - } - //---------------CRC---------------- - //---------[last 16 bytes]---------- - // calc crc of received data - uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - // write crc to message structure and modbus-uart buffer - modbus_msg->MB_CRC = CRC_VALUE; - modbus_uart_buff[ind++] = CRC_VALUE; - modbus_uart_buff[ind++] = CRC_VALUE >> 8; - - hmodbus->RS_Message_Size = ind; - - return RS_OK; // returns ok -} - -/** - * @brief Parse message from buffer to process it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения структуры. - * @details Заполнение структуры сообщения из буффера UART. - */ -RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) -{ - uint32_t check_empty_buff; - int ind = 0; // ind for modbus-uart buffer - //-----INFO ABOUT DATA/MESSAGE------- - #ifdef TCP_ModBus - modbus_msg->ID_Transaction=modbus_uart_buff[ind++]<<8; - modbus_msg->ID_Transaction|=modbus_uart_buff[ind++]; - - modbus_msg->ID_Prot=modbus_uart_buff[ind++]<<8; - modbus_msg->ID_Prot|=modbus_uart_buff[ind++]; - modbus_msg->PDU_Length=modbus_uart_buff[ind++]<<8; - modbus_msg->PDU_Length|=modbus_uart_buff[ind++]; - #else - - #endif - //-----------[first bits]------------ - // get ID of message/user - modbus_msg->MbAddr = modbus_uart_buff[ind++]; - if(modbus_msg->MbAddr != hmodbus->ID) - return RS_SKIP; - - // get func code - modbus_msg->Func_Code = modbus_uart_buff[ind++]; - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request - { - modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++]; - modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++]; - modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++]; - modbus_msg->ByteCnt = 0; - } - else // if its classic modbus request - { - // get address from CMD - modbus_msg->Addr = modbus_uart_buff[ind++] << 8; - modbus_msg->Addr |= modbus_uart_buff[ind++]; - - // get address from CMD - modbus_msg->Qnt = modbus_uart_buff[ind++] << 8; - modbus_msg->Qnt |= modbus_uart_buff[ind++]; - } - if(hmodbus->f.RX_Half == 0) // if all message received - { - //---------------DATA---------------- - // (optional) - if (modbus_msg->ByteCnt != 0) - { - ind++; // increment ind for data_size byte - //check that data size is correct - if (modbus_msg->ByteCnt > DATA_SIZE*2) - { - modbus_msg->Func_Code += ERR_VALUES_START; - return RS_PARSE_MSG_ERR; - } - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; - for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits - { // set data - if (i%2 == 0) - *tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8); - else - { - *tmp_data_addr |= modbus_uart_buff[ind++]; - tmp_data_addr++; - } - } - } - - //---------------CRC---------------- - //----------[last 16 bits]---------- - // calc crc of received data - uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - // get crc of received data - modbus_msg->MB_CRC = modbus_uart_buff[ind++]; - modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; - // compare crc - if (modbus_msg->MB_CRC != CRC_VALUE) - { - modbus_msg->Func_Code += ERR_VALUES_START; - } - // hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc - - // check is buffer empty - check_empty_buff = 0; - for(int i=0; iMB_RESPONSE = MB_EMPTY_MSG; // - } - - return RS_OK; - -} - -/** - * @brief Define size of RX Message that need to be received. - * @param hRS - указатель на хендлер RS. - * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. - * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. - * @details Определение сколько байтов надо принять по протоколу. - */ -RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_t *rx_data_size) -{ - RS_StatusTypeDef MB_RES = 0; - - MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr); - if(MB_RES == RS_SKIP) // if message not for us - return MB_RES; // return - - - if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F) - { - hmodbus->pMessagePtr->ByteCnt = 0; - *rx_data_size = 1; - - } - else - { - hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command - // +1 because that defines is size, not ind. - *rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2; - } - - - if(hmodbus->pMessagePtr->Func_Code == MB_R_DEVICE_INFO) - { - *rx_data_size = 0; - } - - hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message - return RS_OK; -} - -//-----------------------------FOR USER------------------------------ -//------------------------------------------------------------------- - - -void MB_DevoceInentificationInit(void) -{ - MB_INFO.VendorName.name = MODBUS_VENDOR_NAME; - MB_INFO.ProductCode.name = MODBUS_PRODUCT_CODE; - MB_INFO.Revision.name = MODBUS_REVISION; - MB_INFO.VendorUrl.name = MODBUS_VENDOR_URL; - MB_INFO.ProductName.name = MODBUS_PRODUCT_NAME; - MB_INFO.ModelName.name = MODBUS_MODEL_NAME; - MB_INFO.UserApplicationName.name = MODBUS_USER_APPLICATION_NAME; - - - MB_INFO.VendorName.length = sizeof(MODBUS_VENDOR_NAME); - MB_INFO.ProductCode.length = sizeof(MODBUS_PRODUCT_CODE); - MB_INFO.Revision.length = sizeof(MODBUS_REVISION); - MB_INFO.VendorUrl.length = sizeof(MODBUS_VENDOR_URL); - MB_INFO.ProductName.length = sizeof(MODBUS_PRODUCT_NAME); - MB_INFO.ModelName.length = sizeof(MODBUS_MODEL_NAME); - MB_INFO.UserApplicationName.length = sizeof(MODBUS_USER_APPLICATION_NAME); -} - - - diff --git a/john103C6T6/Modbus/modbus.h b/john103C6T6/Modbus/modbus.h deleted file mode 100644 index 8b390d9..0000000 --- a/john103C6T6/Modbus/modbus.h +++ /dev/null @@ -1,383 +0,0 @@ -/** - ************************************************************************** - * @file modbus.h - * @brief Заголовочный файл модуля MODBUS. - * @details Данный файл необходимо подключить в rs_message.h. После подключать - * rs_message.h к основному проекту. - * - * @defgroup MODBUS - * @brief Modbus stuff - * - *************************************************************************/ -#ifndef __MODBUS_H_ -#define __MODBUS_H_ -//#define TCP_ModBus -#include "modbus_config.h" -#include "modbus_data.h" -//#include "settings.h" // for modbus settings - -/** - * @addtogroup MODBUS_SETTINGS - * @ingroup MODBUS - * @brief Some defines for modbus - @{ - */ -///////////////////////////////////////////////////////////////////// -//////////////////////////---SETTINGS---///////////////////////////// -// USER SETTINGS FOR MODBUS IN interface_config.h -//////////////////////////---SETTINGS---///////////////////////////// - - -///////////////////////////////////////////////////////////////////// -/////////////////////---USER MESSAGE DEFINES---////////////////////// -//-------------DEFINES FOR STRUCTURE---------------- -/* defines for structure of modbus message */ - -#define ID_Transaction_size 2 -#define ID_Prot_size 2 -#define DataLength_size 2 -#define MbAddr_SIZE 1 ///< size of (MbAddr) -#define Func_Code_SIZE 1 ///< size of (Func_Code) -#define Addr_SIZE 2 ///< size of (Addr) -#define Qnt_SIZE 2 ///< size of (Qnt) -#define ByteCnt_SIZE 1 ///< size of (ByteCnt) -#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) -#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes - -/** @brief Size of whole message */ -#ifdef TCP_ModBus -#define INFO_SIZE_MAX (ID_Transaction_size+ID_Prot_size+DataLength_size+MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE) -#else -#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) -#endif -/** @brief Size of first part of message that will be received -first receive info part of message, than defines size of rest message*/ -#define RX_FIRST_PART_SIZE INFO_SIZE_MAX - -/** @brief Size of buffer: max size of whole message */ -#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message - -/** @brief Structure for modbus exception codes */ -typedef enum //MB_ExceptionTypeDef -{ - // reading - NO_ERRORS = 0x00, ///< no errors - ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан - ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен - ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной - SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие -// ACKNOWLEDGE = 0x05, ///< idk -// SLAVE_DEVICE_BUSY = 0x06, ///< idk -// MEMORY_PARITY_ERROR = 0x08, ///< idk -}MB_ExceptionTypeDef; - -#define ERR_VALUES_START 0x80U ///< from this value starts error func codes -/** @brief Structure for modbus func codes */ -typedef enum //MB_FunctonTypeDef -{ - /* COMMANDS */ - // reading - MB_R_COILS = 0x01, ///< Чтение битовых ячеек - MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов -#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS - MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров - MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения -#else - MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров - MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения -#endif - - // writting - MB_W_COIL = 0x05, ///< Запись битовой ячейки - MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра - MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек - MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров - - MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве - - /* ERRORS */ - // error reading - MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек - MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов - MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения - MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров - - // error writting - MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки - MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра - MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек - MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров -}MB_FunctonTypeDef; - -/** @brief Structure for MEI func codes */ -typedef enum //MB_FunctonTypeDef -{ - MEI_DEVICE_IDENTIFICATION = 0x0E, -}MB_MEITypeDef; - -/** @brief Structure for MEI func codes */ -typedef enum //MB_FunctonTypeDef -{ - MB_BASIC_IDENTIFICATION = 0x01, - MB_REGULAR_IDENTIFICATION = 0x02, - - - /* ERRORS */ - MB_ERR_BASIC_IDENTIFICATION = MB_BASIC_IDENTIFICATION + ERR_VALUES_START, - MB_ERR_REGULAR_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START, -}MB_ConformityTypeDef; - -/** @brief Structure for decive identification message type */ -typedef struct -{ - MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface - MB_ConformityTypeDef ReadDevId; - MB_ConformityTypeDef Conformity; - uint8_t MoreFollows; ///< in this library always a zero - uint8_t NextObjId; - uint8_t NumbOfObj; -}MB_DevIdMsgTypeDef; - -/** @brief Structure for modbus messsage */ -typedef struct // RS_MsgTypeDef -{ - uint16_t ID_Transaction; - uint16_t ID_Prot; - uint16_t PDU_Length; - - uint8_t MbAddr; ///< Modbus Slave Address - MB_FunctonTypeDef Func_Code; ///< Modbus Function Code - MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct - uint16_t Addr; ///< Modbus Address of data - uint16_t Qnt; ///< Quantity of modbus data - uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive - - uint16_t DATA[DATA_SIZE]; ///< Modbus Data - MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command - - uint16_t MB_CRC; ///< Modbus CRC -}RS_MsgTypeDef; -//-------------------------------------------------- -extern RS_MsgTypeDef MODBUS_MSG; -/////////////////////---MODBUS USER SETTINGS---////////////////////// - -/** MODBUS_SETTINGS - * @} - */ - - -///////////////////////////////////////////////////////////////////// -////////////////////---MODBUS MESSAGE DEFINES---///////////////////// -/** - * @addtogroup MODBUS_MESSAGE_DEFINES - * @ingroup MODBUS - * @brief Some defines for modbus - @{ - */ -/** @brief Structure for coils operation */ -typedef enum -{ - SET_COIL, - RESET_COIL, - TOOGLE_COIL, -}MB_CoilsOpTypeDef; - -//-------------------------------------------------- - -/** - * @brief Macros to set pointer to 16-bit array - * @param _arr_ - массив регистров (16-бит). - */ -#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_))) -/** - * @brief Macros to set pointer to register - * @param _parr_ - массив регистров. - * @param _addr_ - Номер регистра (его индекс) от начала массива _arr_. - */ -#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_)) - -/** - * @brief Macros to set pointer to a certain register that contains certain coil - * @param _parr_ - массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * @note Используется вместе с @ref MB_Set_Coil_Mask - @verbatim Пояснение выражений - (_coil_/16) - get index (address shift) of register that contain certain coil - Visual explanation: 30th coil in coils registers array - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx - |register[0]----| |register[1]----| - |skip this------| |get this-------| - |shift to 14 bit| - @endverbatim - */ -#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) -/** - * @brief Macros to set mask to a certain bit in coils register - * @param _coil_ - Номер коила от начала массива _arr_. - * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr - @verbatim Пояснение выражений - (16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register - _coil_-(16*(_coil_/16)) - shift to certain coil in certain register - e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14) - - Visual explanation: 30th coil in coils registers array - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx - |register[0]----| |register[1]----| - |skip this------| |get this-------| - |shift to 14 bit| - @endverbatim - */ -#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) - -/** - * @brief Read Coil at its local address. - * @param _parr_ - массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * @return uint16_t - Возвращает запрошенный коил на 0м бите. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) -/** - * @brief Set Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) -/** - * @brief Reset Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) -/** - * @brief Set Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) -//-------------------------------------------------- - - -//------------------OTHER DEFINES------------------- -#define RegisterType_Holding 0 -#define RegisterType_Input 1 -#define RegisterType_Discrete 2 -// create hadnles and settings for uart, tim, rs with _modbus_ name -//-------------------------------------------------- - -#ifndef Divide_Up -/** - * @brief Calc dividing including remainder - * @param _val_ - делимое. - * @param _div_ - делитель. - * @details Если результат деления без остатка: он возвращается как есть - Если с остатком - округляется вверх - */ -//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */ -#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */ -#endif - -#ifndef ByteSwap16 -/** - * @brief Swap between Little Endian and Big Endian - * @param v - Переменная для свапа. - * @return v (new) - Свапнутая переменная. - * @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты. - */ -#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8))) -#endif -/** GENERAL_MODBUS_STUFF - * @} - */ -////////////////////---MODBUS MESSAGE DEFINES---///////////////////// - - - -///////////////////////////////////////////////////////////////////// -/////////////////////////---FUNCTIONS---///////////////////////////// -/** - * @addtogroup MODBUS_FUNCTIONS - * @ingroup MODBUS - * @brief Function for controling modbus communication - */ - -//----------------FUNCTIONS FOR USER---------------- -/** - * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS - * @ingroup MODBUS_FUNCTIONS - * @brief Function for user use - @{ - */ -/* First set up of MODBUS */ -void MODBUS_FirstInit(void); -/* Set or Reset Coil at its global address */ -MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal); -/* Read Coil at its global address */ -uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); - -/** MODBUS_DATA_ACCESS_FUNCTIONS - * @} - */ - -//---------PROCESS MODBUS COMMAND FUNCTIONS--------- -/** - * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - * @ingroup MODBUS_FUNCTIONS - * @brief Function process commands - @{ - */ -/* Check is address valid for certain array */ -MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB); -/* Define Address Origin for Input/Holding Registers */ -MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType); -/* Define Address Origin for coils */ -MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag); -/* Proccess command Read Coils (01 - 0x01) */ -uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg); -/* Proccess command Read Holding Registers (03 - 0x03) */ -uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); -/* Proccess command Read Input Registers (04 - 0x04) */ -uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); -/* Proccess command Write Single Coils (05 - 0x05) */ -uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg); -/* Proccess command Write Multiple Coils (15 - 0x0F) */ -uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); -/* Proccess command Write Multiple Register (16 - 0x10) */ -uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); - -/** MODBUS_DATA_ACCESS_FUNCTIONS - * @} - */ -/////////////////////////---FUNCTIONS---///////////////////////////// - - - -///////////////////////////////////////////////////////////////////// -/////////////////////////---CALC DEFINES---////////////////////////// - - -// TRACES DEFINES -#ifndef Trace_MB_UART_Enter -#define Trace_MB_UART_Enter() -#endif //Trace_MB_UART_Enter - -#ifndef Trace_MB_UART_Exit -#define Trace_MB_UART_Exit() -#endif //Trace_MB_UART_Exit - -#ifndef Trace_MB_TIM_Enter -#define Trace_MB_TIM_Enter() -#endif //Trace_MB_TIM_Enter - -#ifndef Trace_MB_TIM_Exit -#define Trace_MB_TIM_Exit() -#endif //Trace_MB_TIM_Exit - -#endif //__MODBUS_H_ diff --git a/john103C6T6/Modbus/modbus_config.h b/john103C6T6/Modbus/modbus_config.h index 93ffdee..bdb9c0c 100644 --- a/john103C6T6/Modbus/modbus_config.h +++ b/john103C6T6/Modbus/modbus_config.h @@ -1,37 +1,60 @@ /** -************************************************************************** -* @file interface_config.h -* @brief Конфигурация для модбаса -*************************************************************************/ +****************************************************************************** +* @file modbus_config.h +* @brief Конфигурационные параметры Modbus устройства +****************************************************************************** +@addtogroup MODBUS_CONFIGS Modbus configs +@ingroup MODBUS +@brief Конфигурация библиотеки +@{ +****************************************************************************** +* @details +Файл содержит настройки для работы Modbus: +- Подключение библиотек контроллера +- ID устройства и таймауты +- Строковые идентификаторы (Vendor, Product, Revision) +- Настройки периферии (UART, TIMER) +- Подключение модулей Modbus +- Опциональные функции (переключение команд 0x03/0x04) +******************************************************************************/ #ifndef _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_ #include "stm32f1xx_hal.h" -#include "proj_setup.h" -// MODBUS PARAMS -#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства -#ifdef OldVer -#define MODBUS_TIMEOUT 2000 ///< максимальнйы тайтаут MB в тиках таймера -#else -#define MODBUS_TIMEOUT 0 -#endif -// STRING OBJECTS MODBUS +// Общие параметры +#define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus +#define MODBUS_TIMEOUT 5000 ///< Таймаут в тиках таймера + +// Строковые идентификаторы устройства #define MODBUS_VENDOR_NAME "NIO-12" #define MODBUS_PRODUCT_CODE "" -#define MODBUS_REVISION "Ver. 1.0" +#define MODBUS_REVISION "" #define MODBUS_VENDOR_URL "" #define MODBUS_PRODUCT_NAME "" -#define MODBUS_MODEL_NAME "STM32F103" +#define MODBUS_MODEL_NAME "" #define MODBUS_USER_APPLICATION_NAME "" -// PERIPH FUNCTIONS AND HANDLERS -#define RS_UART_Init MX_USART1_UART_Init //инициализация uart -#define RS_UART_DeInit HAL_UART_MspDeInit //деинициализация uart -#define RS_TIM_Init MX_TIM2_Init //инициализация таймера -#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit//деинициализация таймера -#define rs_huart huart1 //используемый uart -#define rs_htim htim2 //используемый таймера +#define MODBUS_NUMB_OF_USEROBJECTS 0 ///< Количество пользовательских объектов +#define MODBUS_USEROBJECT_0_NAME "" ///< Строка пользовательского идентификатора 0. По аналогии можно определить строки до <=128 USEROBJECT +// Периферия (опционально) +#define mb_huart huart1 ///< Удобный дефайн для модбасовского uart +#define mb_htim htim2 ///< Удобный дефайн для модбасовского таймера +//#define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485 +//#define RS_EnableTransmit() ///< Функция изменения направления передачи на ПЕРЕДАЧУ для RS-485 + + +// Модули modbus +#define MODBUS_ENABLE_SLAVE ///< Включить обработку СЛЕЙВ режима +//#define MODBUS_ENABLE_MASTER ///< Включить обработку МАСТЕР режима + +#define MODBUS_ENABLE_COILS ///< Включить обработку коилов +#define MODBUS_ENABLE_HOLDINGS ///< Включить обработку регистров хранения +#define MODBUS_ENABLE_INPUTS ///< Включить обработку входных регистров +#define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства +#define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас + +//#define MODBUS_PROTOCOL_TCP ///< Включить TCP-протокол, иначе - RTU /** * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) @@ -45,4 +68,4 @@ -#endif //_MODBUS_CONFIG_H_ \ No newline at end of file +#endif //_MODBUS_CONFIG_H_ diff --git a/john103C6T6/Modbus/modbus_data.c b/john103C6T6/Modbus/modbus_data.c new file mode 100644 index 0000000..50ffa3a --- /dev/null +++ b/john103C6T6/Modbus/modbus_data.c @@ -0,0 +1,141 @@ +/** +****************************************************************************** +* @file modbus_data.c +* @brief Функции доступа к данным Modbus +****************************************************************************** +* @details +Модуль реализует функции валидации адресов и доступа к данным: +- Проверка корректности запрашиваемых адресов +- Определение указателей на реальные данные в памяти +- Поддержка пользовательских массивов регистров и coils + +@section Валидация адресов: +- MB_Check_Address_For_Arr() - проверка принадлежности адреса массиву +- MB_DefineRegistersAddress() - получение указателя на регистры +- MB_DefineCoilsAddress() - получение указателя на coils + +******************************************************************************/ + +#include "modbus_core.h" +#include "modbus_coils.h" +#include "modbus_holdregs.h" +#include "modbus_inputregs.h" +#include "modbus_devid.h" + + +/** + * @brief Check is address valid for certain array. + * @param Addr Начальный адресс. + * @param Qnt Количество запрашиваемых элементов. + * @param R_ARR_ADDR Начальный адресс массива R_ARR. + * @param R_ARR_NUMB Количество элементов в массиве R_ARR. + * @return ExceptionCode - ET_ILLEGAL_DATA_ADRESS если адресс недействителен, и ET_NO_ERRORS если все ок. + * + * @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR: + * Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR. + * Если адресс Addr находится за пределами адрессов массива R_ARR - ET_ILLEGAL_DATA_ADDRESSю. + */ +MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB) +{ + // if address from this array + if(Addr >= R_ARR_ADDR) + { + // if quantity too big return error + if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) + { + return ET_ILLEGAL_DATA_ADDRESS; // return exception code + } + // if all ok - return no errors + return ET_NO_ERRORS; + } + // if address isnt from this array return error + else + return ET_ILLEGAL_DATA_ADDRESS; // return exception code +} +/** + * @brief Define Address Origin for Input/Holding Registers + * @param pRegs Указатель на указатель регистров. + * @param Addr Адрес начального регистра. + * @param Qnt Количество запрашиваемых регистров. + * @param WriteFlag Флаг регистр нужны для чтения или записи. + * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет. + * + * @details Определение адреса начального регистра. + * @note WriteFlag пока не используется. + */ +MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType) +{ + /* check quantity error */ + if (Qnt > DATA_SIZE) + { + return ET_ILLEGAL_DATA_VALUE; // return exception code + } + + if(RegisterType == RegisterType_Holding) + { + // Default holding registers + if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == ET_NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр + } + // if address doesnt match any array - return illegal data address response + else + { + return ET_ILLEGAL_DATA_ADDRESS; + } + } + else if(RegisterType == RegisterType_Input) + { + // Default input registers + if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == ET_NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr - R_INPUT_ADDR); // указатель на выбранный по Addr регистр + } + // if address doesnt match any array - return illegal data address response + else + { + return ET_ILLEGAL_DATA_ADDRESS; + } + } + else + { + return ET_ILLEGAL_FUNCTION; + } + // if found requeried array return no err + return ET_NO_ERRORS; // return no errors +} +/** + * @brief Define Address Origin for coils + * @param pCoils Указатель на указатель коилов. + * @param Addr Адресс начального коила. + * @param Qnt Количество запрашиваемых коилов. + * @param start_shift Указатель на переменную содержащую сдвиг внутри регистра для начального коила. + * @param WriteFlag Флаг коилы нужны для чтения или записи. + * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет. + * + * @details Определение адреса начального регистра запрашиваемых коилов. + * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. + */ +MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag) +{ + /* check quantity error */ + if (Qnt > 2000) + { + return ET_ILLEGAL_DATA_VALUE; // return exception code + } + + // Default coils + if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == ET_NO_ERRORS) + { + *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_CONTROL_ADDR); // указатель на выбранный по Addr массив коилов + } + // if address doesnt match any array - return illegal data address response + else + { + return ET_ILLEGAL_DATA_ADDRESS; + } + + *start_shift = Addr % 16; // set shift to requested coil + // if found requeried array return no err + return ET_NO_ERRORS; // return no errors +} diff --git a/john103C6T6/Modbus/modbus_data.h b/john103C6T6/Modbus/modbus_data.h index 1346ac3..7495e5c 100644 --- a/john103C6T6/Modbus/modbus_data.h +++ b/john103C6T6/Modbus/modbus_data.h @@ -240,17 +240,17 @@ typedef __PACKED_STRUCT - word coils[3]; //32 + word coils[3]; //48 uint16_t reserve1[mb_fill_rsv(128/16, word[3])]; STATUS_TSENS status_tSens[MAX_SENSE/16]; //32 uint16_t reserve2[mb_fill_rsv(128/16, STATUS_TSENS[MAX_SENSE/16])]; RELAY_Struct relay_struct[MAX_SENSE/16*2];//16 2 реле на 1 датчик uint16_t reserve3[mb_fill_rsv(128/16, RELAY_Struct[MAX_SENSE/16*2])]; - unsigned init_param:1; - unsigned init_Tsens:1; - unsigned Save_Param_to_Flash:1; - unsigned reserved2:14; + unsigned init_param:1; //384 + unsigned init_Tsens:1; //385 + unsigned Save_Param_to_Flash:1; //386 + unsigned reserved2:13; }MB_DataCoilsTypeDef; @@ -277,33 +277,6 @@ typedef struct // tester modbus data }MB_DataStructureTypeDef; extern MB_DataStructureTypeDef MB_DATA; - -/** - * @brief Структура для объекта Modbus - * @ingroup MODBUS_DATA - */ -typedef struct -{ - unsigned length; - char *name; -}MB_DeviceObjectTypeDef; -/** - * @brief Структура для объектов Modbus - * @ingroup MODBUS_DATA - */ -typedef struct -{ - MB_DeviceObjectTypeDef VendorName; - MB_DeviceObjectTypeDef ProductCode; - MB_DeviceObjectTypeDef Revision; - MB_DeviceObjectTypeDef VendorUrl; - MB_DeviceObjectTypeDef ProductName; - MB_DeviceObjectTypeDef ModelName; - MB_DeviceObjectTypeDef UserApplicationName; -}MB_DeviceIdentificationTypeDef; -void MB_DevoceInentificationInit(void); - - #endif //_MODBUS_DATA_H_ ///////////////////////////////////////////////////////////// diff --git a/john103C6T6/Modbus/rs_message.c b/john103C6T6/Modbus/rs_message.c deleted file mode 100644 index d40674b..0000000 --- a/john103C6T6/Modbus/rs_message.c +++ /dev/null @@ -1,566 +0,0 @@ -/** -************************************************************************** -* @file rs_message.c -* @brief Модуль для реализации протоколов по RS/UART. -**************************************************************************\ -* @details -* Данный модуль реализует основные функции для приема и передачи сообщений -* по протоколу RS через UART в режиме прерываний. Реализована обработка -* приема и передачи данных, управление состояниями RS, а также функции для -* инициализации и управления периферией. -* -* Реализованы следующие функции: -* - RS_Receive_IT() — запуск приема данных в прерывании по UART. -* - RS_Transmit_IT() — запуск передачи данных в прерывании по UART. -* - RS_Init() — инициализация структуры RS и привязка периферии. -* - RS_ReInit_UART() — переинициализация UART и перезапуск приема данных. -* - RS_Abort() — остановка работы RS/UART с очисткой флагов и структур. -* - RS_Handle_Receive_Start() — обработка старта приема данных по RS. -* -* В модуле также определен буфер RS_Buffer[] для хранения принимаемых/передаваемых данных. -* -* @note -* Для корректной работы модуля предполагается использование соответствующих -* обработчиков прерываний UART и таймера (RS_UART_Handler(), RS_TIM_Handler()), -* которые надо вызывать с обработчиках используемой периферии - -@verbatim -//-------------------Функции-------------------// -Functions: users - - RS_Parse_Message/RS_Collect_Message Заполнение структуры сообщения и буфера - - RS_Response Ответ на сообщение - - RS_Define_Size_of_RX_Message Определение размера принимаемых данных - -Functions: general - - RS_Receive_IT Ожидание комманды и ответ на неё - - RS_Transmit_IT Отправление комманды и ожидание ответа - - RS_Init Инициализация переферии и структуры для RS - - RS_ReInit_UART Реинициализация UART для RS - - RS_Abort Отмена приема/передачи по ЮАРТ - - RS_Init Инициализация периферии и modbus handler - -Functions: callback/handler - - RS_Handle_Receive_Start Функция для запуска приема или остановки RS - - RS_Handle_Transmit_Start Функция для запуска передачи или остановки RS - - - RS_UART_RxCpltCallback Коллбек при окончании приема или передачи - RS_UART_TxCpltCallback - - - RS_UART_Handler Обработчик прерывания для UART - - RS_TIM_Handler Обработчик прерывания для TIM - -@endverbatim -*************************************************************************/ -#include "rs_message.h" - -uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer - -extern void RS_UART_Init(void); -extern void RS_UART_DeInit(UART_HandleTypeDef *huart); -extern void RS_TIM_Init(void); -extern void RS_TIM_DeInit(TIM_HandleTypeDef *htim); - -//------------------------------------------------------------------- -//-------------------------GENERAL FUNCTIONS------------------------- -/** - * @brief Start receive IT. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о состоянии RS после инициализации приема. - */ -RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) -{ - RS_StatusTypeDef RS_RES = 0; - HAL_StatusTypeDef uart_res = 0; - - //-------------CHECK RS LINE---------------- - // check that receive isnt busy - if( RS_Is_RX_Busy(hRS) ) // if tx busy - return busy status - return RS_BUSY; - - //-----------INITIALIZE RECEIVE------------- - // if all OK: start receiving - RS_EnableReceive(); - RS_Set_Busy(hRS); // set RS busy - RS_Set_RX_Flags(hRS); // initialize flags for receive - hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions - - // start receiving - uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, RX_FIRST_PART_SIZE); // receive until ByteCnt+1 byte, - // then in Callback restart receive for rest bytes - - // if receive isnt started - abort RS - if(uart_res != HAL_OK) - { - RS_RES = RS_Abort(hRS, ABORT_RS); - printf_rs_err("\n%d: Error RS: Failed to start RS receiving...", uwTick); - } - else - { - RS_RES = RS_OK; - printf_rs("\n%d: RS: Start Receiving...", uwTick); - } - - hRS->RS_STATUS = RS_RES; - return RS_RES; // returns result of receive init -} - -/** - * @brief Start transmit IT. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о состоянии RS после инициализации передачи. - */ -RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) -{ - RS_StatusTypeDef RS_RES = 0; - HAL_StatusTypeDef uart_res = 0; - - //-------------CHECK RS LINE---------------- - // check that transmit isnt busy - if( RS_Is_TX_Busy(hRS) ) // if tx busy - return busy status - return RS_BUSY; - // check receive line - - - //------------COLLECT MESSAGE--------------- - RS_RES = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr); - if (RS_RES != RS_OK) // if message isnt collect - stop RS and return error in RS_RES - {// need collect message status, so doesnt write abort to RS_RES - RS_Abort(hRS, ABORT_RS); - RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); // restart receive - } - else // if collect successful - { - - //----------INITIALIZE TRANSMIT------------- - RS_EnableTransmit(); -// for(int i = 0; i < hRS->sRS_Timeout; i++); - - RS_Set_Busy(hRS); // set RS busy - RS_Set_TX_Flags(hRS); // initialize flags for transmit IT - hRS->pMessagePtr = RS_msg; // set pointer for filling given structure from UARTHandler fucntion - - // if all OK: start transmitting - uart_res = HAL_UART_Transmit_IT(hRS->huart, hRS->pBufferPtr, hRS->RS_Message_Size); - // if transmit isnt started - abort RS - if(uart_res != HAL_OK) - { - RS_RES = RS_Abort(hRS, ABORT_RS); - printf_rs_err("\n%d: Error RS: Failed to start RS transmitting...", uwTick); - } - else - { - RS_RES = RS_OK; - printf_rs("\n%d: RS: Start Transmitting...", uwTick); - } - } - - - hRS->RS_STATUS = RS_RES; - return RS_RES; // returns result of transmit init -} - -/** - * @brief Initialize UART and handle RS stucture. - * @param hRS - указатель на хендлер RS. - * @param suart - указатель на структуру с настройками UART. - * @param stim - указатель на структуру с настройками таймера. - * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. - * @return RS_RES - статус о состоянии RS после инициализации. - * @note Инициализация перефирии и структуры для приема-передачи по RS. - */ -RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr) -{ - // check that hRS is defined - if (hRS == NULL) - return RS_ERR; - // check that huart is defined - if (huart == NULL) - return RS_ERR; - // init uart - -// RS_UART_Init(); - hRS->huart = huart; - -// RS_TIM_Init(); - hRS->htim = htim; - - if (hRS->sRS_RX_Size_Mode == NULL) - return RS_ERR; - - // check that buffer is defined - if (hRS->pBufferPtr == NULL) - { - hRS->pBufferPtr = RS_Buffer; // if no - set default - } - else - hRS->pBufferPtr = pRS_BufferPtr; // if yes - set by user - - return RS_OK; -} - -/** - * @brief ReInitialize UART and RS receive. - * @param hRS - указатель на хендлер RS. - * @param suart - указатель на структуру с настройками UART. - * @return RS_RES - статус о состоянии RS после инициализации. - * @note Реинициализация UART и приема по RS. - */ -HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart) -{ - HAL_StatusTypeDef RS_RES; - hRS->f.ReInit_UART = 0; - -// // check is settings are valid -// if(Check_UART_Init_Struct(suart) != HAL_OK) -// return HAL_ERROR; - - RS_Abort(hRS, ABORT_RS); - - RS_UART_DeInit(huart); - - RS_UART_Init(); - - - RS_Receive_IT(hRS, hRS->pMessagePtr); - return RS_RES; -} - - -/** - * @brief Abort RS/UART. - * @param hRS - указатель на хендлер RS. - * @param AbortMode - выбор, что надо отменить. - - ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX, - - ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX, - - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, - - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. - * @return RS_RES - статус о состоянии RS после аборта. - * @note Отмена работы UART в целом или отмена приема/передачи RS. - Также очищается хендл hRS. - */ -RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) -{ - HAL_StatusTypeDef uart_res = 0; - hRS->htim->Instance->CNT = 0; - __HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE); - - if(hRS->sRS_Timeout) // if timeout setted - HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout - - if((AbortMode&ABORT_RS) == 0x00) - { - if((AbortMode&ABORT_RX) == ABORT_RX) - { - uart_res = HAL_UART_AbortReceive(hRS->huart); // abort receive - RS_Reset_RX_Flags(hRS); - } - - if((AbortMode&ABORT_TX) == ABORT_TX) - { - uart_res = HAL_UART_AbortTransmit(hRS->huart); // abort transmit - RS_Reset_TX_Flags(hRS); - } - } - else - { - uart_res = HAL_UART_Abort(hRS->huart); - RS_Clear_All(hRS); - } - hRS->RS_STATUS = RS_ABORTED; - return RS_ABORTED; -} - - -//-------------------------GENERAL FUNCTIONS------------------------- -//------------------------------------------------------------------- - - - -//------------------------------------------------------------------- -//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- -/** - * @brief Handle for starting receive. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о состоянии RS после инициализации приема или окончания общения. - * @note Определяет начинать прием команды/ответа или нет. - */ -RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) -{ - RS_StatusTypeDef RS_RES = 0; - - switch(hRS->sRS_Mode) - { - case SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting - RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again - case SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request) - RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy) - } - - if(RS_RES != RS_OK) - { - } - - return RS_RES; -} -/** - * @brief Handle for starting transmit. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о состоянии RS после инициализации передачи. - * @note Определяет отвечать ли на команду или нет. - */ -RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) -{ - RS_StatusTypeDef RS_RES = 0; - - switch(hRS->sRS_Mode) - { - case SLAVE_ALWAYS_WAIT: // in slave mode always response - case SLAVE_TIMEOUT_WAIT: // transmit response - RS_RES = RS_Transmit_IT(hRS, RS_msg); break; - } - if(RS_RES != RS_OK) - { - } - - return RS_RES; -} - -/** - * @brief UART RX Callback: define behaviour after receiving parts of message. - * @param hRS - указатель на хендлер RS. - * @return RS_RES - статус о состоянии RS после обработки приема. - * @note Контролирует прием сообщения: определяет размер принимаемой посылки и обрабатывает его. - */ -RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS) -{ - RS_StatusTypeDef RS_RES = 0; - HAL_StatusTypeDef uart_res = 0; - - // if we had received bytes before ByteCnt - if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and - { // First receive part of message, then define size of rest of message, and start receive it - hRS->f.RX_Half = 1; - //---------------FIND DATA SIZE----------------- - uint32_t NuRS_of_Rest_Bytes = 0xFFFF; - RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes); - - - // if we need to skip this message - restart receive - if(RS_RES == RS_SKIP || NuRS_of_Rest_Bytes == 0xFFFF) - { - RS_Abort(hRS, ABORT_RX); - RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); - return RS_RES; - } - - // if there is no bytes to receive - if(NuRS_of_Rest_Bytes == 0) - { - hRS->f.RX_Half = 0; - - //---------PROCESS DATA & ENDING RECEIVING-------- - RS_Set_RX_End(hRS); - - if(hRS->sRS_Timeout) // if timeout setted - HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout - - // parse received data - RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message - - // RESPONSE - RS_RES = RS_Response(hRS, hRS->pMessagePtr); - return RS_RES; - } - - - //-------------START UART RECEIVE--------------- - uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes); - - if(uart_res != HAL_OK) - {// need uart status, so doesnt write abort to RS_RES - RS_RES = RS_Abort(hRS, ABORT_RS); - } - else - RS_RES = RS_OK; - } - else // if we had received whole message - { - hRS->f.RX_Half = 0; - - //---------PROCESS DATA & ENDING RECEIVING-------- - RS_Set_RX_End(hRS); - - if(hRS->sRS_Timeout) // if timeout setted - HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout - - // parse received data - RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message - - // RESPONSE - RS_RES = RS_Response(hRS, hRS->pMessagePtr); - } - - return RS_RES; -} - - -/** - * @brief UART TX Callback: define behaviour after transmiting message. - * @param hRS - указатель на хендлер RS. - * @return RS_RES - статус о состоянии RS после обработки приема. - * @note Определяет поведение RS после передачи сообщения. - */ -RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS) -{ - RS_StatusTypeDef RS_RES = RS_OK; - HAL_StatusTypeDef uart_res = 0; - - //--------------ENDING TRANSMITTING------------- - RS_Set_TX_End(hRS); - RS_EnableReceive(); -// for(int i = 0; i < hRS->sRS_Timeout; i++); - - //-----------START RECEIVING or END RS---------- - RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); - - return RS_RES; -} - -/** - * @brief Handler for UART. - * @param hRS - указатель на хендлер RS. - * @note Обрабатывает ошибки если есть и вызывает RS Коллбеки. - * Добавить вызов этой функции в UARTx_IRQHandler() после HAL_UART_IRQHandler(). - */ -void RS_UART_Handler(RS_HandleTypeDef *hRS) -{ - //-------------CALL RS CALLBACKS------------ - /* IF NO ERROR OCCURS */ - if(hRS->huart->ErrorCode == 0) - { - hRS->htim->Instance->CNT = 0; // reset cnt; - /* Start timeout */ - if(hRS->sRS_Timeout) // if timeout setted - if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active - { - hRS->htim->Instance->ARR = hRS->sRS_Timeout; // reset cnt; - HAL_TIM_Base_Start_IT(hRS->htim); - RS_Set_RX_Active_Flags(hRS); - } - - /* RX Callback */ - if (( hRS->huart->RxXferCount == 0U) && RS_Is_RX_Busy(hRS) && // if all bytes are received and receive is active - hRS->huart->RxState != HAL_UART_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy - RS_UART_RxCpltCallback(hRS); - - /* TX Callback */ - if (( hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active - hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy - RS_UART_TxCpltCallback(hRS); - } - //----------------ERRORS HANDLER---------------- - else - { - if(hRS->f.RX_Busy) - { - - /* de-init uart transfer */ - RS_Abort(hRS, ABORT_RS); - RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); - // later, maybe, will be added specific handlers for err - } - - } -} - - -/** - * @brief Handler for TIM. - * @param hRS - указатель на хендлер RS. - * @note Попадание сюда = таймаут и перезапуск RS приема - * Добавить вызов этой функции в TIMx_IRQHandler() после HAL_TIM_IRQHandler(). - */ -void RS_TIM_Handler(RS_HandleTypeDef *hRS) -{ - // if(hRS->sRS_Timeout) - // HAL_TIM_Base_Stop_IT(hRS->htim); - - - HAL_TIM_Base_Stop_IT(hRS->htim); - #ifdef OldVer - RS_Abort(hRS, ABORT_RS); - #else - RS_Abort(hRS, ABORT_RX); - #endif - - - - - RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); -} -//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- -//------------------------------------------------------------------- - - - -//------------------------------------------------------------------- -//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- -/** - * @brief Respond accord to received message. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о результате ответа на комманду. - * @note Обработка принятой комманды и ответ на неё. - */ -__weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) -{ - /* Redefine function for user purposes */ - return RS_ERR; -} - -/** - * @brief Collect message in buffer to transmit it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения буфера. - * @note Заполнение буффера UART из структуры сообщения. - */ -__weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) -{ - /* Redefine function for user purposes */ - return RS_ERR; -} - -/** - * @brief Parse message from buffer to process it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения структуры. - * @note Заполнение структуры сообщения из буффера UART. - */ -__weak RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) -{ - /* Redefine function for user purposes */ - return RS_ERR; -} - -/** - * @brief Define size of RX Message that need to be received. - * @param hRS - указатель на хендлер RS. - * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. - * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. - * @note Определение сколько байтов надо принять по протоколу. - */ -__weak RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) -{ - /* Redefine function for user purposes */ - return RS_ERR; -} -//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- -//------------------------------------------------------------------- diff --git a/john103C6T6/Modbus/rs_message.h b/john103C6T6/Modbus/rs_message.h deleted file mode 100644 index 6aaabd3..0000000 --- a/john103C6T6/Modbus/rs_message.h +++ /dev/null @@ -1,259 +0,0 @@ -/** -************************************************************************** -* @file rs_message.h -* @brief Заголовочный файл для модуля реализации протоколов по RS/UART. -************************************************************************** -* @defgroup RS_TOOLS -* @brief Всякое для работы по UART/RS -************************************************************************** -@details -************************************************************************** -Для настройки RS/UART под нужный протокол, необходимо: - - Определить структуру сообщения RS_MsgTypeDef и - дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX. - - Подключить этот файл в раздел rs_message.h. - - Определить функции для обработки сообщения: RS_Parse_Message(), - RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message() - - Добавить UART/TIM Handler в Хендлер используемых UART/TIM. - -Так же данный модуль использует счетчики -************************************************************************** -@verbatim -Визуальное описание. Форматирование сохраняется как в коде. -@endverbatim -*************************************************************************/ -#ifndef __RS_LIB_H_ -#define __RS_LIB_H_ - -#include "modbus.h" - -#include "crc_algs.h" - - -///////////////////////////////////////////////////////////////////// -////////////////////////////---DEFINES---//////////////////////////// -/* Check that all defines required by RS are defined */ -#ifndef MSG_SIZE_MAX -#error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART. -#endif - -#ifndef RX_FIRST_PART_SIZE -#error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message. -#endif - - -/* Clear message-uart buffer */ -#define RS_Clear_Buff(_buff_) for(int i=0; if.RS_Busy = 0 -#define RS_Set_Busy(_hRS_) _hRS_->f.RS_Busy = 1 - -#define RS_Set_RX_Flags(_hRS_) _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 -#define RS_Set_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 1 - - -#define RS_Set_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0 - -#define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0 -#define RS_Reset_RX_Flags(_hRS_) RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 -#define RS_Reset_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0 - -#define RS_Set_RX_End_Flag(_hRS_) _hRS_->f.RX_Done = 1; -#define RS_Set_TX_End_Flag(_hRS_) _hRS_->f.TX_Done = 1 - -#define RS_Set_RX_End(_hRS_) RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_) -#define RS_Set_TX_End(_hRS_) RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_) - -/* Clear all RS stuff */ -#define RS_Clear_All(_hRS_) RS_Clear_Buff(_hRS_->pBufferPtr); RS_Reset_RX_Flags(_hRS_); RS_Reset_TX_Flags(_hRS_); - -//#define MB_Is_RX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX) -//#define MB_Is_TX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX) -#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1) -#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1) - - -#ifndef RS_EnableReceive -#define RS_EnableReceive() -#endif -#ifndef RS_EnableTransmit -#define RS_EnableTransmit() -#endif -////////////////////////////---DEFINES---//////////////////////////// - - - -///////////////////////////////////////////////////////////////////// -///////////////////////---STRUCTURES & ENUMS---////////////////////// -//------------------ENUMERATIONS-------------------- -/** @brief Enums for respond CMD about RS status */ -typedef enum // RS_StatusTypeDef -{ - /* IN-CODE STATUS (start from 0x01, and goes up)*/ - /*0x01*/ RS_OK = 0x01, - /*0x02*/ RS_ERR, - /*0x03*/ RS_ABORTED, - /*0x04*/ RS_BUSY, - /*0x05*/ RS_SKIP, - - /*0x06*/ RS_COLLECT_MSG_ERR, - /*0x07*/ RS_PARSE_MSG_ERR, - - // reserved values -// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) -}RS_StatusTypeDef; - - -/** @brief Enums for RS Modes */ -typedef enum // RS_ModeTypeDef -{ - SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting - SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout -// MASTER = 0x03, ///< Master mode -}RS_ModeTypeDef; - -/** @brief Enums for RS UART Modes */ -typedef enum // RS_ITModeTypeDef -{ - BLCK_MODE = 0x00, ///< Blocking mode - IT_MODE = 0x01, ///< Interrupt mode -}RS_ITModeTypeDef; - -/** @brief Enums for Abort modes */ -typedef enum // RS_AbortTypeDef -{ - ABORT_TX = 0x01, ///< Abort transmit - ABORT_RX = 0x02, ///< Abort receive - ABORT_RX_TX = 0x03, ///< Abort receive and transmit - ABORT_RS = 0x04, ///< Abort uart and reset RS structure -}RS_AbortTypeDef; - -/** @brief Enums for RX Size modes */ -typedef enum // RS_RXSizeTypeDef -{ - RS_RX_Size_Const = 0x01, ///< size of receiving message is constant - RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant -}RS_RXSizeTypeDef; - - -//-----------STRUCTURE FOR HANDLE RS------------ -/** @brief Struct for flags RS */ -typedef struct -{ - unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt - - unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy - unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data - - unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active - unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active - - unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done - unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done - - // setted by user - unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet - unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg - unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt - unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing -}RS_FlagsTypeDef; - - - -/** - * @brief Handle for RS communication. - * @note Prefixes: h - handle, s - settings, f - flag - */ -typedef struct // RS_HandleTypeDef -{ - /* MESSAGE */ - - - uint8_t ID; ///< ID of RS "channel" - RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct - uint8_t *pBufferPtr; ///< pointer to message buffer - uint32_t RS_Message_Size; ///< size of whole message, not only data - - /* HANDLERS and SETTINGS */ - UART_HandleTypeDef *huart; ///< handler for used uart - TIM_HandleTypeDef *htim; ///< handler for used tim - RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef - RS_ITModeTypeDef sRS_IT_Mode; ///< setting: 1 - IT mode, 0 - Blocking mode - uint16_t sRS_Timeout; ///< setting: timeout in ms - RS_RXSizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const - - /* FLAGS */ - RS_FlagsTypeDef f; ///< These flags for controling receive/transmit - - /* RS STATUS */ - RS_StatusTypeDef RS_STATUS; ///< RS status -}RS_HandleTypeDef; -extern RS_HandleTypeDef hmodbus1; - - -///////////////////////---STRUCTURES & ENUMS---////////////////////// - - -///////////////////////////////////////////////////////////////////// -///////////////////////////---FUNCTIONS---/////////////////////////// -//----------------FUNCTIONS FOR PROCESSING MESSAGE------------------- -/*--------------------Defined by users purposes--------------------*/ -/* Respond accord to received message */ -RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); - -/* Collect message in buffer to transmit it */ -RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); - -/* Parse message from buffer to process it */ -RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); - -/* Define size of RX Message that need to be received */ -RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size); - - -//-------------------------GENERAL FUNCTIONS------------------------- -/*-----------------Should be called from main code-----------------*/ -/* Start receive IT */ -RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); - -/* Start transmit IT */ -RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); - -/* Initialize UART and handle RS stucture */ -RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr); - -/* ReInitialize UART and RS receive */ -HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart); - -/* Abort RS/UART */ -RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode); -//-------------------------GENERAL FUNCTIONS------------------------- - - -//------------------------------------------------------------------- -//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- -/* Handle for starting receive */ -RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); -/* Handle for starting transmit */ -RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); -/* UART RX Callback: define behaviour after receiving parts of message */ -RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS); -/* UART TX Callback: define behaviour after transmiting message */ -RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS); -/* Handler for UART */ -void RS_UART_Handler(RS_HandleTypeDef *hRS); -/* Handler for TIM */ -void RS_TIM_Handler(RS_HandleTypeDef *hRS); -//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- -///////////////////////////---FUNCTIONS---/////////////////////////// - - -#ifndef printf_rs_err -#define printf_rs_err(...) -#endif - -#ifndef printf_rs -#define printf_rs(...) -#endif -#endif // __RS_LIB_H_