Полноценно запустилось в матлаб корректно. УПП может плавно открывать тиристоры пачкой импульсов

Начата работа над управлением УПП по командам
This commit is contained in:
Razvalyaev 2025-11-16 19:40:40 +03:00
parent bb5b9886d7
commit b0813fb7e8
38 changed files with 1374 additions and 288 deletions

View File

@ -16,6 +16,7 @@ MCU_CortexMemoryTypeDef MCU_CORTEX_MEM;
// MCU PERIPH INIT // MCU PERIPH INIT
void Initialize_Periph_Sim(void) void Initialize_Periph_Sim(void)
{ {
uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000);
Init_TIM_SIM(); Init_TIM_SIM();
Init_ADC_SIM(); Init_ADC_SIM();
} }

View File

@ -15,7 +15,6 @@
"Initialize_Periph_Sim()" "Initialize_Periph_Sim()"
], ],
"PeriphSimulation": [ "PeriphSimulation": [
"uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000)",
"Simulate_Periph_Sim()" "Simulate_Periph_Sim()"
], ],
"PeriphDeinit": [ "PeriphDeinit": [

View File

@ -55,7 +55,7 @@
// INPUT/OUTPUTS PARAMS START // INPUT/OUTPUTS PARAMS START
#define IN_PORT_NUMB 2 #define IN_PORT_NUMB 2
#define ADC_PORT_1_WIDTH 6 #define ADC_PORT_1_WIDTH 6
#define IN_PORT_2_WIDTH 1 #define IN_PORT_2_WIDTH 16
#define OUT_PORT_NUMB 3 #define OUT_PORT_NUMB 3
#define THYR_PORT_1_WIDTH 6 #define THYR_PORT_1_WIDTH 6

View File

@ -24,6 +24,7 @@ void app_init(void) {
MX_TIM8_Init(); MX_TIM8_Init();
MX_TIM5_Init(); MX_TIM5_Init();
MX_ADC3_Init(); MX_ADC3_Init();
UPP_SetDefault(1, 1);
UPP_Init(); UPP_Init();
UPP_PreWhile(); UPP_PreWhile();

View File

@ -8,7 +8,7 @@
float dbg[16]; float dbg[16];
#define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 0 : 1 #define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 1 : 0
void Write_Thyristors(real_T* Buffer, int ind_port) void Write_Thyristors(real_T* Buffer, int ind_port)
{ {
@ -66,6 +66,7 @@ void app_readInputs(const real_T* Buffer) {
ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5)); ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5));
alpha_dbg = ReadInputArray(1, 0); alpha_dbg = ReadInputArray(1, 0);
upp.call->go = ReadInputArray(1, 1);
// USER APP INPUT END // USER APP INPUT END
} }
@ -83,19 +84,19 @@ void app_writeOutputBuffer(real_T* Buffer) {
int nn = 0; int nn = 0;
//WriteOutputArray(upp.hangle.htim->Instance->CNT, 2, nn++); //WriteOutputArray(upp.hangle.htim->Instance->CNT, 2, nn++);
//WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++); WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++);
//WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++); WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++);
//WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++); WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++);
//WriteOutputArray(dbg[0], 2, nn++); //WriteOutputArray(dbg[0], 2, nn++);
//WriteOutputArray(dbg[1], 2, nn++); //WriteOutputArray(dbg[1], 2, nn++);
//WriteOutputArray(dbg[2], 2, nn++); //WriteOutputArray(dbg[2], 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++);
//WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++); WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++);
// USER APP OUTPUT END // USER APP OUTPUT END
} }

View File

@ -9,7 +9,15 @@
void app_step(void) void app_step(void)
{ {
// USER APP STEP START // USER APP STEP START
UPP_While();
static uint32_t uwTickPrev = 0;
if (uwTickPrev != uwTick)
{
uwTickPrev = uwTick;
UPP_Tick();
}
// USER APP STEP END // USER APP STEP END
} }

Binary file not shown.

@ -1 +1 @@
Subproject commit 3aa279736d9383a06613f72d7b7462f0f23d7d4d Subproject commit e0ce0e6dbf35d035175d30971442bc8d99f3bdd7

@ -1 +1 @@
Subproject commit 1cc886aa8dc5c2fcfdad93a21207793b2cd85fab Subproject commit 272642b310043355b0af95e0410afbbcb74d17b7

View File

@ -16,7 +16,7 @@
******************************************************************************/ ******************************************************************************/
#ifndef __SPI_MEMORY_CONFIG_H_ #ifndef __SPI_MEMORY_CONFIG_H_
#define __SPI_MEMORY_CONFIG_H_ #define __SPI_MEMORY_CONFIG_H_
#include "upp_config.h" #include "upp_defs.h"
/////////////////////////---USER SETTINGS---///////////////////////// /////////////////////////---USER SETTINGS---/////////////////////////

View File

@ -19,7 +19,7 @@
******************************************************************************/ ******************************************************************************/
#ifndef _MODBUS_CONFIG_H_ #ifndef _MODBUS_CONFIG_H_
#define _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_
#include "upp_config.h" #include "upp_defs.h"
// Общие параметры // Общие параметры
#define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus #define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus

View File

@ -22,6 +22,9 @@
#include "modbus_inputregs.h" #include "modbus_inputregs.h"
#include "modbus_devid.h" #include "modbus_devid.h"
/* DEFINE DATA FOR MODBUS */
MB_DataStructureTypeDef MB_DATA = {0};; ///< Coils & Registers
MB_DataInternalTypeDef MB_INTERNAL;
/** /**
* @brief Check is address valid for certain array. * @brief Check is address valid for certain array.
@ -78,6 +81,10 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u
{ {
*pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр
} }
else if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_PRVT_PARAMS_ADR, R_HOLDING_PRVT_PARAMS_QNT) == ET_NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_INTERNAL, Addr - R_HOLDING_PRVT_PARAMS_ADR); // указатель на выбранный по Addr регистр
}
// if address doesnt match any array - return illegal data address response // if address doesnt match any array - return illegal data address response
else else
{ {

View File

@ -51,19 +51,23 @@
#ifndef _MODBUS_DATA_H_ #ifndef _MODBUS_DATA_H_
#define _MODBUS_DATA_H_ #define _MODBUS_DATA_H_
#include "upp_defs.h"
#include "upp_control.h"
#include "stdint.h" #include "stdint.h"
//--------------SIZES OF DATA--------------- //--------------SIZES OF DATA---------------
#define R_HOLDING_PRVT_PARAMS_ADR 555
#define R_HOLDING_PRVT_PARAMS_QNT (sizeof(UPP_PrvtParams_t)/sizeof(uint16_t))
// DEFINES FOR INPUT REGISTERS ARRAYS // DEFINES FOR INPUT REGISTERS ARRAYS
#define R_INPUT_ADDR 0 ///< Начальный адрес входных регистров #define R_INPUT_ADDR 0 ///< Начальный адрес входных регистров
#define R_INPUT_QNT 16 ///< Количество входных регистров #define R_INPUT_QNT (sizeof(UPP_PUI_Values_t)/sizeof(uint16_t)) ///< Количество входных регистров
// DEFINES FOR HOLDING REGISTERS ARRAYS // DEFINES FOR HOLDING REGISTERS ARRAYS
#define R_HOLDING_ADDR 0 ///< Начальный адрес регистров хранения #define R_HOLDING_ADDR 0 ///< Начальный адрес регистров хранения
#define R_HOLDING_QNT 16 ///< Количество регистров хранения #define R_HOLDING_QNT (sizeof(UPP_PUI_Params_t)/sizeof(uint16_t)) ///< Количество регистров хранения
// DEFINES FOR COIL ARRAYS // DEFINES FOR COIL ARRAYS
#define C_COILS_ADDR 0 ///< Начальный адрес коилов #define C_COILS_ADDR 0 ///< Начальный адрес коилов
@ -89,7 +93,7 @@
*/ */
typedef struct //MB_DataInRegsTypeDef typedef struct //MB_DataInRegsTypeDef
{ {
uint16_t in[16]; UPP_PUI_Values_t pui;
}MB_DataInRegsTypeDef; }MB_DataInRegsTypeDef;
@ -98,7 +102,7 @@ typedef struct //MB_DataInRegsTypeDef
*/ */
typedef struct //MB_DataInRegsTypeDef typedef struct //MB_DataInRegsTypeDef
{ {
uint16_t out[16]; UPP_PUI_Params_t pui_params;
}MB_DataHoldRegsTypeDef; }MB_DataHoldRegsTypeDef;
@ -153,6 +157,13 @@ typedef struct // tester modbus data
extern MB_DataStructureTypeDef MB_DATA; extern MB_DataStructureTypeDef MB_DATA;
typedef struct
{
UPP_FuncCalls_t FuncCalls;
UPP_PrvtParams_t param;
}MB_DataInternalTypeDef;
extern MB_DataInternalTypeDef MB_INTERNAL;
#endif //_MODBUS_DATA_H_ #endif //_MODBUS_DATA_H_
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////

View File

