#include "pwm.h" TIM_SettingsTypeDef TIM_CTRL = { 0 }; // variables for filling arrays int Numb_Of_Peroids = 2; // number of periods int Samples_Per_Peroid = 0; // how many samples in one period int Size_Of_Log = 0; // size of written data to log int log_ind = 0; // index of log arrays int cnt_to_cnt_log = 0; // counter for log_cnt int sine_ind_prev = 0; /** * @brief Filling logs. * @note Заполнение логов: синус, шим, пила. * @note This called from TIM_CTRL_Handler */ void Fill_Logs_with_Data(void) { // calc pwm duty from timer float PWM_Duty; if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE) == 0) // if sinus need to be written { if (PWM_Get_Mode(&hpwm1, PWM_BRIDGE_MODE)) // if its signed sine mode (two channels) { if (hpwm1.Duty_Table_Ind < hpwm1.Duty_Table_Size / 2) // first half get from channel 1 PWM_Duty = (((float)PWM_Get_Compare1(&hpwm1)) / (PWM_Get_Autoreload(&hpwm1))) + 1; else // second half get from channel 2 PWM_Duty = 1 - (((float)PWM_Get_Compare2(&hpwm1)) / (PWM_Get_Autoreload(&hpwm1))); } else // if its unsigned sine mode (single channel) { // just get current pwm duty PWM_Duty = ((float)PWM_Get_Compare1(&hpwm1) / PWM_Get_Autoreload(&hpwm1)); } } else // if its dc pwm mode { // just get current pwm duty if (PWM_Get_Mode(&hpwm1, PWM_BRIDGE_MODE)) // if its second channels mode PWM_Duty = ((float)PWM_Get_Compare2(&hpwm1) / PWM_Get_Autoreload(&hpwm1)); else // if its first channel mode PWM_Duty = ((float)PWM_Get_Compare1(&hpwm1) / PWM_Get_Autoreload(&hpwm1)); } // WRITE SINUS TO WHOLE ARRAY // sine_log[log_ind] = sin_val; if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE) == 0) // in table mode write PWM Duty (write sine) with scale 1/2 from sin table max value (0xFFFF/2) sine_log[log_ind] = PWM_Duty * (0x8000 - 1); else // in dc mode write PWM Duty (write sine) sine_log[log_ind] = 0; // WRITE PWM if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE)) // in DC mode { // write 1 - if log_ind < Size_Of_Period*PWM_Dury // write 0 - otherwise pwm_log[log_ind] = (log_ind % (Size_Of_Log / Numb_Of_Peroids) < (Size_Of_Log / Numb_Of_Peroids + 1) * hpwm1.PWM_Value / 100) ? 1 : 0; } else // in table mode { // write fill whole pwm array at one interrupt int PWM_Period_End_Ind = (Size_Of_Log / Numb_Of_Peroids); int PWM_Step_End_Ind; if (PWM_Get_Mode(&hpwm1, PWM_BRIDGE_MODE)) PWM_Step_End_Ind = PWM_Period_End_Ind * fabs(PWM_Duty - 1); else PWM_Step_End_Ind = PWM_Period_End_Ind * PWM_Duty; for (int i = 0; i <= PWM_Step_End_Ind; i++) { for (int j = 0; j < Numb_Of_Peroids; j++) pwm_log[i + j * PWM_Period_End_Ind] = 1; } for (int i = PWM_Step_End_Ind + 1; i < PWM_Period_End_Ind; i++) for (int j = 0; j < Numb_Of_Peroids; j++) pwm_log[i + j * PWM_Period_End_Ind] = 0; } // WRITE COUNTER cnt_log[log_ind] = cnt_to_cnt_log; cnt_to_cnt_log++; if (cnt_to_cnt_log >= Size_Of_Log / 2) cnt_to_cnt_log = 0; // INCREMENT AND RESET COUNTER log_ind++; if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE) == 0) // if its PWM table mode { // SYNCHRONIZE PERIOD OF SIN IN LOG // (это надо, чтобы данные не съезжали из-за несинхронизированного периода) // wait until period ended if (log_ind > Size_Of_Log - 1) // if logs are filled { if ((unsigned)hpwm1.Duty_Table_Ind < sine_ind_prev) // and if new period started { log_ind = 0; // reset counter sine_ind_prev = (unsigned)hpwm1.Duty_Table_Ind; } } // update prev variable only if log currently writing else sine_ind_prev = (unsigned)hpwm1.Duty_Table_Ind; } else // if its PWM DC mode { // if logs are filled if (log_ind > Size_Of_Log - 1) log_ind = 0; } // if its overflow log array size - reset log_ind if (log_ind > LOG_SIZE - 1) { log_ind = 0; sine_ind_prev = (unsigned)hpwm1.Duty_Table_Ind; } } /** * @brief Update log parameters. * @note Проверка надо ли обновлять параметры логов, и если надо - обновляет их. * @note This called from TIM_CTRL_Handler */ void Update_Params_For_Log(void) { unsigned UpdateLog = 0; // READ NUMB OF PERIOD IN LOGS if (Numb_Of_Peroids != log_ctrl[R_LOG_CTRL_LOG_PWM_NUMB]) { Numb_Of_Peroids = log_ctrl[R_LOG_CTRL_LOG_PWM_NUMB]; // update logs params UpdateLog = 1; } // READ SIZE OF LOGS if (Size_Of_Log != log_ctrl[R_LOG_CTRL_LOG_SIZE]) { Size_Of_Log = log_ctrl[R_LOG_CTRL_LOG_SIZE]; // update logs params UpdateLog = 1; } // UPDATE LOG PARAMS if (UpdateLog) { // set logs params Set_Log_Params(); } } /** * @brief Set up log parameters. * @note Устанавливает настройки логов и проверяет их на корректность. */ void Set_Log_Params(void) { // SET LOG PARAMS log_ind = 0; Samples_Per_Peroid = TIM_CTRL.sTimFreqHz / hpwm1.PWM_Value; if (Size_Of_Log > LOG_SIZE) // if its too much data in log { Numb_Of_Peroids = (LOG_SIZE / Samples_Per_Peroid); log_ctrl[R_LOG_CTRL_LOG_SIZE] = Numb_Of_Peroids; Size_Of_Log = Numb_Of_Peroids * Samples_Per_Peroid; } // clear logs arrays for (int i = Size_Of_Log; i < LOG_SIZE; i++) { sine_log[i] = 0; pwm_log[i] = 0; cnt_log[i] = 0; } } /** * @brief reInitialization of control timer. * @note Перенастраивает таймер согласно принятным настройкам в log_ctrl. * @note This called from main while */ void Control_Timer_ReInit(TIM_SettingsTypeDef* stim) { TIM_Base_MspDeInit(&stim->htim); hpwm1.stim.sTickBaseMHz = PROJSET.TIM_CTRL_TICKBASE; TIM_Base_Init(stim); HAL_TIM_Base_Start_IT(&stim->htim); // timer for sinus HAL_NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 1, 1); } /** * @brief First initialization of Control Timer. * @note Первый управляющего таймера. Таймер записывает логи и обновляет параметры ШИМ. * @note This called from main */ void Control_Timer_FirstInit(void) { //-------CONTROL TIMER INIT---------- // tim settings TIM_CTRL.htim.Instance = TIMER_CTRL_INSTANCE; TIM_CTRL.sTimMode = TIM_IT_MODE; TIM_CTRL.sTickBaseMHz = PROJSET.TIM_CTRL_TICKBASE; TIM_CTRL.sTimAHBFreqMHz = PROJSET.TIM_CTRL_AHB_FREQ; TIM_CTRL.sTimFreqHz = HZ_TIMER_CTRL; TIM_Base_Init(&TIM_CTRL); HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 1, 1); HAL_TIM_Base_Start_IT(&TIM_CTRL.htim); // timer for sinus // FILL TIME ARRAY WITH TIME for (int i = 0; i <= R_TIME_LOG_QNT; i++) time_log[i] = i; } //------------------------------------------------------------------- //------------------------HANDLERS FUNCTIONS------------------------- //-------------CONTROL TIMER--------------- void TIM8_UP_TIM13_IRQHandler(void) { /* TIM_CTRL_Handler */ Trace_CTRL_TIM_Enter(); HAL_TIM_IRQHandler(&TIM_CTRL.htim); Fill_Logs_with_Data(); Update_Params_For_Log(); Update_Params_For_PWM(&hpwm1); WriteSettingsToMem(); Trace_CTRL_TIM_Exit(); }