diff --git a/Core/Inc/main.h b/Core/Inc/main.h index 983d414..f392556 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -40,7 +40,7 @@ extern "C" { /* Exported variables prototypes ---------------------------------------------*/ /* Exported functions prototypes ---------------------------------------------*/ -void APP_ErrorHandler(void); +void Error_Handler(void); #ifdef __cplusplus } diff --git a/Core/Inc/py32f002b_hal_conf.h b/Core/Inc/py32f002b_hal_conf.h index aea4ac4..8fd2522 100644 --- a/Core/Inc/py32f002b_hal_conf.h +++ b/Core/Inc/py32f002b_hal_conf.h @@ -47,7 +47,7 @@ //#define HAL_LPTIM_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED //#define HAL_I2C_MODULE_ENABLED -//#define HAL_UART_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED //#define HAL_SPI_MODULE_ENABLED //#define HAL_EXTI_MODULE_ENABLED diff --git a/Core/Inc/tim.h b/Core/Inc/tim.h index b989320..14edb1c 100644 --- a/Core/Inc/tim.h +++ b/Core/Inc/tim.h @@ -33,6 +33,7 @@ extern "C" { /* USER CODE END Includes */ extern TIM_HandleTypeDef htim1; +extern TIM_HandleTypeDef htim14; /* USER CODE BEGIN Private defines */ diff --git a/Core/Inc/usart.h b/Core/Inc/usart.h new file mode 100644 index 0000000..b8f18ef --- /dev/null +++ b/Core/Inc/usart.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.h + * @brief This file contains all the function prototypes for + * the usart.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USART_H__ +#define __USART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern UART_HandleTypeDef huart1; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_USART1_UART_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USART_H__ */ + diff --git a/Core/Modbus/crc_algs.c b/Core/Modbus/crc_algs.c new file mode 100644 index 0000000..fcfa779 --- /dev/null +++ b/Core/Modbus/crc_algs.c @@ -0,0 +1,116 @@ +#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/Core/Modbus/crc_algs.h b/Core/Modbus/crc_algs.h new file mode 100644 index 0000000..5957880 --- /dev/null +++ b/Core/Modbus/crc_algs.h @@ -0,0 +1,9 @@ +#include "mylibs_include.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/Core/Modbus/interface_config.h b/Core/Modbus/interface_config.h new file mode 100644 index 0000000..1e1c45a --- /dev/null +++ b/Core/Modbus/interface_config.h @@ -0,0 +1,70 @@ +/** +************************************************************************** +* @file interface_config.h +* @brief Конфигурации для интерфейсов +************************************************************************** + * @defgroup INTERFACE_CONFIGS Configs for interfaces + * @brief Конфигурации для интерфейсов + * @details + @{ +*************************************************************************/ +#ifndef _INTERFACE_CONFIG_H_ +#define _INTERFACE_CONFIG_H_ + +/** + * @addtogroup MODBUS_CONFIG Конфигурации для модбас + * @ingroup INTERFACE_CONFIGS + * @ingroup MODBUS + @{ + */ + +#define MODBUS_VENDOR_NAME "NIO-12" +#define MODBUS_PRODUCT_CODE "12345" +#define MODBUS_REVISION "Ver. 1.0" +#define MODBUS_VENDOR_URL "https://git.arktika.cyou/Andrey/Diod_Test" +#define MODBUS_PRODUCT_NAME "Diode Tester" +#define MODBUS_MODEL_NAME "STM32F103" +#define MODBUS_USER_APPLICATION_NAME "diode_tester" + +//#define MODBUS_UART_NUMB 1 ///< Номер используемого UART, по нему выставляется дефайн USED_MB_UART = USARTx +#define MODBUS_SPEED 115200 ///< Скорость UART для модбас +//#define MODBUS_GPIOX GPIOA ///< Порт для UART RX/TX +//#define MODBUS_GPIO_PIN_RX GPIO_PIN_9 ///< Пин для UART RX +//#define MODBUS_GPIO_PIN_TX GPIO_PIN_10 ///< Пин для UART TX + +//#define MODBUS_TIM_NUMB 2 ///< number of used tim, accord to this define sets define USED_MB_TIM = TIMx +//#define MODBUS_TIM_AHB_FREQ 72 ///< TIM AHB Bus Freq + +// defines for modbus behaviour +#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства +//#define MODBUS_MAX_TIMEOUT 500 ///< максимальнйы тайтаут MB is ms + + +#define RS_UART_Init MX_USART1_UART_Init +#define RS_UART_DeInit HAL_UART_MspDeInit +#define RS_TIM_Init MX_TIM2_Init +#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit +#define rs_huart huart1 +#define rs_htim htim14 +/** + * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) + * @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS + * Поэтому чтобы считывать Input Regs - надо поменять их местами. + */ +//#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS + +///////////////////////////////////////////////////////////////////// +/////////////////////////---CALC DEFINES---////////////////////////// + +/** MODBUS_CONFIG + * @} + */ + + + + +/** INTERFACE_CONFIGS + * @} + */ + +#endif //_INTERFACE_CONFIG_H_ \ No newline at end of file diff --git a/Core/Modbus/modbus.c b/Core/Modbus/modbus.c new file mode 100644 index 0000000..73de147 --- /dev/null +++ b/Core/Modbus/modbus.c @@ -0,0 +1,1003 @@ +/** +************************************************************************** +* @file modbus.c +* @brief Модуль для реализации MODBUS. +************************************************************************** +* @par Функции и дефайны +* +* Defines: data access +* - MB_Set_Coil_Local() - Выставление коила по локальному адресу относительно начала массива +* - MB_Reset_Coil_Local() - Сброс коила по локальному адресу относительно начала массива +* - MB_Toogle_Coil_Local() - Переключение коила по локальному адресу относительно начала массива +* - MB_Read_Coil_Local() - Чтение коила по локальному адресу относительно начала массива +* +* Functions: data access +* - MB_Write_Coil_Global() - Запись 0/1 в один коил по глобальному адресу +* - MB_Read_Coil_Global() - Чтение одного коила по глобальному адресу +* +* Functions: process message +* - MB_DefineRegistersAddress() - Определение "начального" адреса регистров +* - MB_DefineCoilsAddress() - Определение "начального" адреса коилов +* - MB_Check_Address_For_Arr() - Определение принадлежит ли адресс Addr конкретному массиву +* - Обработка команд модбас +* - MB_Read_Coils(), +* - MB_Read_Hold_Regs(), +* - MB_Write_Single_Coil() +* - MB_Write_Miltuple_Coils() +* - MB_Write_Miltuple_Regs() +* +* Functions: RS functions +* - RS_Parse_Message() / RS_Collect_Message() - Заполнение структуры сообщения и буфера +* - RS_Response() - Ответ на комманду +* - RS_Define_Size_of_RX_Message() - Определение размера принимаемых данных +* - RS_Init() - Инициализация периферии и modbus handler +* +* Functions: initialization +* - MODBUS_FirstInit() - Инициализация modbus +* +************************************************************************** +* @par Данные для модбас +* +* Holding/Input Registers +* - Регистры представляют собой 16-битные числа (слова). В обработке комманд +* находится адресс "начального" регистра и записывается в указатель. Доступ к +* остальным регистрам осуществляется через указатель. Таким образом, сами +* регистры могут представлять собой как массив так и структуру. +* +* Coils +* - Коилы представляют собой биты, упакованные в 16-битные регистры. В обработке +* комманд находится адресс "начального" регистра запрашиваемого коила. Доступ к +* остальным коилам осуществляется через маску и указатель. Таким образом, сами +* коилы могут представлять собой как массив так и структуру. +* +@verbatim +EXAMPLE: INIT SLAVE RECEIVE + //--------------Настройка модбас--------------// + // set up UART for modbus + modbus1_suart.huart.Instance = USED_MODBUS_UART; + modbus1_suart.huart.Init.BaudRate = PROJSET.MB_SPEED; + modbus1_suart.GPIOx = GPIOB; + modbus1_suart.GPIO_PIN_RX = GPIO_PIN_11; + modbus1_suart.GPIO_PIN_TX = GPIO_PIN_10; + + // set up timeout TIM for modbus + modbus1_stim.htim.Instance = TIM7; + modbus1_stim.sTimAHBFreqMHz = 84; + modbus1_stim.sTimMode = TIM_IT_CONF; + + // set up modbus: MB_RX_Size_NotConst and Timeout enable + hmodbus1.ID = 1; + hmodbus1.sRS_Timeout = 5000; + hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; + hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; + + // INIT + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0); + + //----------------Прием модбас----------------// + RS_MsgTypeDef MODBUS_MSG; + RS_Receive_IT(&hmodbus1, &MODBUS_MSG); +@endverbatim +*************************************************************************/ + +#include "rs_message.h" +uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug +/* MODBUS HANDLES */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +UART_SettingsTypeDef modbus1_suart; +TIM_SettingsTypeDef modbus1_stim; +#else +extern UART_HandleTypeDef rs_huart; +extern TIM_HandleTypeDef rs_htim; +#endif +RS_HandleTypeDef hmodbus1; + +/* DEFINE REGISTERS/COILS */ +MB_DeviceIdentificationTypeDef MB_INFO; +MB_DataStructureTypeDef MB_DATA; +RS_MsgTypeDef MODBUS_MSG; + +uint32_t delay_scide = 1; +uint32_t numb_scide = 10; +//------------------------------------------------------------------- +//-----------------------------FOR USER------------------------------ +/** + * @brief First set up of MODBUS. + * @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас. + * Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1) + * ШИМ генерируется на одном канале. + * @note This called from main + */ +void MODBUS_FirstInit(void) +{ + MB_DevoceInentificationInit(); + //-----------SETUP MODBUS------------- + // set up UART for modbus +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + modbus1_suart.huart.Instance = USED_MODBUS_UART; + modbus1_suart.huart.Init.BaudRate = MODBUS_SPEED; + modbus1_suart.GPIOx = MODBUS_GPIOX; + modbus1_suart.GPIO_PIN_RX = MODBUS_GPIO_PIN_RX; + modbus1_suart.GPIO_PIN_TX = MODBUS_GPIO_PIN_TX; + + // set up timeout TIM for modbus + modbus1_stim.htim.Instance = USED_MODBUS_TIM; + modbus1_stim.sTimAHBFreqMHz = MODBUS_TIM_AHB_FREQ; + modbus1_stim.sTimMode = TIM_IT_CONF; + +#endif + // set up modbus: MB_RX_Size_NotConst and Timeout enable + hmodbus1.ID = MODBUS_DEVICE_ID; + hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; + hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; + + // INIT +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0); +#else + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, &rs_htim, 0); +#endif + + 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) + { + // Устаки для тестера + if(MB_Check_Address_For_Arr(Addr, Qnt, R_SETTINGS_ADDR, R_SETTINGS_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // начало регистров хранения/входных + } + // if address doesnt match any array - return illegal data address response + else + { + return ILLEGAL_DATA_ADDRESS; + } + } + else if(RegisterType == RegisterType_Input) + { + // Измеренные параметры диода + if(MB_Check_Address_For_Arr(Addr, Qnt, R_MEASURED_ADDR, R_MEASURED_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, 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 + } + + // tester settings coils + if(MB_Check_Address_For_Arr(Addr, Qnt, C_SETTINGS_ADDR, C_SETTINGS_QNT) == NO_ERRORS) + { + *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr); + }// tester control coils + else 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); + } + // 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) + { + TrackerCnt_Err(hmodbus->rs_err); + modbus_msg->Func_Code += ERR_VALUES_START; + } + else + { + TrackerCnt_Ok(hmodbus->rs_err); + } + + + } + + // 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 + { + TrackerCnt_Err(hmodbus->rs_err); + 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 + { + TrackerCnt_Err(hmodbus->rs_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------- + //-----------[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) + { + TrackerCnt_Err(hmodbus->rs_err); + 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) + { + TrackerCnt_Err(hmodbus->rs_err); + 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/Core/Modbus/modbus.h b/Core/Modbus/modbus.h new file mode 100644 index 0000000..d23e8a9 --- /dev/null +++ b/Core/Modbus/modbus.h @@ -0,0 +1,357 @@ +/** + ************************************************************************** + * @file modbus.h + * @brief Заголовочный файл модуля MODBUS. + * @details Данный файл необходимо подключить в rs_message.h. После подключать + * rs_message.h к основному проекту. + * + * @defgroup MODBUS + * @brief Modbus stuff + * + *************************************************************************/ +#ifndef __MODBUS_H_ +#define __MODBUS_H_ + +#include "mylibs_include.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 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 */ +#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) + +/** @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 +{ + 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 +#define CONCAT(a,b) a##b +#define Create_MODBUS_Handles(_modbus_) \ + UART_SettingsTypeDef CONCAT(_modbus_, _suart); \ + UART_HandleTypeDef CONCAT(_modbus_, _huart); \ + TIM_SettingsTypeDef CONCAT(_modbus_, _stim); \ + TIM_HandleTypeDef CONCAT(_modbus_, _htim); \ + RS_HandleTypeDef CONCAT(h, _modbus_) +//-------------------------------------------------- +/** 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/Core/Modbus/modbus_data.h b/Core/Modbus/modbus_data.h new file mode 100644 index 0000000..9fcb038 --- /dev/null +++ b/Core/Modbus/modbus_data.h @@ -0,0 +1,173 @@ +/** +************************************************************************** +* @file modbus_data.h +* @brief Заголовочный файл с описанием даты MODBUS. +* @details Данный файл необходимо подключается в rs_message.h. После rs_message.h +* подключается к основному проекту. +* +* @defgroup MODBUS_DATA +* @ingroup MODBUS +* @brief Modbus data description +* +*************************************************************************/ + +#ifndef _MODBUS_DATA_H_ +#define _MODBUS_DATA_H_ + +#include "stdint.h" +//--------------DEFINES FOR REGISTERS--------------- +// DEFINES FOR ARRAYS +/** + * @addtogroup MODBUS_DATA_RERISTERS_DEFINES + * @ingroup MODBUS_DATA + * @brief Defines for registers + Структура дефайна адресов + @verbatim + Для массивов регистров: + R__ADDR - модбас адресс первого регистра в массиве + R__QNT - количество регистров в массиве + + @endverbatim + * @{ + */ + + +/** + * @brief Регистры хранения + */ +typedef struct //MB_DataInRegsTypeDef +{ + uint16_t ForwardVoltage; + uint16_t ReversePeakVoltage; +}MB_DataInRegsTypeDef; + + +/** + * @brief Входные регистры + */ +typedef struct //MB_DataInRegsTypeDef +{ + uint16_t TimeForForward; + uint16_t TimeForReverse; + uint16_t TimeBeforeTest; + uint16_t TimeDeadtime; + uint16_t TimeBeforePeak; + + uint16_t Adc_PulseWidth; + uint16_t Adc_PulseSign; + uint16_t Adc_CalibrValue; + uint16_t Adc_ZeroValue; + uint16_t Adc_U_Calibr; +}MB_DataHoldRegsTypeDef; + + +// DEFINES FOR INPUT REGISTERS ARRAYS +#define R_MEASURED_ADDR 0 +#define R_MEASURED_QNT 2 + +// DEFINES FOR HOLDING REGISTERS ARRAYS +#define R_SETTINGS_ADDR 0 +#define R_SETTINGS_QNT 10 + + +// DEFINES FOR REGISTERS LOCAL ADDRESSES +//#define R_SET_ERROR(_te_num_) 0 + + +/** MODBUS_DATA_RERISTERS_DEFINES + * @} + */ + +//----------------DEFINES FOR COILS----------------- +/** + * @addtogroup MODBUS_DATA_COILS_DEFINES + * @ingroup MODBUS_DATA + * @brief Defines for coils + @verbatim + Структура дефайна + Для массивов коилов: + C__ADDR - модбас адресс первого коила в массиве + C__QNT - количество коилов в массиве (минимум 16) + + @endverbatim + * @{ + */ + + + +/** + * @brief Коилы + */ +typedef struct //MB_DataCoilsTypeDef +{ + /* reg 1 - control */ + unsigned ForwardTest:1; + unsigned ReverseTest:1; + unsigned StartTest:1; + unsigned KeyForwardHiTest:1; + unsigned KeyForwardLoTest:1; + unsigned KeyReverseHiTest:1; + unsigned KeyReverseLoTest:1; + + unsigned reserved:9; + + /* reg 2 - settings */ + unsigned msTimeForForward_enable:1; + unsigned msTimeForReverse_enable:1; + unsigned msTimeBeforeTest_enable:1; + unsigned msTimeDeadtime_enable:1; + unsigned msTimeBeforePeak_enable:1; + unsigned reserved2:11; +}MB_DataCoilsTypeDef; + +// DEFINES FOR COIL ARRAYS +#define C_CONTROL_ADDR 0 +#define C_CONTROL_QNT 7 + +#define C_SETTINGS_ADDR 16 +#define C_SETTINGS_QNT 5 + +/** MODBUS_DATA_COILS_DEFINES + * @} + */ + + +//-----------MODBUS DEVICE DATA SETTING------------- +// MODBUS DATA STRUCTTURE +/** + * @brief Структура со всеми регистрами и коилами модбас + * @ingroup MODBUS_DATA + */ +typedef struct // tester modbus data +{ + MB_DataInRegsTypeDef InRegs; ///< Modbus input registers @ref MB_DataInRegsTypeDef + + MB_DataCoilsTypeDef Coils; ///< Modbus coils @ref MB_DataCoilsTypeDef + + MB_DataHoldRegsTypeDef HoldRegs; ///< Modbus holding registers @ref MB_DataHoldRegsTypeDef +}MB_DataStructureTypeDef; +extern MB_DataStructureTypeDef MB_DATA; + + +typedef struct +{ + unsigned length; + char *name; +}MB_DeviceObjectTypeDef; +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_ + +///////////////////////////////////////////////////////////// +///////////////////////TEMP/OUTDATE/OTHER//////////////////// \ No newline at end of file diff --git a/Core/Modbus/rs_message.c b/Core/Modbus/rs_message.c new file mode 100644 index 0000000..46673d0 --- /dev/null +++ b/Core/Modbus/rs_message.c @@ -0,0 +1,598 @@ +/** +************************************************************************** +* @file rs_message.c +* @brief Модуль для реализации протоколов по RS/UART. +************************************************************************** + @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 + + Functions: uart initialize (это было в отдельных файлах, мб надо обратно разнести) + - UART_Base_Init Инициализация UART для RS + - RS_UART_GPIO_Init Инициализация GPIO для RS + - UART_DMA_Init Инициализация DMA для RS + - UART_MspInit Аналог HAL_MspInit для RS + - UART_MspDeInit Аналог HAL_MspDeInit для RS + + @endverbatim +*************************************************************************/ +#include "rs_message.h" + +uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer + +#ifndef INCLUDE_GENERAL_PERIPH_LIBS +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); +#endif + +//------------------------------------------------------------------- +//-------------------------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); + TrackerCnt_Err(hRS->rs_err); + } + else + { + RS_RES = RS_OK; + printf_rs("\n%d: RS: Start Receiving...", uwTick); + TrackerCnt_Ok(hRS->rs_err); + } + + 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); + TrackerCnt_Err(hRS->rs_err); + } + else + { + RS_RES = RS_OK; + printf_rs("\n%d: RS: Start Transmitting...", uwTick); + TrackerCnt_Ok(hRS->rs_err); + } + } + + + 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. + */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr) +#else +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr) +#endif +{ + // check that hRS is defined + if (hRS == NULL) + return RS_ERR; +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check that huart is defined + if ((suart->huart.Instance == NULL) || (suart->huart.Init.BaudRate == NULL)) + return RS_ERR; +#else + // check that huart is defined + if (huart == NULL) + return RS_ERR; +#endif + // init uart + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + UART_Base_Init(suart); + hRS->huart = &suart->huart; +#else +// RS_UART_Init(); + hRS->huart = huart; +#endif + + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check that timeout in interrupt needed + if (hRS->sRS_Timeout) + { + if (stim->htim.Instance == NULL) // check is timer defined + return RS_ERR; + + // calc frequency corresponding to timeout and tims 1ms tickbase + stim->sTickBaseUS = TIM_TickBase_1MS; + stim->htim.Init.Period = hRS->sRS_Timeout; + + TIM_Base_Init(stim); + hRS->htim = &stim->htim; + } +#else +// RS_TIM_Init(); + hRS->htim = htim; +#endif + + 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. + */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart) +#else +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart) +#endif +{ + HAL_StatusTypeDef RS_RES; + hRS->f.ReInit_UART = 0; + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check is settings are valid + if(Check_UART_Init_Struct(suart) != HAL_OK) + return HAL_ERROR; + + RS_Abort(hRS, ABORT_RS); + + UART_MspDeInit(&suart->huart); + + RS_RES = UART_Base_Init(suart); + +#else +// // 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(); + +#endif + + 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) + { + TrackerCnt_Err(hRS->rs_err); + } + + 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) + { + TrackerCnt_Err(hRS->rs_err); + } + + 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) + { + TrackerCnt_Err(hRS->rs_err); + 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 + TrackerCnt_Err(hRS->rs_err); + 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(). + */ +void RS_UART_Handler(RS_HandleTypeDef *hRS) +{ + HAL_UART_IRQHandler(hRS->huart); + //-------------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 + { + 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 + { + TrackerCnt_Err(hRS->rs_err); + /* 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(). + */ +void RS_TIM_Handler(RS_HandleTypeDef *hRS) +{ + HAL_TIM_IRQHandler(hRS->htim); + HAL_TIM_Base_Stop_IT(hRS->htim); + RS_Abort(hRS, ABORT_RS); + + 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/Core/Modbus/rs_message.h b/Core/Modbus/rs_message.h new file mode 100644 index 0000000..a3d525d --- /dev/null +++ b/Core/Modbus/rs_message.h @@ -0,0 +1,265 @@ +/** +************************************************************************** +* @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 "mylibs_include.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_TrackerTypeDef rs_err; +}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 */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr); +#else +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr); +#endif +/* ReInitialize UART and RS receive */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart); +#else +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart); +#endif +/* 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_ diff --git a/Core/MyLibs/bit_access.h b/Core/MyLibs/bit_access.h new file mode 100644 index 0000000..081983c --- /dev/null +++ b/Core/MyLibs/bit_access.h @@ -0,0 +1,249 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup BIT_ACCESS_DEFINES Bit access defines +* @ingroup MYLIBS_DEFINES +* @brief Всякое для доступа к битам в unsigned +*************************************************************************/ +#ifndef __BIT_ACCESS_H_ +#define __BIT_ACCESS_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup BIT_ACCESS_TYPEDEF Byte access typedefs + * @ingroup BIT_ACCESS_DEFINES + * @brief Дефайны юнионов для обращения к битам. + @{ + */ +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned reserved:4; + }bit; +}uint4_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned reserved:3; + }bit; +}uint5_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned reserved:2; + }bit; +}uint6_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned reserved:1; + }bit; +}uint7_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + }bit; +}uint8_BitTypeDef; + +typedef union +{ + uint16_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + }bit; +}uint16_BitTypeDef; + + +typedef union +{ + uint32_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + unsigned bit16:1; + unsigned bit17:1; + unsigned bit18:1; + unsigned bit19:1; + unsigned bit20:1; + unsigned bit21:1; + unsigned bit22:1; + unsigned bit23:1; + unsigned bit24:1; + unsigned bit25:1; + unsigned bit26:1; + unsigned bit27:1; + unsigned bit28:1; + unsigned bit29:1; + unsigned bit30:1; + unsigned bit31:1; + }bit; +}uint32_BitTypeDef; + + +typedef union +{ + uint64_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + unsigned bit16:1; + unsigned bit17:1; + unsigned bit18:1; + unsigned bit19:1; + unsigned bit20:1; + unsigned bit21:1; + unsigned bit22:1; + unsigned bit23:1; + unsigned bit24:1; + unsigned bit25:1; + unsigned bit26:1; + unsigned bit27:1; + unsigned bit28:1; + unsigned bit29:1; + unsigned bit30:1; + unsigned bit31:1; + unsigned bit32:1; + unsigned bit33:1; + unsigned bit34:1; + unsigned bit35:1; + unsigned bit36:1; + unsigned bit37:1; + unsigned bit38:1; + unsigned bit39:1; + unsigned bit40:1; + unsigned bit41:1; + unsigned bit42:1; + unsigned bit43:1; + unsigned bit44:1; + unsigned bit45:1; + unsigned bit46:1; + unsigned bit47:1; + unsigned bit48:1; + unsigned bit49:1; + unsigned bit50:1; + unsigned bit51:1; + unsigned bit52:1; + unsigned bit53:1; + unsigned bit54:1; + unsigned bit55:1; + unsigned bit56:1; + unsigned bit57:1; + unsigned bit58:1; + unsigned bit59:1; + unsigned bit60:1; + unsigned bit61:1; + unsigned bit62:1; + unsigned bit63:1; + }bit; +}uint64_BitTypeDef; +/** BIT_ACCESS_TYPEDEF + * @} + */ + +/** + * @addtogroup BIT_ACCESS_FUNCTIONS Byte access functions + * @ingroup BIT_ACCESS_DEFINES + * @brief Дефайны для обращения к битам в unsigned. + @{ + */ +#define uint8_bit(_uint8_, _bit_) (*(uint8_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint16_bit(_uint8_, _bit_) (*(uint16_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint32_bit(_uint8_, _bit_) (*(uint32_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint64_bit(_uint8_, _bit_) (*(uint64_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ + +/** BIT_ACCESS_FUNCTIONS + * @} + */ +#endif //__BIT_ACCESS_H_ \ No newline at end of file diff --git a/Core/MyLibs/general_gpio.c b/Core/MyLibs/general_gpio.c new file mode 100644 index 0000000..f5799cd --- /dev/null +++ b/Core/MyLibs/general_gpio.c @@ -0,0 +1,128 @@ +/** + ************************************************************************** + * @file general_gpio.c + * @brief Модуль для инициализации портов. + ************************************************************************** + @verbatim + //-------------------Функции-------------------// + Functions: users + - GPIO_Clock_Enable Инициализация тактирования порта + @endverbatim +***************************************************************************/ +#include "general_gpio.h" + +//------------------------------------------------------------------- +//------------------------GPIO INIT FUNCTIONS------------------------ + +HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx) +{ + HAL_StatusTypeDef status = HAL_OK; + // choose port for enable clock + if (GPIOx==GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (GPIOx==GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (GPIOx==GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); +#ifdef GPIOD + else if (GPIOx==GPIOD) + __HAL_RCC_GPIOD_CLK_ENABLE(); +#endif +#ifdef GPIOE + else if (GPIOx==GPIOE) + __HAL_RCC_GPIOE_CLK_ENABLE(); +#endif + else + status = HAL_ERROR; + + return status; +} + +//------------------------GPIO INIT FUNCTIONS------------------------ +//------------------------------------------------------------------- + + +//------------------------------------------------------------------- +//------------------------GPIO LED FUNCTIONS------------------------- + +/** + * @brief Включить светодиод + */ +void GPIO_LED_On(GPIO_LEDTypeDef *led) +{ + led->state = LED_IS_ON; + HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_ON); +} +/** + * @brief Выключить светодиод + */ +void GPIO_LED_Off(GPIO_LEDTypeDef *led) +{ + led->state = LED_IS_OFF; + HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_OFF); +} + +/** + * @brief Активировать моргание светодиодом + */ +void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period) +{ + led->state = LED_IS_BLINKING; + led->LED_Period = period; +} + +/** + * @brief Моргание светодиодом + */ +void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led) +{ + if(led->state == LED_IS_BLINKING) + { + uint32_t tickcurrent = HAL_GetTick(); + if((tickcurrent - led->tickprev) > led->LED_Period) + { + HAL_GPIO_TogglePin(led->LED_Port, led->LED_Pin); + led->tickprev = tickcurrent; + } + } +} +//------------------------GPIO LED FUNCTIONS------------------------- +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +//------------------------GPIO SW FUNCTIONS------------------------- + +/** + * @brief Считать состоянии кнопки запуска + */ +uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *sw) +{ + + if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON) + { + sw->Sw_PrevState = 1; + + if(sw->tickprev == 0) + sw->tickprev = HAL_GetTick(); + + if((HAL_GetTick() - sw->tickprev) > sw->Sw_FilterDelay) + { + if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON) + { + return 1; + } + else + { + sw->tickprev = 0; + return 0; + } + } + } + else + { + sw->Sw_PrevState = 0; + } + return 0; +} +//------------------------GPIO SW FUNCTIONS------------------------- +//------------------------------------------------------------------- \ No newline at end of file diff --git a/Core/MyLibs/general_gpio.h b/Core/MyLibs/general_gpio.h new file mode 100644 index 0000000..f107bf1 --- /dev/null +++ b/Core/MyLibs/general_gpio.h @@ -0,0 +1,88 @@ +/** + ************************************************************************** + * @file general_gpio.h + * @brief Заголовочный файл для модуля инициализации портов. + *************************************************************************/ +#ifndef __GPIO_GENERAL_H_ +#define __GPIO_GENERAL_H_ + +#include "mylibs_defs.h" + + +#define SPI_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \ + (((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \ + (((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \ + (((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \ + (0)) + + +#define TIM_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \ + (((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \ + (((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \ + (((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \ + (0)) + + +typedef enum +{ + LED_IS_OFF = 0, + LED_IS_ON = 1, + LED_IS_BLINKING = 2, + LED_IS_FADING = 3, +}GPIO_LEDStateTypeDef; + +typedef struct +{ + GPIO_LEDStateTypeDef state; + + GPIO_TypeDef *LED_Port; + uint32_t LED_Pin; + + uint32_t LED_Period; + uint32_t tickprev; +}GPIO_LEDTypeDef; + +typedef struct +{ + GPIO_TypeDef *Sw_Port; + uint32_t Sw_Pin; + + uint32_t Sw_PrevState; + uint32_t Sw_FilterDelay; + uint32_t tickprev; +}GPIO_SwitchTypeDef; + +///////////////////////////////////////////////////////////////////// +///////////////////////////---FUNCTIONS---/////////////////////////// +HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx); + +/* Считать состоянии кнопки запуска */ +uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *swstart); +/* Включить светодиод */ +void GPIO_LED_On(GPIO_LEDTypeDef *led); +/* Выключить светодиод */ +void GPIO_LED_Off(GPIO_LEDTypeDef *led); +/* Активировать моргание светодиодом */ +void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period); +/* Моргание светодиодом */ +void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led); +///////////////////////////---FUNCTIONS---/////////////////////////// + + +#ifndef LED_ON +#define LED_ON 0 +#endif + +#ifndef LED_0FF +#define LED_OFF 1 +#endif + +#ifndef SW_ON +#define SW_ON 0 +#endif + +#ifndef SW_0FF +#define SW_OFF 1 +#endif + +#endif // __GPIO_GENERAL_H_ diff --git a/Core/MyLibs/mylibs_config.h b/Core/MyLibs/mylibs_config.h new file mode 100644 index 0000000..982dff0 --- /dev/null +++ b/Core/MyLibs/mylibs_config.h @@ -0,0 +1,35 @@ +/** +************************************************************************** +* @file mylibs_config.h +* @brief Конфигурации для библиотек MyLibs +************************************************************************** +* @defgroup MYLIBS_CONFIG Configs My Libs +* @ingroup MYLIBS_ALL +* @brief Конфигурации для библиотек MyLibs +@{ +*************************************************************************/ +#ifndef __MYLIBS_CONFIG_H_ +#define __MYLIBS_CONFIG_H_ + +#include "py32f0xx_hal.h" + +// user includes +#include "interface_config.h" + + +#define RS_USER_VARS_NUMB 0 +#define ADC_USER_VARS_NUMB 0 +#define ADC_CH_USER_VARS_NUMB 0 + + +#define INCLUDE_BIT_ACCESS_LIB +#define INCLUDE_TRACKERS_LIB +#define INCLUDE_TRACE_LIB +//#define INCLUDE_GENERAL_PERIPH_LIBS +//#define FREERTOS_DELAY + + +/** MYLIBS_CONFIG + * @} + */ +#endif //__MYLIBS_CONFIG_H_ \ No newline at end of file diff --git a/Core/MyLibs/mylibs_defs.h b/Core/MyLibs/mylibs_defs.h new file mode 100644 index 0000000..fb7f008 --- /dev/null +++ b/Core/MyLibs/mylibs_defs.h @@ -0,0 +1,105 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup MYLIBS_DEFINES My Libs defines +* @brief Базовые дефайны для всего проекта +* +*************************************************************************/ +#ifndef __MYLIBS_DEFINES_H_ +#define __MYLIBS_DEFINES_H_ + +#include "mylibs_config.h" + +/*************************************************************************** +******************************ERROR_HANDLER********************************/ +/** + * @addtogroup ERROR_HANDLER_DEFINES Error Handler defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для определения функции обработки ошибок + @{ + */ + +/* extern Error_Handler from main.h */ +extern void Error_Handler(void); + +/* Define error handler for MyLibs */ +#define MyLibs_Error_Handler(_params_) Error_Handler(_params_) +/* If error handler not defined - set void */ +#ifndef MyLibs_Error_Handler +#define ((void)0U) +#endif // MyLibs_Error_Handler + +/** ERROR_HANDLER_DEFINES + * @} + */ + + +/*************************************************************************** +********************************ACCESS_DEFINES*****************************/ + +#define ClearStruct(_struct_) memset(&(_struct_), 0, sizeof(_struct_)) + + + +/*************************************************************************** +******************************DELAYS_DEFINES*******************************/ +/** + * @addtogroup DELAYS_DEFINES Delays defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для реализации задержек + @{ + */ + +#ifdef FREERTOS_DELAY + #define msDelay(_ms_) osDelay(_ms_) +#else + #define msDelay(_ms_) if(_ms_ != 0) HAL_Delay(_ms_-1) +#endif + +/** DELAYS_DEFINES + * @} + */ + + +/*************************************************************************** +*******************************MATH_DEFINES********************************/ +/** + * @addtogroup MATH_DEFINES Math defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для различных математических функций + @{ + */ + +/** + * @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 /* через мат выражение */ + +/** + * @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))) + +/** + * @brief Absolute + * @param x - Переменная для модудя. + * @return x (new) - Число по модулю. + * @details Берет число по модулю. Хз как работает библиотечный abs в stdlib.h, мб это быстрее, но вряд ли конечно. + */ +#define ABS(x) ( ((x) > 0)? (x) : -(x))? + +/** MATH_DEFINES + * @} + */ + +#endif //__MYLIBS_DEFINES_H_ \ No newline at end of file diff --git a/Core/MyLibs/mylibs_include.h b/Core/MyLibs/mylibs_include.h new file mode 100644 index 0000000..4785078 --- /dev/null +++ b/Core/MyLibs/mylibs_include.h @@ -0,0 +1,80 @@ +/** +************************************************************************** +* @file mylibs_include.h +* @brief Заголочный файл для всех библиотек +************************************************************************** +@details +Здесь нужно собрать библиотеки и дефайны, которые должны быть видны во всем проекте, +чтобы не подключать 100 инклюдов в каждом ".c" файле +************************************************************************** +* @defgroup MYLIBS_ALL My Libs +* @brief Все используемые MyLibs библиотеки +* +*************************************************************************/ +#ifndef __MYLIBS_INCLUDE_H_ +#define __MYLIBS_INCLUDE_H_ + +#include "mylibs_defs.h" + + +#ifdef ARM_MATH_CM4 + #include "arm_math.h" +#endif + + +#ifdef INCLUDE_BIT_ACCESS_LIB +#include "bit_access.h" +#endif + +#ifdef INCLUDE_TRACKERS_LIB +#include "trackers.h" +#endif + +#ifdef INCLUDE_TRACE_LIB +#include "trace.h" +#endif + + + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + +#include "general_flash.h" +#include "general_gpio.h" +#ifdef HAL_SPI_MODULE_ENABLED +#include "general_spi.h" +#endif +#ifdef HAL_UART_MODULE_ENABLED +#include "general_uart.h" +#endif +#ifdef HAL_TIM_MODULE_ENABLED +#include "general_tim.h" +#endif + +#endif //INCLUDE_GENERAL_PERIPH_LIBS + + + + +/////////////////////////---USER SETTINGS---///////////////////////// +// user includes +#include "stdlib.h" +#include "string.h" +#include "stdio.h" +#include "math.h" + +#include "main.h" +#include "modbus_data.h" +#include "general_gpio.h" + +/** @brief Struct for trackers for Measure */ +/** @brief Struct for trackers for RS */ +typedef TrackerTypeDef(RS_USER_VARS_NUMB) RS_TrackerTypeDef; +/** @brief Struct for trackers for ADC */ +typedef TrackerTypeDef(ADC_USER_VARS_NUMB) ADC_TrackerTypeDef; +/** @brief Struct for trackers for ADC Channel */ +typedef TrackerTypeDef(ADC_CH_USER_VARS_NUMB) ADCChannel_TrackerTypeDef; +/////////////////////////---USER SETTINGS---///////////////////////// + + +#endif // __MYLIBS_INCLUDE_H_ + diff --git a/Core/MyLibs/trace.h b/Core/MyLibs/trace.h new file mode 100644 index 0000000..0b4a87e --- /dev/null +++ b/Core/MyLibs/trace.h @@ -0,0 +1,80 @@ +/** +************************************************************************** +* @file trace.h +* @brief Заголочный файл для работы с трассировкой. +************************************************************************** +* @addtogroup TRACE Trace defines +* @ingroup MYLIBS_DEFINES +* @brief Дефайны для работы с трассировкой +*************************************************************************/ +#ifndef __TRACE_H_ +#define __TRACE_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup TRACE_SERIAL Serial trace defines + * @ingroup TRACE + * @brief Дефайны для работы с serial трассировкой + * @details Определяется дефайн my_printf() для работы с serial трассировкой: + - для RTT это будет вызов функции SEGGER_RTT_printf(), с подключением библиотеки SEGGER_RTT.h + - для SWO это будет просто printf(), но библиотеку STDOUT надо подключить самостоятельно: + + @verbatim + Manage Run-Time Environment -> Compiler -> I/O -> STDOUT + @endverbatim + + - Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют + @{ + */ +/* Выбор какой serial trace использовать */ +#ifdef SERIAL_TRACE_ENABLE + + #if defined(RTT_TRACE_ENABLE) + #undef SWO_TRACE_ENABLE + #include "SEGGER_RTT.h" + #define my_printf(...) SEGGER_RTT_printf(0, __VA_ARGS__) + #elif defined(SWO_TRACE_ENABLE) + #undef RTT_TRACE_ENABLE + #define my_printf(...) printf(__VA_ARGS__) + #else // NO_TRACE + #define my_printf(...) + #warning No trace is selected. Serial debug wont work. + #endif // RTT_TRACE_ENABLE/SWO_TRACE_ENABLE/NO_TRACE +#else //SERIAL_TRACE_ENABLE + #define my_printf(...) + #undef RTT_TRACE_ENABLE + #undef SWO_TRACE_ENABLE + +#endif //SERIAL_TRACE_ENABLE + +/** TRACE_SERIAL + * @} + */ + + +/** + * @addtogroup TRACE_GPIO GPIO trace defines + * @ingroup TRACE + * @brief Дефайны для работы с GPIO трассировкой + * @details Определяется дефайны для работы с GPIO трассировкой: + - TRACE_GPIO_RESET() - для сброса ножки GPIO (через BSRR) + - TRACE_GPIO_SET() - для выставления ножки GPIO (через BSRR) + + - Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют + @{ + */ +#ifndef GPIO_TRACE_ENABLE + #define TRACE_GPIO_RESET(_gpio_,_pin_) + #define TRACE_GPIO_SET(_gpio_,_pin_) +#else + #define TRACE_GPIO_RESET(_gpio_,_pin_) (_gpio_)->BSRR = ((_pin_)<<16) + #define TRACE_GPIO_SET(_gpio_,_pin_) (_gpio_)->BSRR = (((_pin_))) +#endif //GPIO_TRACE_ENABLE + + +/** TRACE_GPIO + * @} + */ + + +#endif //__TRACE_H_ \ No newline at end of file diff --git a/Core/MyLibs/trackers.h b/Core/MyLibs/trackers.h new file mode 100644 index 0000000..641d606 --- /dev/null +++ b/Core/MyLibs/trackers.h @@ -0,0 +1,141 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup MYLIBS_DEFINES My Libs defines +* @brief Базовые дефайны для всего проекта +* +*************************************************************************/ +#ifndef __TRACKERS_H_ +#define __TRACKERS_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup TRACKERS Trackers defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для работы с трекерами + * @details Есть дефайн для объявления структуры трекера: TrackerTypeDef(num_user_vars). + Структура состоит из следующих элементов: + - cnt_ok + - cnt_err + - cnt_warn + - user[num_user_vars] + Также есть ряд функций (дефайнов) для обращения к элементам этой структуры. + + + Если трассировка отключена, то все дефайны определяются как ничего и на производительность кода не влияют + + @par Пример: + Определяем typedef трекера измерений @ref Measure_TrackerTypeDef + + @verbatim + typedef TrackerTypeDef(MEASURE_USER_VARS_NUMB) Measure_TrackerTypeDef; + @endverbatim + + И через @ref Measure_TrackerTypeDef структура подключается в @ref TESTER_MeasureHandleTypeDef, а также + если необхожимо в другие структуру, например в структуру всех ошибок через указатель @ref TESTER_TrackerTypeDef + + @{ + */ + +#ifdef TRACKERS_ENABLE + /** + * @brief Структура для счетчиков отладки + * @param num_user_vars - количество пользовательских счетчиков + * @details Содержит счетчик для успешных событый (cnt_ok), + * счетчик для ошибок (cnt_err), счетчик для предупреждений (cnt_warn). + * + * Также есть возможность объявить пользовательские счетчики в + * количестве штук. + * + * Для работы с структурой можно использовать функции: + * - TrackerCnt_Ok() + * - TrackerCnt_Err() + * - TrackerCnt_Warn() + * - TrackerCnt_User() + * - TrackerWrite_User() + * - TrackerClear_All() + * - TrackerClear_Ok() + * - TrackerClear_Err() + * - TrackerClear_Warn() + * - TrackerClear_User() + * - TrackerClear_UserAll() + */ + #define TrackerTypeDef(num_user_vars) \ + struct \ + { \ + uint32_t cnt_ok; \ + uint32_t cnt_err; \ + uint32_t cnt_warn; \ + uint32_t user[num_user_vars]; \ + } + + /** @brief Получить количетство пользовательских переменных */ + #define num_of_usercnts(_user_) (sizeof(_user_) / sizeof(_user_[0])) + /** @brief Проверка существует ли указанная пользовательская переменная */ + #define assert_usertracker(_cntstruct_, _uservarnumb_) ((_uservarnumb_) < num_of_usercnts((_cntstruct_).user)) + /** @brief Условие для проверки существует ли указанная пользовательская переменная */ + #define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(assert_usertracker(_cntstruct_, _uservarnumb_)) + /** @brief Тернарный оператор для проверки существует ли указанная пользовательская переменная */ + #define tern_assert_usertracker(_cntstruct_, _uservarnumb_) (assert_usertracker(_cntstruct_, _uservarnumb_)) ? _uservarnumb_ : 0 + + + + /** + * @brief Запись числа в пользовательскую переменную + * @note Здесь нет проверки - существует ли пользовательская переменная! + * Есть возможность выйти за границы структуры!!! + * Чтобы этого избежать используете дефайн #ref assert_usertracker() + */ + #define TrackerGet_User(_cntstruct_, _uservarnumb_) (_cntstruct_).user[tern_assert_usertracker(_cntstruct_, _uservarnumb_)] + + + + /** @brief Инкрементирование счетчика успешных событий */ + #define TrackerCnt_Ok(_cntstruct_) (_cntstruct_).cnt_ok++ + /** @brief Инкрементирование счетчика ошибок */ + #define TrackerCnt_Err(_cntstruct_) (_cntstruct_).cnt_err++ + /** @brief Инкрементирование счетчика предупреждений */ + #define TrackerCnt_Warn(_cntstruct_) (_cntstruct_).cnt_warn++ + /** @brief Инкрементирование пользовательской переменной */ + #define TrackerCnt_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_]++; + /** @brief Запись числа в пользовательскую переменную */ + #define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = (_val_) + + /** @brief Очистка всей структуры */ + #define TrackerClear_All(_cntstruct_) memset(&(_cntstruct_), 0, sizeof(_cntstruct_)) + /** @brief Очистка счетчика успешных событий */ + #define TrackerClear_Ok(_cntstruct_) (_cntstruct_).cnt_ok = 0 + /** @brief Очистка счетчика ошибок */ + #define TrackerClear_Err(_cntstruct_) (_cntstruct_).cnt_err = 0 + /** @brief Очистка счетчика предупреждений */ + #define TrackerClear_Warn(_cntstruct_) (_cntstruct_).cnt_warn = 0 + /** @brief Очистка пользовательской переменной */ + #define TrackerClear_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = 0; + /** @brief Очистка всех пользовательских переменных */ + #define TrackerClear_UserAll(_cntstruct_) memset(&(_cntstruct_).user, 0, sizeof((_cntstruct_).user)) + +#else //TRACKERS_ENABLE + #define TrackerTypeDef(num_user_vars) void * + + #define num_of_usercnts(_user_) + #define assert_tracecnt(_cntstruct_, _uservarnumb_) + + #define TrackerCnt_Ok(_cntstruct_) + #define TrackerCnt_Err(_cntstruct_) + #define TrackerCnt_Warn(_cntstruct_) + #define TrackerCnt_User(_cntstruct_, _uservarnumb_) + #define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) + + /** @brief Очистка всей структуры */ + #define TrackerClear_All(_cntstruct_) + #define TrackerClear_Ok(_cntstruct_) + #define TrackerClear_Err(_cntstruct_) + #define TrackerClear_Warn(_cntstruct_) + #define TrackerClear_User(_cntstruct_) + #define TrackerClear_UserAll(_cntstruct_) + +#endif //TRACKERS_ENABLE + +#endif //__TRACKERS_H_ \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index fdcde63..953bef4 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -25,10 +25,10 @@ #include "gpio.h" #include "tim.h" #include "pch_sensors.h" +#include "rs_message.h" /* Private define ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ -uint32_t predelay = 10000; /* Private user code ---------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ @@ -41,6 +41,7 @@ static void APP_SystemClockConfig(void); int main(void) { __HAL_DBGMCU_FREEZE_TIM1(); + __HAL_DBGMCU_FREEZE_TIM14(); /* Reset of all peripherals, Initializes the Systick. */ HAL_Init(); @@ -84,7 +85,7 @@ static void APP_SystemClockConfig(void) /* Configure oscillator */ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - APP_ErrorHandler(); + Error_Handler(); } /* Clock source configuration */ @@ -95,20 +96,23 @@ static void APP_SystemClockConfig(void) /* Configure clock source */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { - APP_ErrorHandler(); + Error_Handler(); } } /** - * @brief Error executing function. - * @param None + * @brief This function is executed in case of error occurrence. * @retval None */ -void APP_ErrorHandler(void) +void Error_Handler(void) { + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); while (1) { } + /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT diff --git a/Core/Src/tim.c b/Core/Src/tim.c index 962adbe..21c69fb 100644 --- a/Core/Src/tim.c +++ b/Core/Src/tim.c @@ -25,6 +25,7 @@ /* USER CODE END 0 */ TIM_HandleTypeDef htim1; +TIM_HandleTypeDef htim14; /* TIM3 init function */ void MX_TIM1_Init(void) @@ -48,18 +49,18 @@ void MX_TIM1_Init(void) htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { - while(1); + Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) { - while(1); + Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { - while(1); + Error_Handler(); } /* USER CODE BEGIN TIM3_Init 2 */ @@ -67,19 +68,74 @@ void MX_TIM1_Init(void) } +/* TIM2 init function */ +void MX_TIM2_Init(void) +{ + + /* USER CODE BEGIN TIM2_Init 0 */ + + /* USER CODE END TIM2_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + + /* USER CODE BEGIN TIM2_Init 1 */ + + /* USER CODE END TIM2_Init 1 */ + htim14.Instance = TIM14; + htim14.Init.Prescaler = (HAL_RCC_GetPCLK1Freq()/1000000) - 1; + htim14.Init.CounterMode = TIM_COUNTERMODE_UP; + htim14.Init.Period = 50000; + htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim14) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim14, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim14, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM2_Init 2 */ + + /* USER CODE END TIM2_Init 2 */ + +} void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM1) { - /* USER CODE BEGIN TIM3_MspInit 0 */ + /* USER CODE BEGIN TIM1_MspInit 0 */ - /* USER CODE END TIM3_MspInit 0 */ - /* TIM3 clock enable */ + /* USER CODE END TIM1_MspInit 0 */ + /* TIM1 clock enable */ __HAL_RCC_TIM1_CLK_ENABLE(); - /* USER CODE BEGIN TIM3_MspInit 1 */ + /* USER CODE BEGIN TIM1_MspInit 1 */ - /* USER CODE END TIM3_MspInit 1 */ + /* USER CODE END TIM1_MspInit 1 */ + } + else if(tim_baseHandle->Instance==TIM14) + { + /* USER CODE BEGIN TIM14_MspInit 0 */ + + /* USER CODE END TIM14_MspInit 0 */ + /* TIM14 clock enable */ + __HAL_RCC_TIM14_CLK_ENABLE(); + + /* TIM14 interrupt Init */ + HAL_NVIC_SetPriority(TIM14_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM14_IRQn); + /* USER CODE BEGIN TIM14_MspInit 1 */ + + /* USER CODE END TIM14_MspInit 1 */ } } @@ -88,17 +144,31 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) if(tim_baseHandle->Instance==TIM1) { - /* USER CODE BEGIN TIM3_MspDeInit 0 */ + /* USER CODE BEGIN TIM1_MspDeInit 0 */ - /* USER CODE END TIM3_MspDeInit 0 */ + /* USER CODE END TIM1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM1_CLK_DISABLE(); - /* TIM3 interrupt Deinit */ + /* TIM1 interrupt Deinit */ HAL_NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); - /* USER CODE BEGIN TIM3_MspDeInit 1 */ + /* USER CODE BEGIN TIM1_MspDeInit 1 */ - /* USER CODE END TIM3_MspDeInit 1 */ + /* USER CODE END TIM1_MspDeInit 1 */ + } + else if(tim_baseHandle->Instance==TIM14) + { + /* USER CODE BEGIN TIM14_MspDeInit 0 */ + + /* USER CODE END TIM14_MspDeInit 0 */ + /* TIM14 clock disable */ + __HAL_RCC_TIM14_CLK_DISABLE(); + + /* TIM14 interrupt Deinit */ + HAL_NVIC_DisableIRQ(TIM14_IRQn); + /* USER CODE BEGIN TIM14_MspDeInit 1 */ + + /* USER CODE END TIM14_MspDeInit 1 */ } } diff --git a/Core/Src/usart.c b/Core/Src/usart.c index 8e6986b..66d3c09 100644 --- a/Core/Src/usart.c +++ b/Core/Src/usart.c @@ -7,7 +7,7 @@ ****************************************************************************** * @attention * - * Copyright (c) 2025 STMicroelectronics. + * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file @@ -46,7 +46,7 @@ void MX_USART1_UART_Init(void) huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; - if (HAL_HalfDuplex_Init(&huart1) != HAL_OK) + if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } @@ -66,18 +66,27 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration - PA9 ------> USART1_TX + + /* GPIO initialization + PB04:TX, + PB05:RX */ - GPIO_InitStruct.Pin = GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF1_USART1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Alternate = GPIO_AF1_USART1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ @@ -97,9 +106,12 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) /**USART1 GPIO Configuration PA9 ------> USART1_TX + PA10 ------> USART1_RX */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + /* USART1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ diff --git a/MDK-ARM/Project.uvguix.I b/MDK-ARM/Project.uvguix.I index c6c6e30..d95bbcc 100644 --- a/MDK-ARM/Project.uvguix.I +++ b/MDK-ARM/Project.uvguix.I @@ -6,7 +6,7 @@
### uVision Project, (C) Keil Software
- F:\Work\Projects\PY32\dallas\Core\Interfaces + F:\Work\Projects\PY32\dallas\Core\Src @@ -95,7 +95,7 @@ 466 Source Browser 500 - 166 + 300 @@ -135,8 +135,8 @@ 0 - 2252 - 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000001800000000000000010000002C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C6D61696E2E6300000000066D61696E2E6300000000C5D4F200FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C7063685F73656E736F72732E68000000000D7063685F73656E736F72732E6800000000FFDC7800FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C64616C6C61735F746F6F6C732E63000000000E64616C6C61735F746F6F6C732E6300000000BECEA100FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C7063685F73656E736F72732E63000000000D7063685F73656E736F72732E6300000000F0A0A100FFFFFFFF2E463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6477742E6800000000056477742E6800000000BCA8E100FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C64616C6C61735F746F6F6C732E68000000000E64616C6C61735F746F6F6C732E68000000009CC1B600FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F775F706F72742E6800000000096F775F706F72742E6800000000F7B88600FFFFFFFF2C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C6D61696E2E6800000000066D61696E2E6800000000D9ADC200FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F775F706F72742E6300000000096F775F706F72742E6300000000A5C2D700FFFFFFFF50463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C434D5349535C4465766963655C50593332463078785C496E636C7564655C70793332663030326278352E68000000000D70793332663030326278352E6800000000B3A6BE00FFFFFFFF2C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C6770696F2E6300000000066770696F2E6300000000EAD6A300FFFFFFFF52463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C496E635C7079333266303032625F68616C5F6770696F2E6800000000147079333266303032625F68616C5F6770696F2E6800000000F6FA7D00FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F6E65776972652E6300000000096F6E65776972652E6300000000B5E99D00FFFFFFFF3A463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C4D444B2D41524D5C737461727475705F70793332663030326278782E730000000015737461727475705F70793332663030326278782E73000000005FC3CF00FFFFFFFF2E463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6477742E6300000000056477742E6300000000C1838300FFFFFFFF39463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C647331386232305F6472697665722E630000000010647331386232305F6472697665722E6300000000CACAD500FFFFFFFF39463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C647331386232305F6472697665722E680000000010647331386232305F6472697665722E6800000000C5D4F200FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F6E65776972652E6800000000096F6E65776972652E6800000000FFDC7800FFFFFFFF4D463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C2E63000000000F7079333266303032625F68616C2E6300000000BECEA100FFFFFFFF52463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C5F6770696F2E6300000000147079333266303032625F68616C5F6770696F2E6300000000F0A0A100FFFFFFFF2B463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C74696D2E63000000000574696D2E6300000000BCA8E100FFFFFFFF2B463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C74696D2E68000000000574696D2E68000000009CC1B600FFFFFFFF3A463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C7079333266303032625F68616C5F636F6E662E6800000000147079333266303032625F68616C5F636F6E662E6800000000F7B88600FFFFFFFF51463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C5F7263632E6300000000137079333266303032625F68616C5F7263632E6300000000D9ADC200FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD5000100000000000000020000003A0100006600000090060000B1020000 + 3581 + 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000002700000024000000010000002C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C6D61696E2E6300000000066D61696E2E6300000000C5D4F200FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C7063685F73656E736F72732E68000000000D7063685F73656E736F72732E6800000000FFDC7800FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C64616C6C61735F746F6F6C732E63000000000E64616C6C61735F746F6F6C732E6300000000BECEA100FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C7063685F73656E736F72732E63000000000D7063685F73656E736F72732E6300000000F0A0A100FFFFFFFF2E463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6477742E6800000000056477742E6800000000BCA8E100FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C64616C6C61735F746F6F6C732E68000000000E64616C6C61735F746F6F6C732E68000000009CC1B600FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F775F706F72742E6800000000096F775F706F72742E6800000000F7B88600FFFFFFFF2C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C6D61696E2E6800000000066D61696E2E6800000000D9ADC200FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F775F706F72742E6300000000096F775F706F72742E6300000000A5C2D700FFFFFFFF50463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C434D5349535C4465766963655C50593332463078785C496E636C7564655C70793332663030326278352E68000000000D70793332663030326278352E6800000000B3A6BE00FFFFFFFF2C463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C6770696F2E6300000000066770696F2E6300000000EAD6A300FFFFFFFF52463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C496E635C7079333266303032625F68616C5F6770696F2E6800000000147079333266303032625F68616C5F6770696F2E6800000000F6FA7D00FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F6E65776972652E6300000000096F6E65776972652E6300000000B5E99D00FFFFFFFF3A463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C4D444B2D41524D5C737461727475705F70793332663030326278782E730000000015737461727475705F70793332663030326278782E73000000005FC3CF00FFFFFFFF2E463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6477742E6300000000056477742E6300000000C1838300FFFFFFFF39463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C647331386232305F6472697665722E630000000010647331386232305F6472697665722E6300000000CACAD500FFFFFFFF39463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C647331386232305F6472697665722E680000000010647331386232305F6472697665722E6800000000C5D4F200FFFFFFFF32463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C44616C6C61735C6F6E65776972652E6800000000096F6E65776972652E6800000000FFDC7800FFFFFFFF4D463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C2E63000000000F7079333266303032625F68616C2E6300000000BECEA100FFFFFFFF52463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C5F6770696F2E6300000000147079333266303032625F68616C5F6770696F2E6300000000F0A0A100FFFFFFFF2B463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C74696D2E63000000000574696D2E6300000000BCA8E100FFFFFFFF2B463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C74696D2E68000000000574696D2E68000000009CC1B600FFFFFFFF3A463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C496E635C7079333266303032625F68616C5F636F6E662E6800000000147079333266303032625F68616C5F636F6E662E6800000000F7B88600FFFFFFFF51463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C5F7263632E6300000000137079333266303032625F68616C5F7263632E6300000000D9ADC200FFFFFFFF3B463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C696E746572666163655F636F6E6669672E680000000012696E746572666163655F636F6E6669672E6800000000A5C2D700FFFFFFFF31463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C6D6F646275732E6300000000086D6F646275732E6300000000B3A6BE00FFFFFFFF35463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C72735F6D6573736167652E68000000000C72735F6D6573736167652E6800000000EAD6A300FFFFFFFF33463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C6372635F616C67732E68000000000A6372635F616C67732E6800000000F6FA7D00FFFFFFFF31463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C6D6F646275732E6800000000086D6F646275732E6800000000B5E99D00FFFFFFFF35463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C72735F6D6573736167652E63000000000C72735F6D6573736167652E63000000005FC3CF00FFFFFFFF53463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C496E635C7079333266303032625F68616C5F75736172742E6800000000157079333266303032625F68616C5F75736172742E6800000000C1838300FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D6F646275735C6D6F646275735F646174612E68000000000D6D6F646275735F646174612E6800000000CACAD500FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D794C6962735C67656E6572616C5F6770696F2E63000000000E67656E6572616C5F6770696F2E6300000000C5D4F200FFFFFFFF37463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D794C6962735C67656E6572616C5F6770696F2E68000000000E67656E6572616C5F6770696F2E6800000000FFDC7800FFFFFFFF36463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D794C6962735C6D796C6962735F646566732E68000000000D6D796C6962735F646566732E6800000000BECEA100FFFFFFFF38463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C4D794C6962735C6D796C6962735F636F6E6669672E68000000000F6D796C6962735F636F6E6669672E6800000000F0A0A100FFFFFFFF2D463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C75736172742E63000000000775736172742E6300000000BCA8E100FFFFFFFF52463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C447269766572735C5059333246303032425F48414C5F4472697665725C5372635C7079333266303032625F68616C5F756172742E6300000000147079333266303032625F68616C5F756172742E63000000009CC1B600FFFFFFFF39463A5C576F726B5C50726F6A656374735C505933325C64616C6C61735C436F72655C5372635C7079333266303032625F68616C5F6D73702E6300000000137079333266303032625F68616C5F6D73702E6300000000F7B88600FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD5000100000000000000020000003A0100006600000090060000B1020000 @@ -1830,8 +1830,8 @@ 59392 File - 2837 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000B616374696F6E2E72656164960000000000000014000B616374696F6E2E7265616400184F4E45574952455F5245434F564552595F54494D455F555305757374696D0773656E73524F4D1A50434853656E735F46696E64556E6B6E6F776E53656E736F7273096E6F745F666F756E640F4F6E655769726544656C61795F7577056874696D33055F4952516E0A4457545F435943434E540B6D6963726F7365636F6E640D73746D3332663178785F68616C035243430A4750494F5F50494E5F350A4750494F5F50494E5F340A4750494F5F50494E5F31064750494F465F054750494F46045243435F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E2280000002000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B46350000000000000000000000000100000001000000000000000000000001000000020021802280000000000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000021456E65726779204D6561737572656D656E742026776974686F75742044656275670000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000003002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000000002180E50100000000000078000000264B696C6C20416C6C20427265616B706F696E747320696E204163746976652050726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180E601000000000000790000002F4B696C6C20416C6C20427265616B706F696E747320696E204D756C74692D50726F6A65637420576F726B73706163650000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65C6030000 + 2865 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000B616374696F6E2E7265616496000000000000001400056874696D320454494D33064C45445F4F4E1355534152545F48616E646C65547970654465660848414C5F5541525410696E746572666163655F636F6E6669670012554152545F48616E646C65547970654465660B616374696F6E2E72656164184F4E45574952455F5245434F564552595F54494D455F555305757374696D0773656E73524F4D1A50434853656E735F46696E64556E6B6E6F776E53656E736F7273096E6F745F666F756E640F4F6E655769726544656C61795F7577056874696D33055F4952516E0A4457545F435943434E540B6D6963726F7365636F6E640D73746D3332663178785F68616C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E2280000002000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B46350000000000000000000000000100000001000000000000000000000001000000020021802280000000000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000021456E65726779204D6561737572656D656E742026776974686F75742044656275670000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000003002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000000002180E50100000000000078000000264B696C6C20416C6C20427265616B706F696E747320696E204163746976652050726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180E601000000000000790000002F4B696C6C20416C6C20427265616B706F696E747320696E204D756C74692D50726F6A65637420576F726B73706163650000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65C6030000 1423 @@ -3628,12 +3628,12 @@ 0 100 - 0 + 36 ..\Core\Src\main.c - 22 - 35 - 54 + 17 + 12 + 88 1 0 @@ -3650,8 +3650,8 @@ ..\Core\Dallas\dallas_tools.c 0 - 186 - 208 + 42 + 43 1 0 @@ -3694,9 +3694,9 @@ ..\Core\Inc\main.h - 22 - 1 - 33 + 29 + 16 + 39 1 0 @@ -3811,27 +3811,27 @@ ..\Core\Src\tim.c - 32 - 29 - 46 + 24 + 1 + 28 1 0 ..\Core\Inc\tim.h - 30 + 0 7 - 35 + 36 1 0 ..\Core\Inc\py32f002b_hal_conf.h - 14 + 19 28 - 46 + 47 1 0 @@ -3845,6 +3845,141 @@ 0 + + ..\Core\Modbus\interface_config.h + 57 + 22 + 43 + 1 + + 0 + + + ..\Core\Modbus\modbus.c + 58 + 103 + 340 + 1 + + 0 + + + ..\Core\Modbus\rs_message.h + 7 + 1 + 30 + 1 + + 0 + + + ..\Core\Modbus\crc_algs.h + 24 + 1 + 1 + 1 + + 0 + + + ..\Core\Modbus\modbus.h + 30 + 31 + 265 + 1 + + 0 + + + ..\Core\Modbus\rs_message.c + 74 + 206 + 237 + 1 + + 0 + + + ..\Drivers\PY32F002B_HAL_Driver\Inc\py32f002b_hal_usart.h + 60 + 482 + 513 + 1 + + 0 + + + ..\Core\Modbus\modbus_data.h + 29 + 4 + 18 + 1 + + 0 + + + ..\Core\MyLibs\general_gpio.c + 55 + 38 + 54 + 1 + + 0 + + + ..\Core\MyLibs\general_gpio.h + 6 + 56 + 82 + 1 + + 0 + + + ..\Core\MyLibs\mylibs_defs.h + 15 + 1 + 13 + 1 + + 0 + + + ..\Core\MyLibs\mylibs_config.h + 0 + 3 + 15 + 1 + + 0 + + + ..\Core\Src\usart.c + 26 + 10 + 19 + 1 + + 0 + + + ..\Drivers\PY32F002B_HAL_Driver\Src\py32f002b_hal_uart.c + 17 + 335 + 345 + 1 + + 0 + + + ..\Core\Src\py32f002b_hal_msp.c + 0 + 12 + 1 + 1 + + 0 + diff --git a/MDK-ARM/Project.uvoptx b/MDK-ARM/Project.uvoptx index 22ceaa8..3c1c417 100644 --- a/MDK-ARM/Project.uvoptx +++ b/MDK-ARM/Project.uvoptx @@ -411,6 +411,18 @@ 0 0 0 + ..\Core\Src\usart.c + usart.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 ..\Core\Src\py32f002b_hal_msp.c py32f002b_hal_msp.c 0 @@ -418,7 +430,7 @@ 2 - 8 + 9 1 0 0 @@ -438,7 +450,7 @@ 0 3 - 9 + 10 1 0 0 @@ -450,7 +462,7 @@ 3 - 10 + 11 1 0 0 @@ -462,7 +474,7 @@ 3 - 11 + 12 1 0 0 @@ -474,7 +486,7 @@ 3 - 12 + 13 1 0 0 @@ -486,7 +498,7 @@ 3 - 13 + 14 1 0 0 @@ -498,7 +510,7 @@ 3 - 14 + 15 1 0 0 @@ -510,7 +522,7 @@ 3 - 15 + 16 1 0 0 @@ -522,7 +534,7 @@ 3 - 16 + 17 1 0 0 @@ -534,7 +546,7 @@ 3 - 17 + 18 1 0 0 @@ -544,6 +556,18 @@ 0 0 + + 3 + 19 + 1 + 0 + 0 + 0 + ..\Drivers\PY32F002B_HAL_Driver\Src\py32f002b_hal_uart.c + py32f002b_hal_uart.c + 0 + 0 + @@ -554,7 +578,7 @@ 0 4 - 18 + 20 1 0 0 @@ -566,7 +590,7 @@ 4 - 19 + 21 5 0 0 @@ -578,7 +602,7 @@ 4 - 20 + 22 1 0 0 @@ -590,7 +614,7 @@ 4 - 21 + 23 5 0 0 @@ -602,7 +626,7 @@ 4 - 22 + 24 1 0 0 @@ -614,7 +638,7 @@ 4 - 23 + 25 5 0 0 @@ -626,7 +650,7 @@ 4 - 24 + 26 1 0 0 @@ -638,7 +662,7 @@ 4 - 25 + 27 5 0 0 @@ -650,7 +674,7 @@ 4 - 26 + 28 1 0 0 @@ -662,7 +686,7 @@ 4 - 27 + 29 5 0 0 @@ -674,6 +698,214 @@ + + Modbus + 1 + 0 + 0 + 0 + + 5 + 30 + 1 + 0 + 0 + 0 + ..\Core\Modbus\crc_algs.c + crc_algs.c + 0 + 0 + + + 5 + 31 + 5 + 0 + 0 + 0 + ..\Core\Modbus\crc_algs.h + crc_algs.h + 0 + 0 + + + 5 + 32 + 5 + 0 + 0 + 0 + ..\Core\Modbus\interface_config.h + interface_config.h + 0 + 0 + + + 5 + 33 + 1 + 0 + 0 + 0 + ..\Core\Modbus\modbus.c + modbus.c + 0 + 0 + + + 5 + 34 + 5 + 0 + 0 + 0 + ..\Core\Modbus\modbus.h + modbus.h + 0 + 0 + + + 5 + 35 + 5 + 0 + 0 + 0 + ..\Core\Modbus\modbus_data.h + modbus_data.h + 0 + 0 + + + 5 + 36 + 1 + 0 + 0 + 0 + ..\Core\Modbus\rs_message.c + rs_message.c + 0 + 0 + + + 5 + 37 + 5 + 0 + 0 + 0 + ..\Core\Modbus\rs_message.h + rs_message.h + 0 + 0 + + + + + MyLibs + 1 + 0 + 0 + 0 + + 6 + 38 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\bit_access.h + bit_access.h + 0 + 0 + + + 6 + 39 + 1 + 0 + 0 + 0 + ..\Core\MyLibs\general_gpio.c + general_gpio.c + 0 + 0 + + + 6 + 40 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\general_gpio.h + general_gpio.h + 0 + 0 + + + 6 + 41 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_config.h + mylibs_config.h + 0 + 0 + + + 6 + 42 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_defs.h + mylibs_defs.h + 0 + 0 + + + 6 + 43 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_include.h + mylibs_include.h + 0 + 0 + + + 6 + 44 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\trace.h + trace.h + 0 + 0 + + + 6 + 45 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\trackers.h + trackers.h + 0 + 0 + + + ::CMSIS 0 diff --git a/MDK-ARM/Project.uvprojx b/MDK-ARM/Project.uvprojx index 9ff1824..820c47e 100644 --- a/MDK-ARM/Project.uvprojx +++ b/MDK-ARM/Project.uvprojx @@ -341,7 +341,7 @@ USE_HAL_DRIVER,PY32F002Bx5 - ..\Core\Inc;..\Drivers\CMSIS\Include;..\Drivers\CMSIS\Device\PY32F0xx\Include;..\Drivers\PY32F002B_HAL_Driver\Inc;..\Core\Dallas + ..\Core\Inc;..\Drivers\CMSIS\Include;..\Drivers\CMSIS\Device\PY32F0xx\Include;..\Drivers\PY32F002B_HAL_Driver\Inc;..\Core\Dallas;..\Core\Modbus;..\Core\MyLibs @@ -420,6 +420,11 @@ 1 ..\Core\Src\tim.c + + usart.c + 1 + ..\Core\Src\usart.c + py32f002b_hal_msp.c 1 @@ -480,6 +485,11 @@ 1 ..\Drivers\PY32F002B_HAL_Driver\Src\py32f002b_hal_tim_ex.c + + py32f002b_hal_uart.c + 1 + ..\Drivers\PY32F002B_HAL_Driver\Src\py32f002b_hal_uart.c + @@ -537,6 +547,96 @@ + + Modbus + + + crc_algs.c + 1 + ..\Core\Modbus\crc_algs.c + + + crc_algs.h + 5 + ..\Core\Modbus\crc_algs.h + + + interface_config.h + 5 + ..\Core\Modbus\interface_config.h + + + modbus.c + 1 + ..\Core\Modbus\modbus.c + + + modbus.h + 5 + ..\Core\Modbus\modbus.h + + + modbus_data.h + 5 + ..\Core\Modbus\modbus_data.h + + + rs_message.c + 1 + ..\Core\Modbus\rs_message.c + + + rs_message.h + 5 + ..\Core\Modbus\rs_message.h + + + + + MyLibs + + + bit_access.h + 5 + ..\Core\MyLibs\bit_access.h + + + general_gpio.c + 1 + ..\Core\MyLibs\general_gpio.c + + + general_gpio.h + 5 + ..\Core\MyLibs\general_gpio.h + + + mylibs_config.h + 5 + ..\Core\MyLibs\mylibs_config.h + + + mylibs_defs.h + 5 + ..\Core\MyLibs\mylibs_defs.h + + + mylibs_include.h + 5 + ..\Core\MyLibs\mylibs_include.h + + + trace.h + 5 + ..\Core\MyLibs\trace.h + + + trackers.h + 5 + ..\Core\MyLibs\trackers.h + + + ::CMSIS