@ -10,7 +10,7 @@
*************************************************************************/ *************************************************************************/
#ifndef __MYLIBS_CONFIG_H_ #ifndef __MYLIBS_CONFIG_H_
#define __MYLIBS_CONFIG_H_ #define __MYLIBS_CONFIG_H_
#include "upp_config.h" #include "upp_defs.h"
// user includes // user includes
/** /**

View File

@ -27,39 +27,58 @@
#define TEMP_1 0 #define TEMP_1 0
#define TEMP_2 1 #define TEMP_2 1
/* Дефайны для базовых величин */
#define PM_U_BASE 1216.0
#define PM_I_BASE 53.0
/* Дефайны для настройки мониторинга питания */
#define PM_ADC_PERIOD_MKS 10
#define PM_ZERO_CROSS_HYSTERESIS_V 10
#define PM_ZERO_CROSS_DEBOUNCE_10US 2.5*100 // (2.5 * 100 = 2.5 мс)
/* Рассчитанные дефайны */
#define PM_ADC_PERIOD (180*PM_ADC_PERIOD_MKS)-1
/* Общие для всего проекта структуры*/
/**
* @brief Состояния полуволны
*/
typedef enum {
UPP_WAVE_UNKNOWED = 0,
UPP_WAVE_POSITIVE,
UPP_WAVE_NEGATIVE
} UPP_HalfWave_t;
/** /**
* @brief Названия Фаз * @addtogroup UPP_DEFAULT_PARAMS Default params for external flash
* @ingroup UPP_CONFIG
* @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке
* @{
*/ */
typedef enum { /* Параметры ПУИ */
UPP_PHASE_A = 0, #define PUI_Iref_PERCENT_DEFAULT 150
UPP_PHASE_B = 1, #define PUI_Tnt_MS_DEFAULT 300
UPP_PHASE_C = 2, #define PUI_Umin_PERCENT_DEFAULT 80
UPP_PHASE_UNKNOWN = 3 #define PUI_Umax_PERCENT_DEFAULT 120
} UPP_Phase_t; #define PUI_Imax_PERCENT_DEFAULT 99
#define PUI_Imin_PERCENT_DEFAULT 7
#define PUI_TiMax_US_DEFAULT 5000
#define PUI_Tdelay_SECONDS_DEFAULT 30
#define PUI_Interlace_EN_DEFAULT 5000
/* Параметры АЦП */
#define ADC_U_MAX_V_DEFAULT 1216.0
#define ADC_I_MAX_A_DEFAULT 53.0
#define ADC_U_ZERO_DEFAULT 2048
#define ADC_I_ZERO_DEFAULT 2048
/* Параметры определения перехода через ноль */
#define ZERO_CROSS_HYSTERESIS_V_DEFAULT 10.0
#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2.5*100 // (2.5 * 100 = 2.5 мс)
/* Параметры ШИМ для тиристоров */
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000
#define PWM_THYR_PULSE_NUMBER_DEFAULT 20
/** //UPP_DEFAULT_PARAMS
* @}
*/
/**
* @addtogroup UPP_COMPILED_PARAMS Fixed params
* @ingroup UPP_CONFIG
* @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять
* @{
*/
#define PM_U_NOM_V 690
#define PM_I_NOM_V 5
#define PM_F_NOM_HZ 50
#define PM_ADC_PERIOD_MKS 10 ///< Период опроса АЦП в мкс
/* Частоты таймеров в МГц*/
#define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП
#define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы)
#define PWM_TIM3_FREQ_MHZ 90 ///< Частота тиков таймера ШИМ (5-6 каналы)
#define ANGLE_TIM2_FREQ_MHZ 90 ///< Частота тиков таймера отсчета угла открытия тиристоров
#endif //_UPP_CONFIG_H_ #endif //_UPP_CONFIG_H_

178
UPP/Core/Configs/upp_defs.h Normal file
View File

@ -0,0 +1,178 @@
/**
******************************************************************************
* @file upp_defs.h
* @brief Общие дефайны УПП
******************************************************************************
@addtogroup UPP_DEFS UPP defines
@ingroup UPP_MAIN
@brief Общие дефайны для всего проекта УПП
@{
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_DEFS_H_
#define _UPP_DEFS_H_
#include "upp_config.h"
/**
* @addtogroup UPP_HIGHLEVEL Defines for high-level
* @ingroup UPP_DEFS
* @brief Дефайны УПП которые определяют коды ошибок и параметры для общения с верхним уровнем
* @{
*/
/**
* @brief Список аварий УПП
*/
typedef enum {
WM_Not_Init = 0, ///< УПП не инициализирован
WM_Ready = 1, ///< УПП в готовности
WM_Running = 2, ///< УПП в работе, управляет тиристорами
WM_Error = 3, ///< УПП в аварии
} UPP_WorkModeType_t;
/**
* @brief Список аварий УПП
*/
typedef enum {
Err_None = 0, ///< Неисправность отсутствует
/* Програмные ошибки */
Err_Internal_1 = 1, ///< Внутренняя неисправность УПП 1
Err_Internal_2 = 2, ///< Внутренняя неисправность УПП 2
Err_Internal_3 = 3, ///< Внутренняя неисправность УПП 3
Err_Internal_4 = 4, ///< Внутренняя неисправность УПП 4
Err_Internal_5 = 5, ///< Внутренняя неисправность УПП 5
Err_Internal_6 = 6, ///< Внутренняя неисправность УПП 6
/* Ошибки по питанию */
Err_Power_Digit_5V = 7, ///< Неисправность цифрового источника питания (5 В)
Err_Power_24V = 8, ///< Неисправность источника питания 24 В
Err_Power_Analog_5V = 9, ///< Неисправность аналогового источника питания микроконтроллера (± 5 В)
Err_Power_SCI_5V = 10, ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В)
Err_Power_DIO_24V = 11, ///< Неисправность источника питания дискретных входов/выходов (24 В)
/* Ошибки по допустимым пределам Наряжений/Токов/Температуры */
Err_OverCurrent = 12, ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t)
Err_OverVoltage = 13, ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t)
Err_OverTemperature = 14, ///< Температура выше допустимой (плюс 85 °C)
Err_UnderVoltage = 15, ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t)
/* Ошибки по обрывам фаз */
Err_LossPhaseAll = 16, ///< Обрыв трёх фаз (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseA = 17, ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseB = 18, ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseC = 19, ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t)
/* Другие ошибки */
Err_LongStart = 20, ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t)
Err_Interlace = 21, ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t)
Err_OverFrequency = 22, ///< Частота сети выше допустимой
Err_UnderFrequency = 23, ///< Частота сети ниже допустимой
} UPP_ErrorType_t;
/**
* @brief Структура данных от УПП передаваемых в ПУИ
*/
typedef struct {
uint16_t Error; /** @brief Текущая авария
@details В случае срабатывания защиты */
uint16_t WorkMode; /** @brief Режим работы
@details «Готовность» или «Работа» */
uint16_t Voltage; /** @brief Напряжение на входе УПП, Вольты */
uint16_t Current; /** @brief Ток на входе УПП, Амперы */
uint16_t Frequency; /** @brief Частота напряжения на входе УПП */
uint16_t Temperature; /** @brief Температура радиатора тиристоров, Градусы Цельсия */
} UPP_PUI_Values_t;
/**
* @brief Структура параметров УПП от ПУИ
* @details Параметры по умолчанию приведены в @ref UPP_DEFAULT_PARAMS
* @note Защиты X приведены в @ref UPP_ErrorType_t
*/
typedef struct {
uint16_t Iref; /** @brief Уставка ограничения тока УПП
@details В диапазоне от 100 % до 500 % от = 5 А
По умолчанию @ref PUI_Iref_PERCENT_DEFAULT */
uint16_t Tnt; /** @brief Уставка времени нарастания заданного тока
@details В диапазоне от 50 до 5000 мс.
По умолчанию @ref PUI_Tnt_MS_DEFAULT */
uint16_t Umin; /** @brief Уставка защиты №15 от понижения напряжения входной сети
@details В диапазоне от 5% до 99 % от = 690 В.
По умолчанию @ref PUI_Umin_PERCENT_DEFAULT */
uint16_t Umax; /** @brief Уставка защиты №13 от повышения напряжения входной сети
@details В диапазоне от 100% до 120 % от = 690 В.
По умолчанию @ref PUI_Umax_PERCENT_DEFAULT */
uint16_t Imax; /** @brief Уставка защиты №12 по току
@details В диапазоне от 5 % до 99 % от 50 А.
По умолчанию @ref PUI_Imax_PERCENT_DEFAULT */
uint16_t Imin; /** @brief Уставка защит № 16 №19 от обрыва фаз(ы)
@details В диапазоне от 0 % до 40 % от = 5 А. При задании нуля эти защиты отключаются.
По умолчанию @ref PUI_Imin_PERCENT_DEFAULT */
uint16_t TiMax; /** @brief Выдержка времени на срабатывание защиты № 12 по току
@details В диапазоне от 500 до 10000 мкс.
По умолчанию @ref PUI_TiMax_US_DEFAULT */
uint16_t Tdelay; /** @brief Выдержка времени защиты № 20 от затянутого пуска
@details В диапазоне от 5 до 60 с.
По умолчанию @ref PUI_Tdelay_SECONDS_DEFAULT */
uint16_t Interlace; /** @brief Разрешение защиты № 21 от обратного порядка чередования фаз;
@details 0 нет защиты, 1 есть защита.
По умолчанию @ref PUI_Interlace_EN_DEFAULT */
} UPP_PUI_Params_t;
/** //UPP_HIGHLEVEL
* @}
*/
/**
* @addtogroup UPP_INTERNAL_DEFS Defines for internal use
* @ingroup UPP_DEFS
* @brief Дефайны УПП которые используютяс исключительно внутри программы
* @{
*/
#define ANGLE_PERIOD_MS (((float)1/(PM_F_NOM_HZ*2))*1000)
/**
* @brief Состояния полуволны
*/
typedef enum {
UPP_WAVE_UNKNOWED = 0,
UPP_WAVE_POSITIVE,
UPP_WAVE_NEGATIVE
} UPP_HalfWave_t;
/**
* @brief Названия Фаз
*/
typedef enum {
UPP_PHASE_A = 0,
UPP_PHASE_B = 1,
UPP_PHASE_C = 2,
UPP_PHASE_UNKNOWN = 3
} UPP_Phase_t;
/** //UPP_INTERNAL_DEFS
* @}
*/
#endif //_UPP_DEFS_H_
/** //UPP_DEFS
* @}
*/

View File

@ -31,11 +31,10 @@ extern "C" {
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include "upp_config.h" #include "upp_defs.h"
#include "upp_errors.h"
#include "mylibs_include.h" #include "mylibs_include.h"
#ifndef MATLAB
#include "modbus.h" #include "modbus.h"
#endif
/* USER CODE END Includes */ /* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
@ -56,7 +55,7 @@ extern "C" {
void Error_Handler(void); void Error_Handler(void);
/* USER CODE BEGIN EFP */ /* USER CODE BEGIN EFP */
extern __IO uint32_t micros;
/* USER CODE END EFP */ /* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/

View File

@ -7,32 +7,6 @@
******************************************************************************/ ******************************************************************************/
#include "adc_tools.h" #include "adc_tools.h"
//Полосовой фильтр 45-55 Гц
static float coefs_biquad_U[5] = {
0.000010f, // b0
0.000020f, // b1
0.000010f, // b2
-1.900000f, // a1
0.950000f // a2
};
// ФНЧ 100 Гц
static float coefs_biquad_I[5] = {
0.000010f, // b0
0.000020f, // b1
0.000010f, // b2
-1.900000f, // a1
0.950000f // a2
};
// ФНЧ 10 Гц
static float coefs_biquad_T[5] = {
0.0002f, // b0
0.0004f, // b1
0.0002f, // b2
-1.98f, // a1
0.980f // a2
};
static void ADC_EnableAllFilters(ADC_Periodic_t *adc) static void ADC_EnableAllFilters(ADC_Periodic_t *adc)
{ {
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
@ -106,6 +80,8 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le
adc->Coefs[ChNumb].lMax = levelMax; adc->Coefs[ChNumb].lMax = levelMax;
adc->Coefs[ChNumb].vMax = valueMax; adc->Coefs[ChNumb].vMax = valueMax;
adc->Coefs[ChNumb].lZero = levelZero; adc->Coefs[ChNumb].lZero = levelZero;
ADC_ResetStatistics(adc, ChNumb);
return HAL_OK; return HAL_OK;
} }
@ -116,16 +92,16 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le
* @return HAL Status. * @return HAL Status.
* @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim. * @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim.
*/ */
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period) HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs)
{ {
HAL_StatusTypeDef res; HAL_StatusTypeDef res;
if(assert_upp(adc)) if(assert_upp(adc))
return HAL_ERROR; return HAL_ERROR;
if(Period == 0) if(PeriodUs == 0)
return HAL_ERROR; return HAL_ERROR;
// Запускаем таймер который будет запускать опрос АЦП с заданным периодом // Запускаем таймер который будет запускать опрос АЦП с заданным периодом
__HAL_TIM_SET_AUTORELOAD(adc->htim, Period); __HAL_TIM_SET_AUTORELOAD(adc->htim, TIM_MicrosToTick(PeriodUs, ADC_TIM8_FREQ_MZH));
res = HAL_TIM_Base_Start(adc->htim); res = HAL_TIM_Base_Start(adc->htim);
if(res != HAL_OK) if(res != HAL_OK)
{ {

View File

@ -123,7 +123,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_Han
/* Конфигуарция канала АЦП. */ /* Конфигуарция канала АЦП. */
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax); HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax);
/* Запуск АЦП. */ /* Запуск АЦП. */
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period); HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs);
/* Остановка АЦП. */ /* Остановка АЦП. */
HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc); HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc);

View File

@ -15,17 +15,32 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK) if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, 2048, PM_U_BASE, 4095) != HAL_OK) if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA],
4095) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC, 2048, PM_U_BASE, 4095) != HAL_OK)
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC],
4095) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC, 2048, PM_I_BASE, 4095) != HAL_OK)
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC],
4095) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA, 2048, PM_I_BASE, 4095) != HAL_OK)
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA],
4095) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ZC_Init(&hpm->zc, 3, PM_ZERO_CROSS_HYSTERESIS_V, PM_ZERO_CROSS_DEBOUNCE_10US) != HAL_OK) if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK) if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK)
@ -41,7 +56,7 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm)
{ {
if(ADC_Start(&hpm->adc, PM_ADC_PERIOD) != HAL_OK) if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_MKS) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
return HAL_OK; return HAL_OK;
@ -51,6 +66,7 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm)
void PowerMonitor_Handle(PowerMonitor_t *hpm) void PowerMonitor_Handle(PowerMonitor_t *hpm)
{ {
/* Считываем АЦП */
static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0}; static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0};
ADC_Handle(&hpm->adc); ADC_Handle(&hpm->adc);

View File

@ -28,9 +28,9 @@ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels,
memset(zc, 0, sizeof(ZeroCross_Handle_t)); memset(zc, 0, sizeof(ZeroCross_Handle_t));
// Установка параметров хендла // Установка параметров хендла
zc->NumChannels = num_channels; zc->Config.NumChannels = num_channels;
zc->Hysteresis = hysteresis; zc->Config.Hysteresis = hysteresis;
zc->DebounceSamples = debounce_samples; zc->Config.DebounceSamples = debounce_samples;
// Инициализация каналов // Инициализация каналов
for (int i = 0; i < num_channels; i++) { for (int i = 0; i < num_channels; i++) {
@ -63,7 +63,7 @@ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel,
if (assert_upp(zc)){ if (assert_upp(zc)){
return HAL_ERROR; return HAL_ERROR;
} }
if (channel >= zc->NumChannels) { if (channel >= zc->Config.NumChannels) {
return HAL_ERROR; return HAL_ERROR;
} }
@ -94,7 +94,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
if (!zc->f.Monitoring) { if (!zc->f.Monitoring) {
return; return;
} }
if (channel >= zc->NumChannels) { if (channel >= zc->Config.NumChannels) {
return; return;
} }
int zc_detected = 0; int zc_detected = 0;
@ -111,16 +111,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
} }
// Детектирование rising edge (отрицательное -> положительное) // Детектирование rising edge (отрицательное -> положительное)
if ((zc_ch->LastValue <= -zc->Hysteresis) && if ((zc_ch->LastValue <= -zc->Config.Hysteresis) &&
(value >= zc->Hysteresis)) (value >= zc->Config.Hysteresis))
{ {
if (zc_ch->EdgeType == ZC_RISING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) { if (zc_ch->EdgeType == ZC_RISING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
if(zc->DebounceSamples) if(zc->Config.DebounceSamples)
{ {
if(zc_ch->DebounceCounter == 0) if(zc_ch->DebounceCounter == 0)
{ {
zc_ch->DebounceCounter = zc->DebounceSamples; zc_ch->DebounceCounter = zc->Config.DebounceSamples;
} }
} }
@ -128,16 +128,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
} }
} }
// Детектирование falling edge (положительное -> отрицательное) // Детектирование falling edge (положительное -> отрицательное)
else if ((zc_ch->LastValue >= zc->Hysteresis) && else if ((zc_ch->LastValue >= zc->Config.Hysteresis) &&
(value <= -zc->Hysteresis)) (value <= -zc->Config.Hysteresis))
{ {
if (zc_ch->EdgeType == ZC_FALLING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) { if (zc_ch->EdgeType == ZC_FALLING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
if(zc->DebounceSamples) if(zc->Config.DebounceSamples)
{ {
if(zc_ch->DebounceCounter == 0) if(zc_ch->DebounceCounter == 0)
{ {
zc_ch->DebounceCounter = zc->DebounceSamples; zc_ch->DebounceCounter = zc->Config.DebounceSamples;
} }
} }
@ -149,7 +149,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
{ {
zc_ch->HalfWave = zc_detected == 1 ? UPP_WAVE_POSITIVE : UPP_WAVE_NEGATIVE; zc_ch->HalfWave = zc_detected == 1 ? UPP_WAVE_POSITIVE : UPP_WAVE_NEGATIVE;
zc_ch->Occurred = 1; zc_ch->Occurred = 1;
uint32_t RealTimeShift = 0;//zc->DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции uint32_t RealTimeShift = 0;//zc->Config.DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции
// Переход подтвержден сразу // Переход подтвержден сразу
uint32_t RealTimestamp = timestamp-RealTimeShift; uint32_t RealTimestamp = timestamp-RealTimeShift;
@ -166,7 +166,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
} }
// Сохраняем текущее значение для следующей итерации в случае если оно не в мертвой зоне // Сохраняем текущее значение для следующей итерации в случае если оно не в мертвой зоне
if((value > zc->Hysteresis) || (value < -zc->Hysteresis)) if((value > zc->Config.Hysteresis) || (value < -zc->Config.Hysteresis))
{ {
zc_ch->LastValue = value; zc_ch->LastValue = value;
} }
@ -188,7 +188,7 @@ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t times
return; return;
} }
for (int ch = 0; ch < zc->NumChannels; ch++) { for (int ch = 0; ch < zc->Config.NumChannels; ch++) {
ZC_ProcessChannel(zc, ch, values[ch], timestamp); ZC_ProcessChannel(zc, ch, values[ch], timestamp);
} }
@ -238,7 +238,7 @@ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel)
if (assert_upp(zc)){ if (assert_upp(zc)){
return 0.0f; return 0.0f;
} }
if (channel >= zc->NumChannels) { if (channel >= zc->Config.NumChannels) {
return 0.0f; return 0.0f;
} }
@ -273,7 +273,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel)
return; return;
} }
if (channel < zc->NumChannels) { if (channel < zc->Config.NumChannels) {
zc->Channel[channel].LastValue = 0.0f; zc->Channel[channel].LastValue = 0.0f;
zc->Channel[channel].CurrentValue = 0.0f; zc->Channel[channel].CurrentValue = 0.0f;
zc->Channel[channel].DebounceCounter = 0; zc->Channel[channel].DebounceCounter = 0;
@ -284,7 +284,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel)
} }
else { else {
// Сброс всех каналов // Сброс всех каналов
for (int i = 0; i < zc->NumChannels; i++) { for (int i = 0; i < zc->Config.NumChannels; i++) {
zc->Channel[i].LastValue = 0.0f; zc->Channel[i].LastValue = 0.0f;
zc->Channel[i].CurrentValue = 0.0f; zc->Channel[i].CurrentValue = 0.0f;
zc->Channel[i].DebounceCounter = 0; zc->Channel[i].DebounceCounter = 0;

View File

@ -100,15 +100,22 @@ typedef struct {
ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода
} ZC_Channel_t; } ZC_Channel_t;
/**
* @brief Параметры перехода через ноль
*/
typedef struct {
uint8_t NumChannels; ///< Количество используемых каналов для этого хендла
float Hysteresis; ///< Гистерезис для избежания дребезга
uint16_t DebounceSamples; ///< Количество samples для антидребезга
} ZC_Config_t;
/** /**
* @brief Хендл детектора нуля * @brief Хендл детектора нуля
*/ */
typedef struct { typedef struct {
ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t
uint8_t NumChannels; ///< Количество используемых каналов для этого хендла ZC_Config_t Config;
float Hysteresis; ///< Гистерезис для избежания дребезга
uint16_t DebounceSamples; ///< Количество samples для антидребезга
struct { struct {
unsigned Initialized:1; ///< Флаг инициализации unsigned Initialized:1; ///< Флаг инициализации
unsigned Monitoring:1; ///< Флаг активности мониторинга unsigned Monitoring:1; ///< Флаг активности мониторинга

View File

@ -34,7 +34,7 @@
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */ /* USER CODE BEGIN PTD */
__IO uint32_t micros;
/* USER CODE END PTD */ /* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/

View File

@ -246,6 +246,7 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void)
HAL_TIM_IRQHandler(&htim14); HAL_TIM_IRQHandler(&htim14);
/* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */ /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */
#endif #endif
UPP_Tick();
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */ /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */
} }

View File

@ -1,7 +1,7 @@
/** /**
****************************************************************************** ******************************************************************************
* @file pwm_thyristors.c * @file angle_control.c
* @brief Модуль для управления тиристорами * @brief Модуль для формирования и отсчитывания угла открытия
****************************************************************************** ******************************************************************************
* @details * @details
******************************************************************************/ ******************************************************************************/
@ -10,22 +10,16 @@
/** /**
* @brief Инициализация ШИМ тиристоров. * @brief Инициализация таймера для расчета угла открытия.
* @param hangle Указатель на таймер * @param hangle Указатель на таймер
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax) HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
{ {
if(hangle == NULL) if(hangle == NULL)
return HAL_ERROR; return HAL_ERROR;
if(AngleMax < 0 || AngleMax > 1)
return HAL_ERROR;
if(AngleMin < 0 || AngleMin > 1)
return HAL_ERROR;
hangle->htim = &angletim; hangle->htim = &angletim;
hangle->AngleMax = AngleMax;
hangle->AngleMin = AngleMin;
HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1); HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1);
@ -36,9 +30,65 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle
Angle_Reset(hangle, UPP_PHASE_B); Angle_Reset(hangle, UPP_PHASE_B);
Angle_Reset(hangle, UPP_PHASE_C); Angle_Reset(hangle, UPP_PHASE_C);
hangle->f.Initialized = 1;
return HAL_OK; return HAL_OK;
} }
/**
* @brief Инициализация углов открытия.
* @param hangle Указатель на таймер
* @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ
* @param AngleMin Минимально возможный угол открытия
* @param AngleMax Максимально возможный угол открытия
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax)
{
if(assert_upp(hangle))
return HAL_ERROR;
if(hangle->f.Running)
return HAL_BUSY;
if(AngleMax < 0 || AngleMax > 1)
return HAL_ERROR;
if(AngleMin < 0 || AngleMin > 1)
return HAL_ERROR;
if(AngleMax > hangle->Config.AngleLimit)
AngleMax = hangle->Config.AngleLimit;
if(AngleMin > hangle->Config.AngleLimit)
AngleMin = hangle->Config.AngleLimit;
if(AngleMin >= AngleMax)
return HAL_ERROR;
hangle->Config.AngleMax = AngleMax;
hangle->Config.AngleMin = AngleMin;
return HAL_OK;
}
/**
* @brief Инициализация предельного угла открытия.
* @param hangle Указатель на таймер
* @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ
* @param AngleMin Минимально возможный угол открытия
* @param AngleMax Максимально возможный угол открытия
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit)
{
if(assert_upp(hangle))
return HAL_ERROR;
if(hangle->f.Running)
return HAL_BUSY;
if(AngleLimit < 0 || AngleLimit > 1)
return HAL_ERROR;
hangle->Config.AngleLimit = AngleLimit;
return HAL_OK;
}
/** /**
* @brief Хендл таймера для рассчета угла открытия. * @brief Хендл таймера для рассчета угла открытия.
* @param hangle Указатель на таймер * @param hangle Указатель на таймер
@ -46,7 +96,7 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle
*/ */
UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle)
{ {
if(hangle == NULL) if(assert_upp(hangle))
return UPP_PHASE_UNKNOWN; return UPP_PHASE_UNKNOWN;
@ -79,9 +129,9 @@ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle)
* @param Phase Для какой фазы надо установить угол открытия * @param Phase Для какой фазы надо установить угол открытия
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq) HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs)
{ {
if(hangle == NULL) if(assert_upp(hangle))
return HAL_ERROR; return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку // Если канал дурацкий - возвращаем ошибку
@ -89,16 +139,16 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A
{ {
return HAL_ERROR; return HAL_ERROR;
} }
if(Angle > hangle->AngleMax) if(Angle > hangle->Config.AngleMax)
{ {
Angle = hangle->AngleMax; Angle = hangle->Config.AngleMax;
} }
if(Angle < hangle->AngleMin) if(Angle < hangle->Config.AngleMin)
{ {
Angle = hangle->AngleMin; Angle = hangle->Config.AngleMin;
} }
uint32_t timer_ticks = TIM_FreqToTick(Freq/Angle, ANGLE_TIM2_FREQ_MHZ); uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*Angle, ANGLE_TIM2_FREQ_MHZ);
uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks; uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks;
switch(Phase) switch(Phase)
@ -106,16 +156,19 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A
case UPP_PHASE_A: case UPP_PHASE_A:
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_1, ccr_ticks); __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_1, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1);
hangle->f.Running++;
break; break;
case UPP_PHASE_B: case UPP_PHASE_B:
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_2, ccr_ticks); __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_2, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2);
hangle->f.Running++;
break; break;
case UPP_PHASE_C: case UPP_PHASE_C:
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_3, ccr_ticks); __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_3, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3);
hangle->f.Running++;
break; break;
case UPP_PHASE_UNKNOWN: case UPP_PHASE_UNKNOWN:
@ -136,7 +189,7 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A
*/ */
HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase)
{ {
if(hangle == NULL) if(assert_upp(hangle))
return HAL_ERROR; return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку // Если канал дурацкий - возвращаем ошибку
@ -149,14 +202,20 @@ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase)
{ {
case UPP_PHASE_A: case UPP_PHASE_A:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC1); __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC1);
if(hangle->f.Running)
hangle->f.Running--;
break; break;
case UPP_PHASE_B: case UPP_PHASE_B:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC2); __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC2);
if(hangle->f.Running)
hangle->f.Running--;
break; break;
case UPP_PHASE_C: case UPP_PHASE_C:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC3); __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC3);
if(hangle->f.Running)
hangle->f.Running--;
break; break;
case UPP_PHASE_UNKNOWN: case UPP_PHASE_UNKNOWN:

View File

@ -1,27 +1,39 @@
/** /**
****************************************************************************** ******************************************************************************
* @file pwm_thyristors.h * @file angle_control.h
* @brief Модуль для управления тиристорами (объединённый 6-канальный) * @brief Модуль для формирования и отсчитывания угла открытия
****************************************************************************** ******************************************************************************
*/ */
#ifndef _ANGLE_CONTROL_H_ #ifndef _ANGLE_CONTROL_H_
#define _ANGLE_CONTROL_H_ #define _ANGLE_CONTROL_H_
#include "main.h" #include "main.h"
#define ANGLE_TIM2_FREQ_MHZ 90 typedef struct
{
float AngleLimit; ///< Лимит AngleMax, рассчитывается от параметров ШИМ
float AngleMin; ///< Минимально возможный угол открытия
float AngleMax; ///< Максимально возможный угол открытия
}Angle_Config_t;
typedef struct typedef struct
{ {
TIM_HandleTypeDef *htim; TIM_HandleTypeDef *htim;
Angle_Config_t Config;
float AngleMin; struct {
float AngleMax; unsigned Initialized : 1;
unsigned Running : 3; ///< Сколько каналов запущено сейчас
} f;
}Angle_Handle_t; }Angle_Handle_t;
/* Инициализация Таймера для рассчета угла открытия. */ /* Инициализация Таймера для рассчета угла открытия. */
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax); HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle);
/* Инициализация углов открытия. */
HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax);
/* Инициализация предельного угла открытия. */
HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit);
/* Установка угла открытия в таймер. */ /* Установка угла открытия в таймер. */
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq); HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs);
/* Сброс угла открытия у таймера. */ /* Сброс угла открытия у таймера. */
HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase); HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase);

View File

@ -56,7 +56,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED);
PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED);
PWM_SetFrequency(hpwm, hpwm->Config.Frequency); PWM_SetConfig(hpwm, MB_INTERNAL.param.pwm.PhaseMask, MB_INTERNAL.param.pwm.Frequency, MB_INTERNAL.param.pwm.PulseNumber);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2);
@ -115,7 +115,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
* @param Phase На какой фазе надо остановить ШИМ * @param Phase На какой фазе надо остановить ШИМ
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop) HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all)
{ {
if(assert_upp(hpwm)) if(assert_upp(hpwm))
return HAL_ERROR; return HAL_ERROR;
@ -129,10 +129,18 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
hpwm->Phase[Phase]->State = PWM_THYR_DISABLED; hpwm->Phase[Phase]->State = PWM_THYR_DISABLED;
if(force_stop) // Если не force_stop_all - сбрасываем только текущий канал
if (!force_stop_all)
{ {
__PWM_SetOutputState(hpwm->Phase[Phase], PWM_DISABLE); __PWM_SetOutputState(hpwm->Phase[Phase], PWM_DISABLE);
} }
// Если force_stop_all - сбрасываем ВСЕ КАНАЛЫ
else {
for(int ch = 0; ch < 6; ch++)
{
__PWM_SetOutputState(&hpwm->AllPhases[ch], PWM_DISABLE);
}
}
return HAL_OK; return HAL_OK;
} }
@ -169,6 +177,7 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
__PWM_SetOutputState(hPhase, PWM_ENABLE); __PWM_SetOutputState(hPhase, PWM_ENABLE);
hPhase->PulseCnt = hpwm->Config.PulseNumber; hPhase->PulseCnt = hpwm->Config.PulseNumber;
hPhase->State = PWM_THYR_TIM_ACTIVE; hPhase->State = PWM_THYR_TIM_ACTIVE;
hpwm->f.Running++;
break; break;
case PWM_THYR_TIM_ACTIVE: case PWM_THYR_TIM_ACTIVE:
@ -182,6 +191,8 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
case PWM_THYR_TIM_DONE: case PWM_THYR_TIM_DONE:
hPhase->State = PWM_THYR_TIM_WAIT; hPhase->State = PWM_THYR_TIM_WAIT;
if(hpwm->f.Running)
hpwm->f.Running--;
break; break;
default: default:
@ -192,6 +203,37 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
return HAL_OK; return HAL_OK;
} }
/**
* @brief Установка частоты ШИМ.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Frequency Частота в ГЦ
* @return HAL Status.
*/
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber)
{
if(assert_upp(hpwm))
return HAL_ERROR;
if(hpwm->f.Running)
return HAL_BUSY;
HAL_TIM_Base_Stop(&hpwm1);
hpwm->Config.PhaseMask.all = PhaseMask;
hpwm->Config.PulseNumber = PulseNumber;
hpwm->Config.Frequency = Frequency;
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ));
__HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM3_FREQ_MHZ));
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2);
return HAL_TIM_Base_Start_IT(&hpwm1);
}
/** /**
* @brief Установка полуволны для слежения. * @brief Установка полуволны для слежения.
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
@ -206,7 +248,7 @@ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_Hal
// Сбрасываем текущий канал // Сбрасываем текущий канал
PWM_Stop(hpwm, Phase, 1); PWM_Stop(hpwm, Phase, 0);
// Если канал дурацкий - выставляем заглушку // Если канал дурацкий - выставляем заглушку
if(Phase >= 3) if(Phase >= 3)

View File

@ -1,7 +1,7 @@
/** /**
****************************************************************************** ******************************************************************************
* @file pwm_thyristors.h * @file pwm_thyristors.h
* @brief Модуль для управления тиристорами (объединённый 6-канальный) * @brief Модуль для управления тиристорами
****************************************************************************** ******************************************************************************
*/ */
#ifndef _PWM_THYRISTORS_H #ifndef _PWM_THYRISTORS_H
@ -12,23 +12,11 @@
#define PWM_TIM1_FREQ_MHZ 180
#define PWM_TIM3_FREQ_MHZ 90
#define PWM_ENABLE TIM_OCMODE_PWM1 #define PWM_ENABLE TIM_OCMODE_PWM2
#define PWM_DISABLE TIM_OCMODE_FORCED_ACTIVE #define PWM_DISABLE TIM_OCMODE_FORCED_INACTIVE
#define PWM_SetFrequency(_hpwm_, _freq_) \
do { _hpwm_->Config.Frequency = _freq_; \
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(_freq_, PWM_TIM1_FREQ_MHZ)); \
__HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(_freq_, PWM_TIM3_FREQ_MHZ)); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); \
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); }while(0);
// Индексы для структур каналов @ref PWM_Handle_t // Индексы для структур каналов @ref PWM_Handle_t
@ -67,7 +55,7 @@ typedef struct {
} PWM_Channel_t; } PWM_Channel_t;
/** /**
* @brief Канал PWM (один тиристор) * @brief Параметры ШИМ
*/ */
typedef struct { typedef struct {
union union
@ -81,7 +69,7 @@ typedef struct {
}; };
}PhaseMask; ///< Какими каналами управлять }PhaseMask; ///< Какими каналами управлять
uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров
uint32_t Frequency; ///< Частота импульсов uint16_t Frequency; ///< Частота импульсов
} PWM_ThyrConfig_t; } PWM_ThyrConfig_t;
/** /**
@ -93,7 +81,7 @@ typedef struct {
struct { struct {
unsigned Initialized : 1; unsigned Initialized : 1;
unsigned Running : 1; ///< true если оба таймера запущены unsigned Running : 3; ///< Сколько каналов запущено сейчас
} f; } f;
} PWM_Handle_t; } PWM_Handle_t;
@ -103,7 +91,9 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm);
/* Запуск ШИМ. */ /* Запуск ШИМ. */
HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase); HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase);
/* Остановить ШИМ. */ /* Остановить ШИМ. */
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop); HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all);
/* Установка частоты ШИМ. */
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber);
/* Установка полуволны для слежения. */ /* Установка полуволны для слежения. */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave); HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave);
/* Установка полуволны для слежения. */ /* Установка полуволны для слежения. */

267
UPP/Core/UPP/upp_control.c Normal file
View File

@ -0,0 +1,267 @@
/**
******************************************************************************
* @file upp_control.c
* @brief Модуль определябщий поведение УПП
******************************************************************************
* @details
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef);
static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef);
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc);
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
static int __AngleSetLimit(void);
/**
* @brief Контроль внутренних параметров УПП.
* @return HAL Status.
*/
void UPP_Control_InternalParams(void)
{
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
// флаги обновились ли конфиги
static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
static int zc_update = 0;
static int pwm_update = 0;
// временная переменная для параметров каналов АЦП
float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
// временная переменная для параметров перехода через ноль
float zc_hysteresis = upp.pm.zc.Config.Hysteresis;
uint16_t zc_debounce = upp.pm.zc.Config.DebounceSamples;
// временная переменная для параметров ШИМ
uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all;
uint16_t pwm_freq = upp.hpwm.Config.Frequency;
uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber;
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
adc_channel_max[i] = upp.pm.adc.Coefs[i].vMax;
adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero;
// Максимальное измеряемое напряжение
if(__CheckSimpleParamF(&adc_channel_max[i], MB_INTERNAL.param.adc.ADC_Max[i], 10))
{
adc_channel_update[i] = 1;
}
// Значение АЦП при нулевом входе
if(__CheckSimpleParamU16(&adc_channel_zero[i], MB_INTERNAL.param.adc.ADC_Zero[i]))
{
adc_channel_update[i] = 1;
}
}
// Параметры алгоритма перехода через ноль
if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 100))
{
zc_update = 1;
}
if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.Hysteresis))
{
zc_update = 1;
}
// Параметры ШИМ токов
if(__CheckSimpleParamU8(&pwm_phase_mask, MB_INTERNAL.param.pwm.PhaseMask, 1))
{
pwm_update = 1;
}
if(__CheckSimpleParamU16(&pwm_freq, MB_INTERNAL.param.pwm.Frequency))
{
pwm_update = 1;
}
if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1))
{
pwm_update = 1;
}
// Обновление АЦП конфигов
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
if(adc_channel_update[i])
{
if(ADC_ConfigChannel(&upp.pm.adc, i, adc_channel_zero[i], adc_channel_max[i], 4095) == HAL_OK)
adc_channel_update[i] = 0;
else
errors.prvt.cnt.adc_reinit_err++;
}
}
// Обновление Zero-Cross конфигов
if(zc_update)
{
if(ZC_Init(&upp.pm.zc, upp.pm.zc.Config.NumChannels, zc_hysteresis, zc_debounce) == HAL_OK)
zc_update = 0;
else
errors.prvt.cnt.zc_reinit_err++;
}
// Обновление ШИМ конфигов
if(pwm_update)
{
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_pulse_num) == HAL_OK)
{
pwm_update = 0;
__AngleSetLimit();
}
else
errors.prvt.cnt.pwm_reinit_err++;
}
if (upp.hangle.Config.AngleLimit == 0)
{
__AngleSetLimit();
}
}
/**
* @brief Установка параметров на дефолтные значения @ref UPP_DEFAULT_PARAMS.
* @param pui_default Сбросить параметры ПУИ
* @param internal_default Сбросить внутренние параметры
* @return HAL Status.
*/
void UPP_SetDefault(int pui_default, int internal_default)
{
if(pui_default)
{
MB_DATA.HoldRegs.pui_params.Iref = PUI_Iref_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Tnt = PUI_Tnt_MS_DEFAULT;
MB_DATA.HoldRegs.pui_params.Umin = PUI_Umin_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Umax = PUI_Umax_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Imax = PUI_Imax_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Imin = PUI_Imin_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.TiMax = PUI_TiMax_US_DEFAULT;
MB_DATA.HoldRegs.pui_params.Tdelay = PUI_Tdelay_SECONDS_DEFAULT;
MB_DATA.HoldRegs.pui_params.Interlace = PUI_Interlace_EN_DEFAULT;
}
if(internal_default)
{
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT;
MB_INTERNAL.param.pwm.PhaseMask = 0x7; // (все три фазы)
MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT;
MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT;
MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_V_DEFAULT*100;
MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT;
//__AngleSetLimit();
}
}
static int __AngleSetLimit(void)
{
// Перерасчет максимально допустимого угла
float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS;
float angle_limit = 1 - pulses_percent_of_period;
Angle_SetLimit(&upp.hangle, angle_limit);
}
/**
* @brief Сверить и обновить float параметр из uint16_t.
* @param paramDist Указатель на float параметр
* @param paramSrc Значение для сравнения с float параметром
* @param Coef Коэффициент для приведения float к uint16_t: uint16_t = float*coef, float = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (float)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint32_t параметр из uint16_t.
* @param paramDist Указатель на uint32_t параметр
* @param paramSrc Значение для сравнения с uint32_t параметром
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint32_t*coef, uint32_t = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint32_t)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint16_t параметр из uint16_t.
* @param paramDist Указатель на uint16_t параметр
* @param paramSrc Значение для сравнения с uint16_t параметром
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint16_t)paramSrc;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint8_t параметр из uint16_t.
* @param paramDist Указатель на uint8_t параметр
* @param paramSrc Значение для сравнения с uint32_t параметром
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint8_t*coef, uint8_t = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint8_t)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}

View File

@ -0,0 +1,67 @@
/**
******************************************************************************
* @file upp_control.h
* @brief Модуль определябщий поведение УПП
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_CONTROL_H
#define _UPP_CONTROL_H
#include "upp_defs.h"
typedef struct
{
unsigned set_default_pui:1;
unsigned set_default_internal:1;
unsigned go:1;
unsigned stop:1;
unsigned reserved:11;
unsigned reset_mcu:1;
}UPP_FuncCalls_t;
typedef struct
{
/* Параметры АЦП */
struct
{
uint16_t ADC_Max[4];
uint16_t ADC_Zero[4];
}adc;
/* Параметры ШИМ */
struct
{
uint16_t PhaseMask;
uint16_t Frequency;
uint16_t PulseNumber;
}pwm;
/* Параметры Угла */
struct
{
uint16_t Hysteresis;
uint16_t DebouneCouner;
}zc;
/* Параметры Угла */
struct
{
uint16_t Angle_Max;
uint16_t Angle_Min;
}angle;
}UPP_PrvtParams_t;
/* Контроль внутренних параметров УПП. */
void UPP_Control_InternalParams(void);
/* Установка параметров на дефолтные значения */
void UPP_SetDefault(int pui_default, int internal_default);
#endif //_UPP_CONTROL_H

44
UPP/Core/UPP/upp_errors.c Normal file
View File

@ -0,0 +1,44 @@
/**
******************************************************************************
* @file upp_errors.c
* @brief Ошибки УПП и их обработка
******************************************************************************
* @details
******************************************************************************/
#include "upp_errors.h" // всё остальное по работе с УПП
UPP_Errors_t errors;
static UPP_ErrorType_t UPP_SelectCommonError(void)
{
// Пока нет ошибки
UPP_ErrorType_t best = Err_None;
// Приоритет отсутствия ошибок
uint8_t best_prio = UPP_ErrorPriority[Err_None];
// Перебираем все возможные ошибки по enum
for (int e = Err_None + 1; e <= Err_UnderFrequency; e++)
{
// Проверяем: установлен ли соответствующий бит в pui.all
// e-1, потому что ошибка №1 = бит 0, ошибка №2 = бит 1 и т.д.
if (errors.pui.all & (1u << (e - 1)))
{
// Получаем приоритет этой ошибки
uint8_t pr = UPP_ErrorPriority[e];
// Если её приоритет лучше (меньше число) — запоминаем
if (pr < best_prio)
{
best_prio = pr;
best = (UPP_ErrorType_t)e;
}
}
}
// Возвращаем самую важную (наивысшего приоритета) ошибку
return best;
}
void UPP_ErrorsHandle(void)
{
errors.common = UPP_SelectCommonError();
}

124
UPP/Core/UPP/upp_errors.h Normal file
View File

@ -0,0 +1,124 @@
/**
******************************************************************************
* @file upp_errors.h
* @brief Ошибки УПП и их обработка
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_ERRORS_H
#define _UPP_ERRORS_H
#include "upp_defs.h"
/**
* @brief Приоритет ПУИ ошибок
*/
static const uint8_t UPP_ErrorPriority[] =
{
[Err_None] = 255,
/* Фатальные ошибки */
[Err_LossPhaseAll] = 1,
[Err_OverCurrent] = 2,
[Err_OverVoltage] = 3,
[Err_OverTemperature] = 4,
[Err_Power_24V] = 5,
[Err_Power_Digit_5V] = 6,
[Err_Power_DIO_24V] = 7,
[Err_Power_Analog_5V] = 8,
/* Критичные */
[Err_LossPhaseA] = 10,
[Err_LossPhaseB] = 11,
[Err_LossPhaseC] = 12,
[Err_LongStart] = 13,
[Err_Interlace] = 14,
/* Пограничные параметры */
[Err_UnderVoltage] = 20,
[Err_OverFrequency] = 21,
[Err_UnderFrequency] = 22,
/* Внутренние */
[Err_Internal_1] = 40,
[Err_Internal_2] = 41,
[Err_Internal_3] = 42,
[Err_Internal_4] = 43,
[Err_Internal_5] = 44,
[Err_Internal_6] = 45,
};
/**
* @brief Структура с всеми ошибками УПП
*/
typedef struct
{
UPP_ErrorType_t common; ///< Общая ошибка @ref UPP_ErrorType_t;
union
{
uint32_t all;
struct
{
/* Програмные ошибки */
unsigned Internal_1:1; ///< Внутренняя неисправность УПП 1
unsigned Internal_2:1; ///< Внутренняя неисправность УПП 2
unsigned Internal_3:1; ///< Внутренняя неисправность УПП 3
unsigned Internal_4:1; ///< Внутренняя неисправность УПП 4
unsigned Internal_5:1; ///< Внутренняя неисправность УПП 5
unsigned Internal_6:1; ///< Внутренняя неисправность УПП 6
/* Ошибки по питанию */
unsigned Power_Digit_5V:1; ///< Неисправность цифрового источника питания (5 В)
unsigned Power_24V:1; ///< Неисправность источника питания 24 В
unsigned Power_Analog_5V:1; ///< Неисправность аналогового источника питания микроконтроллера (± 5 В)
unsigned Power_SCI_5V:1; ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В)
unsigned Power_DIO_24V:1; ///< Неисправность источника питания дискретных входов/выходов (24 В)
/* Ошибки по допустимым пределам Наряжений/Токов/Температуры */
unsigned OverCurrent:1; ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t)
unsigned OverVoltage:1; ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t)
unsigned OverTemperature:1; ///< Температура выше допустимой (плюс 85 °C)
unsigned UnderVoltage:1; ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t)
/* Ошибки по обрывам фаз */
unsigned LossPhaseA:1; ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t)
unsigned LossPhaseB:1; ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t)
unsigned LossPhaseC:1; ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t)
/* Другие ошибки */
unsigned LongStart:1; ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t)
unsigned Interlace:1; ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t)
unsigned OverFrequency:1; ///< Частота сети выше допустимой
unsigned UnderFrequency:1; ///< Частота сети ниже допустимой
}err;
}pui;
struct
{
union
{
uint64_t all;
struct
{
unsigned :1;
}err;
}f;
struct
{
uint16_t adc_reinit_err;
uint16_t zc_reinit_err;
uint16_t pwm_reinit_err;
}cnt;
}prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ
}UPP_Errors_t;
extern UPP_Errors_t errors;
void UPP_ErrorsHandle(void);
#endif //_UPP_ERRORS_H

View File

@ -6,6 +6,7 @@
* @details * @details
******************************************************************************/ ******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП #include "upp_main.h" // всё остальное по работе с УПП
UPP_t upp; UPP_t upp;
float alpha_dbg = 0.5; float alpha_dbg = 0.5;
// ОСНОВНОЙ ЦИКЛ main.c // ОСНОВНОЙ ЦИКЛ main.c
@ -16,12 +17,18 @@ float alpha_dbg = 0.5;
*/ */
int UPP_Init(void) int UPP_Init(void)
{ {
// Подключение указателей
upp.errors = &errors;
upp.PUI.params = &MB_DATA.HoldRegs.pui_params;
upp.PUI.values = &MB_DATA.InRegs.pui;
upp.call = &MB_INTERNAL.FuncCalls;
HAL_TIM_Base_Start(&ustim); HAL_TIM_Base_Start(&ustim);
PowerMonitor_Init(&upp.pm); PowerMonitor_Init(&upp.pm);
upp.hpwm.Config.Frequency = 20000;
upp.hpwm.Config.PulseNumber = 20;
PWM_Init(&upp.hpwm); PWM_Init(&upp.hpwm);
Angle_Init(&upp.hangle, 0, 0.8); Angle_Init(&upp.hangle);
upp.workmode = WM_Ready;
return 0; return 0;
} }
@ -31,8 +38,9 @@ int UPP_Init(void)
*/ */
int UPP_PreWhile(void) int UPP_PreWhile(void)
{ {
UPP_Control_InternalParams();
Angle_SetRange(&upp.hangle, 0.0, 0.8);
PowerMonitor_Start(&upp.pm); PowerMonitor_Start(&upp.pm);
upp.hpwm.Config.PhaseMask.all = 0x7;
return 0; return 0;
} }
@ -42,10 +50,84 @@ int UPP_PreWhile(void)
*/ */
int UPP_While(void) int UPP_While(void)
{ {
// если ошибка вызываем СТОП
if(errors.pui.all)
{
upp.call->stop = 1;
}
// иначе снимаем СТОП
else
{
upp.call->stop = 0;
}
// Сброс на дефолтные по запросу
if(upp.call->set_default_pui)
{
UPP_SetDefault(1, 0);
}
if(upp.call->set_default_internal)
{
UPP_SetDefault(0, 1);
}
// Если СТОП - переходим в ошибку
if (upp.call->stop)
upp.workmode = WM_Error;
// Автомат состояний УПП
switch(upp.workmode)
{
case WM_Ready:
// если пришла команда на запуск
if (upp.call->go)
{
upp.workmode = WM_Running;
upp.StartTick = local_time();
}
break;
case WM_Running:
// если пришла команда на остановку
if (!upp.call->go)
upp.workmode = WM_Ready;
// если слишком долгий запуск
if((local_time() - upp.StartTick) > (upp.PUI.params->Tdelay*1000))
{
errors.pui.err.LongStart = 1;
}
break;
case WM_Error:
if(errors.common == Err_None)
upp.workmode = WM_Ready;
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
break;
}
return 0; return 0;
} }
/**
* @brief Всякое что будет делатся каждую 1 мс.
*/
void UPP_Tick(void)
{
if(upp.workmode == WM_Not_Init)
return;
UPP_ErrorsHandle();
UPP_Control_InternalParams();
}
// ПРЕРЫВАНИЯ stm32f4xx_it.c // ПРЕРЫВАНИЯ stm32f4xx_it.c
void UPP_ADC_Handle(void) void UPP_ADC_Handle(void)
@ -56,30 +138,33 @@ void UPP_ADC_Handle(void)
{ {
// Если произошел Zero Cross // Если произошел Zero Cross
if(ZC_isOccurred(&upp.pm.zc, phase)) if(ZC_isOccurred(&upp.pm.zc, phase))
{
// Если УПП в работе
if(upp.workmode == WM_Running)
{ {
// Меняем полуволну тиристора // Меняем полуволну тиристора
UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase); UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase);
PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave); PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave);
Angle_Start(&upp.hangle, phase, alpha_dbg, 100); // Начинаем отсчитывать угол
Angle_Start(&upp.hangle, phase, alpha_dbg, 10);
} }
} }
}
// Проверяем на ошибки
} }
void UPP_PWM_Handle(void) void UPP_PWM_Handle(void)
{ {
PWM_Handle(&upp.hpwm); PWM_Handle(&upp.hpwm);
} }
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim == upp.hangle.htim)
{
UPP_Angle_Handle();
}
}
void UPP_Angle_Handle(void) void UPP_Angle_Handle(void)
{ {
UPP_Phase_t phase = Angle_Handle(&upp.hangle); UPP_Phase_t phase = Angle_Handle(&upp.hangle);
Angle_Reset(&upp.hangle, phase); Angle_Reset(&upp.hangle, phase);
// Если УПП в работе
if(upp.workmode == WM_Running)
{
switch(phase) switch(phase)
{ {
case UPP_PHASE_A: case UPP_PHASE_A:
@ -94,4 +179,13 @@ void UPP_Angle_Handle(void)
default: default:
break; break;
} }
}
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim == upp.hangle.htim)
{
UPP_Angle_Handle();
}
} }

View File

@ -1,6 +1,6 @@
/** /**
****************************************************************************** ******************************************************************************
* @file modbus_data.h * @file upp_main.h
* @brief Определения структур данных Modbus устройства * @brief Определения структур данных Modbus устройства
****************************************************************************** ******************************************************************************
* @details * @details
@ -9,19 +9,35 @@
#ifndef _UPP_MAIN_H #ifndef _UPP_MAIN_H
#define _UPP_MAIN_H #define _UPP_MAIN_H
#include "main.h" // либы из AllLibs и вербальные имена из CubeMX #include "main.h" // общие библиотеки, конфигурации и вербальные имена из CubeMX
#include "upp_config.h"
#include "power_monitor.h" // статистика сети и АЦП #include "power_monitor.h" // статистика сети и АЦП
#include "pwm_thyristors.h" // Управление тиристорами #include "pwm_thyristors.h" // Управление тиристорами
#include "angle_control.h" // Управление углом открытия #include "angle_control.h" // Управление углом открытия
#include "upp_status.h" // статус упп
#include "upp_control.h" // управление упп
extern float alpha_dbg; extern float alpha_dbg;
typedef struct typedef struct
{ {
PowerMonitor_t pm; UPP_WorkModeType_t workmode; ///< Режим УПП
PWM_Handle_t hpwm; UPP_FuncCalls_t *call; ///< Вызов функций УПП
Angle_Handle_t hangle;
PowerMonitor_t pm; ///< Мониторинг сети
PWM_Handle_t hpwm; ///< Хендл ШИМ тиристоров
Angle_Handle_t hangle; ///< Хендл отсчитывания угла открытия
struct
{
UPP_PUI_Params_t *params; ///< Параметры от ПУИ
UPP_PUI_Values_t *values; ///< Данные для ПУИ
} PUI; ///< Общение с ПУИ
UPP_Errors_t *errors; ///< Ошибки УПП
uint32_t StartTick;
}UPP_t; }UPP_t;
extern UPP_t upp; extern UPP_t upp;
@ -32,7 +48,10 @@ int UPP_Init(void);
int UPP_PreWhile(void); int UPP_PreWhile(void);
/* Основной цикл УПП. */ /* Основной цикл УПП. */
int UPP_While(void); int UPP_While(void);
/* Всякое что будет делатся каждую 1 мс. */
void UPP_Tick(void);
// Прерывания
void UPP_ADC_Handle(void); void UPP_ADC_Handle(void);
void UPP_PWM_Handle(void); void UPP_PWM_Handle(void);
void UPP_Angle_Handle(void); void UPP_Angle_Handle(void);

12
UPP/Core/UPP/upp_status.c Normal file
View File

@ -0,0 +1,12 @@
/**
******************************************************************************
* @file upp_status.c
* @brief Модуль определяющий состояние УПП
******************************************************************************
* @details
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
void UPP_Status_Handler(void)
{
}

13
UPP/Core/UPP/upp_status.h Normal file
View File

@ -0,0 +1,13 @@
/**
******************************************************************************
* @file upp_status.h
* @brief Модуль определяющий состояние УПП
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_STATUS_H
#define _UPP_STATUS_H
#endif //_UPP_STATUS_H

View File

@ -206,6 +206,18 @@
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2> <bDave2>0</bDave2>
<PathWithFileName>..\Core\Configs\upp_defs.h</PathWithFileName>
<FilenameWithoutPath>upp_defs.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Inc\main.h</PathWithFileName> <PathWithFileName>..\Core\Inc\main.h</PathWithFileName>
<FilenameWithoutPath>main.h</FilenameWithoutPath> <FilenameWithoutPath>main.h</FilenameWithoutPath>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@ -213,7 +225,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber> <FileNumber>4</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -225,7 +237,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>4</FileNumber> <FileNumber>5</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -237,7 +249,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>5</FileNumber> <FileNumber>6</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -249,7 +261,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>6</FileNumber> <FileNumber>7</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -261,7 +273,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>7</FileNumber> <FileNumber>8</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -273,7 +285,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>8</FileNumber> <FileNumber>9</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -285,7 +297,7 @@
</File> </File>
<File> <File>
<GroupNumber>1</GroupNumber> <GroupNumber>1</GroupNumber>
<FileNumber>9</FileNumber> <FileNumber>10</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -305,7 +317,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber> <FileNumber>11</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -317,7 +329,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber> <FileNumber>12</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -329,7 +341,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>12</FileNumber> <FileNumber>13</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -341,7 +353,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>13</FileNumber> <FileNumber>14</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -353,7 +365,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>14</FileNumber> <FileNumber>15</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -365,7 +377,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>15</FileNumber> <FileNumber>16</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -375,6 +387,78 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<bShared>0</bShared> <bShared>0</bShared>
</File> </File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_control.c</PathWithFileName>
<FilenameWithoutPath>upp_control.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_control.h</PathWithFileName>
<FilenameWithoutPath>upp_control.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_status.c</PathWithFileName>
<FilenameWithoutPath>upp_status.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_status.h</PathWithFileName>
<FilenameWithoutPath>upp_status.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_errors.c</PathWithFileName>
<FilenameWithoutPath>upp_errors.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_errors.h</PathWithFileName>
<FilenameWithoutPath>upp_errors.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group> </Group>
<Group> <Group>
@ -385,7 +469,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber> <FileNumber>23</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -397,7 +481,7 @@
</File> </File>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber> <FileNumber>24</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -409,7 +493,7 @@
</File> </File>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber> <FileNumber>25</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -421,7 +505,7 @@
</File> </File>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber> <FileNumber>26</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -433,7 +517,7 @@
</File> </File>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber> <FileNumber>27</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -445,7 +529,7 @@
</File> </File>
<File> <File>
<GroupNumber>3</GroupNumber> <GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber> <FileNumber>28</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -465,7 +549,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>22</FileNumber> <FileNumber>29</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -477,7 +561,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>23</FileNumber> <FileNumber>30</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -489,7 +573,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>24</FileNumber> <FileNumber>31</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -501,7 +585,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>25</FileNumber> <FileNumber>32</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -513,7 +597,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>26</FileNumber> <FileNumber>33</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -525,7 +609,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>27</FileNumber> <FileNumber>34</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -537,7 +621,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>28</FileNumber> <FileNumber>35</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -549,7 +633,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>29</FileNumber> <FileNumber>36</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -561,7 +645,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>30</FileNumber> <FileNumber>37</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -573,7 +657,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>31</FileNumber> <FileNumber>38</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -585,7 +669,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>32</FileNumber> <FileNumber>39</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -597,7 +681,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>33</FileNumber> <FileNumber>40</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -609,7 +693,7 @@
</File> </File>
<File> <File>
<GroupNumber>4</GroupNumber> <GroupNumber>4</GroupNumber>
<FileNumber>34</FileNumber> <FileNumber>41</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -629,7 +713,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber> <FileNumber>42</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -641,7 +725,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>36</FileNumber> <FileNumber>43</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -653,7 +737,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber> <FileNumber>44</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -665,7 +749,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>38</FileNumber> <FileNumber>45</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -677,7 +761,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>39</FileNumber> <FileNumber>46</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -689,7 +773,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>40</FileNumber> <FileNumber>47</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -701,7 +785,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>41</FileNumber> <FileNumber>48</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -713,7 +797,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>42</FileNumber> <FileNumber>49</FileNumber>
<FileType>5</FileType> <FileType>5</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -733,7 +817,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>43</FileNumber> <FileNumber>50</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -745,7 +829,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>44</FileNumber> <FileNumber>51</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -757,7 +841,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>45</FileNumber> <FileNumber>52</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -769,7 +853,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>46</FileNumber> <FileNumber>53</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -781,7 +865,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>47</FileNumber> <FileNumber>54</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -793,7 +877,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>48</FileNumber> <FileNumber>55</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -805,7 +889,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>49</FileNumber> <FileNumber>56</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -817,7 +901,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>50</FileNumber> <FileNumber>57</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -829,7 +913,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>51</FileNumber> <FileNumber>58</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -841,7 +925,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>52</FileNumber> <FileNumber>59</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -853,7 +937,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>53</FileNumber> <FileNumber>60</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -865,7 +949,7 @@
</File> </File>
<File> <File>
<GroupNumber>6</GroupNumber> <GroupNumber>6</GroupNumber>
<FileNumber>54</FileNumber> <FileNumber>61</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -885,7 +969,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>7</GroupNumber> <GroupNumber>7</GroupNumber>
<FileNumber>55</FileNumber> <FileNumber>62</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -897,7 +981,7 @@
</File> </File>
<File> <File>
<GroupNumber>7</GroupNumber> <GroupNumber>7</GroupNumber>
<FileNumber>56</FileNumber> <FileNumber>63</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -917,7 +1001,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>8</GroupNumber> <GroupNumber>8</GroupNumber>
<FileNumber>57</FileNumber> <FileNumber>64</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -929,7 +1013,7 @@
</File> </File>
<File> <File>
<GroupNumber>8</GroupNumber> <GroupNumber>8</GroupNumber>
<FileNumber>58</FileNumber> <FileNumber>65</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -941,7 +1025,7 @@
</File> </File>
<File> <File>
<GroupNumber>8</GroupNumber> <GroupNumber>8</GroupNumber>
<FileNumber>59</FileNumber> <FileNumber>66</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -953,7 +1037,7 @@
</File> </File>
<File> <File>
<GroupNumber>8</GroupNumber> <GroupNumber>8</GroupNumber>
<FileNumber>60</FileNumber> <FileNumber>67</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -965,7 +1049,7 @@
</File> </File>
<File> <File>
<GroupNumber>8</GroupNumber> <GroupNumber>8</GroupNumber>
<FileNumber>61</FileNumber> <FileNumber>68</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -985,7 +1069,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>62</FileNumber> <FileNumber>69</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -997,7 +1081,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>63</FileNumber> <FileNumber>70</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1009,7 +1093,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>64</FileNumber> <FileNumber>71</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1021,7 +1105,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>65</FileNumber> <FileNumber>72</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1033,7 +1117,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>66</FileNumber> <FileNumber>73</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1045,7 +1129,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>67</FileNumber> <FileNumber>74</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1057,7 +1141,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>68</FileNumber> <FileNumber>75</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1069,7 +1153,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>69</FileNumber> <FileNumber>76</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1081,7 +1165,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>70</FileNumber> <FileNumber>77</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1093,7 +1177,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>71</FileNumber> <FileNumber>78</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1105,7 +1189,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>72</FileNumber> <FileNumber>79</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1117,7 +1201,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>73</FileNumber> <FileNumber>80</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1129,7 +1213,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>74</FileNumber> <FileNumber>81</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1141,7 +1225,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>75</FileNumber> <FileNumber>82</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1153,7 +1237,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>76</FileNumber> <FileNumber>83</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1165,7 +1249,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>77</FileNumber> <FileNumber>84</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1177,7 +1261,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>78</FileNumber> <FileNumber>85</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1189,7 +1273,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>79</FileNumber> <FileNumber>86</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1201,7 +1285,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>80</FileNumber> <FileNumber>87</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1213,7 +1297,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>81</FileNumber> <FileNumber>88</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1225,7 +1309,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>82</FileNumber> <FileNumber>89</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1237,7 +1321,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>83</FileNumber> <FileNumber>90</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1249,7 +1333,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>84</FileNumber> <FileNumber>91</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1261,7 +1345,7 @@
</File> </File>
<File> <File>
<GroupNumber>9</GroupNumber> <GroupNumber>9</GroupNumber>
<FileNumber>85</FileNumber> <FileNumber>92</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1281,7 +1365,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>10</GroupNumber> <GroupNumber>10</GroupNumber>
<FileNumber>86</FileNumber> <FileNumber>93</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@ -1301,7 +1385,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>11</GroupNumber> <GroupNumber>11</GroupNumber>
<FileNumber>87</FileNumber> <FileNumber>94</FileNumber>
<FileType>2</FileType> <FileType>2</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>

View File

@ -17,8 +17,8 @@
<TargetCommonOption> <TargetCommonOption>
<Device>STM32F427ZGTx</Device> <Device>STM32F427ZGTx</Device>
<Vendor>STMicroelectronics</Vendor> <Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.17.1</PackID> <PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>https://www.keil.com/pack/</PackURL> <PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu> <Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile> <StartupFile></StartupFile>
@ -390,6 +390,11 @@
<FileType>5</FileType> <FileType>5</FileType>
<FilePath>..\Core\Configs\upp_config.h</FilePath> <FilePath>..\Core\Configs\upp_config.h</FilePath>
</File> </File>
<File>
<FileName>upp_defs.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\Configs\upp_defs.h</FilePath>
</File>
<File> <File>
<FileName>main.h</FileName> <FileName>main.h</FileName>
<FileType>5</FileType> <FileType>5</FileType>
@ -465,6 +470,36 @@
<FileType>5</FileType> <FileType>5</FileType>
<FilePath>..\Core\UPP\angle_control.h</FilePath> <FilePath>..\Core\UPP\angle_control.h</FilePath>
</File> </File>
<File>
<FileName>upp_control.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_control.c</FilePath>
</File>
<File>
<FileName>upp_control.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_control.h</FilePath>
</File>
<File>
<FileName>upp_status.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_status.c</FilePath>
</File>
<File>
<FileName>upp_status.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_status.h</FilePath>
</File>
<File>
<FileName>upp_errors.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_errors.c</FilePath>
</File>
<File>
<FileName>upp_errors.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_errors.h</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>