init
This commit is contained in:
239
научка/code/matlab_stm_emulate/Code/PWM/control.c
Normal file
239
научка/code/matlab_stm_emulate/Code/PWM/control.c
Normal file
@@ -0,0 +1,239 @@
|
||||
#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();
|
||||
}
|
||||
48
научка/code/matlab_stm_emulate/Code/PWM/control.h
Normal file
48
научка/code/matlab_stm_emulate/Code/PWM/control.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __CONTROL_H_
|
||||
#define __CONTROL_H_
|
||||
|
||||
#include "periph_general.h"
|
||||
#include "modbus.h"
|
||||
#include "math.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
|
||||
extern TIM_SettingsTypeDef TIM_CTRL;
|
||||
|
||||
//---------------------this called from TIM_CTRL_Handler()-----------------------
|
||||
/**
|
||||
* @brief Update log parameters.
|
||||
* @note Проверка надо ли обновлять параметры логов, и если надо - обновляет их.
|
||||
* @note This called from TIM_CTRL_Handler
|
||||
*/
|
||||
void Update_Params_For_Log(void);
|
||||
/**
|
||||
* @brief Filling logs.
|
||||
* @note заполнение логов: синус, шим, пила.
|
||||
* @note this called from TIM_CTRL_Handler
|
||||
*/
|
||||
void Fill_Logs_with_Data(void);
|
||||
/**
|
||||
* @brief Set up log parameters.
|
||||
* @note Устанавливает настройки логов и проверяет их на корректность.
|
||||
*/
|
||||
void Set_Log_Params(void);
|
||||
|
||||
/**
|
||||
* @brief First initialization of Control Timer.
|
||||
* @note Первый управляющего таймера. Таймер записывает логи и обновляет параметры ШИМ.
|
||||
* @note This called from main
|
||||
*/
|
||||
void Control_Timer_FirstInit(void);
|
||||
|
||||
// this called from main while(1)
|
||||
/**
|
||||
* @brief reInitialization of control timer.
|
||||
* @param stim - указатель на настройки таймера.
|
||||
* @note Перенастраивает таймер согласно принятным настройкам в log_ctrl.
|
||||
* @note This called from main while
|
||||
*/
|
||||
void Control_Timer_ReInit(TIM_SettingsTypeDef *stim);
|
||||
|
||||
#endif // __CONTROL_H_
|
||||
1087
научка/code/matlab_stm_emulate/Code/PWM/pwm.c
Normal file
1087
научка/code/matlab_stm_emulate/Code/PWM/pwm.c
Normal file
@@ -0,0 +1,1087 @@
|
||||
#include "pwm.h"
|
||||
//#include "rng.h"
|
||||
|
||||
PWM_HandleTypeDef hpwm1;
|
||||
PWM_SlaveHandleTypeDef hpwm2;
|
||||
PWM_SlaveHandleTypeDef hpwm3;
|
||||
uint32_t sin_table[SIN_TABLE_SIZE_MAX];
|
||||
unsigned ActiveChannelSHDW_Master;
|
||||
float DeadTimeCnt_Master;
|
||||
|
||||
unsigned ActiveChannelSHDW_Slave2;
|
||||
float DeadTimeCnt_Slave2;
|
||||
float shiftPHASE1 = 0.6666666666;
|
||||
float shiftPHASE2 = 0.3333333333;
|
||||
unsigned ActiveChannelSHDW_Slave3;
|
||||
float DeadTimeCnt_Slave3;
|
||||
/**
|
||||
* @brief First set up of PWM.
|
||||
* @note Первый инит ШИМ. Заполняет структуры и инициализирует таймер для генерации синуоидального ШИМ.
|
||||
* Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1)
|
||||
* ШИМ генерируется на одном канале.
|
||||
* @note This called from main
|
||||
*/
|
||||
void PWM_Sine_FirstInit(void)
|
||||
{
|
||||
hpwm1.sPWM_Config.PWM_Mode = (PWM_ModeCoilsTypeDef*)&coils_regs[0];
|
||||
hpwm1.sPWM_Config.PWM_Settings = (PWM_ModeRegsTypeDef*)&pwm_ctrl[0];
|
||||
|
||||
// PWM RAMP INIT
|
||||
hpwm1.pDuty_Table_Origin = SIN_TABLE_ORIGIN;
|
||||
|
||||
hpwm1.hramp.Kp = 0;
|
||||
hpwm1.hramp.Ki = PWM_RAMP_SPEED;
|
||||
hpwm1.hramp.Kd = 0;
|
||||
|
||||
hpwm1.hramp.limMax = 656;
|
||||
hpwm1.hramp.limMin = 0;
|
||||
hpwm1.hramp.limMaxInt = 20;
|
||||
hpwm1.hramp.limMinInt = -20;
|
||||
hpwm1.hramp.SampleT = (1.0f / HZ_TIMER_CTRL);
|
||||
|
||||
// PWM CONTROL PINS INIT
|
||||
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
||||
GPIO_Clock_Enable(GPIOC);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
GPIOC->ODR |= 1 << 0;//подача 0 разрешает . Аппаратное разрешение и запрет не подачу шим . Cигнал идет на логический элемент & 74AC08d
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); //кнопка для вкл аппаратно шим 74AC08d
|
||||
|
||||
|
||||
//---------PWM TIMER1 INIT------------
|
||||
// channels settings
|
||||
hpwm1.sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
hpwm1.sConfigOC.Pulse = 0;
|
||||
hpwm1.sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
|
||||
//hpwm1.sConfigOC.OCNPolarity=TIM_OCNPOLARITY_LOW;
|
||||
hpwm1.sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
|
||||
// tim1 settings
|
||||
hpwm1.stim.htim.Instance = TIMER_PWM1_INSTANCE;
|
||||
hpwm1.stim.sTimMode = TIM_IT_MODE;
|
||||
hpwm1.stim.sTimFreqHz = HZ_TIMER_PWM;
|
||||
hpwm1.stim.sTickBaseMHz = PROJSET.TIM_PWM_TICKBASE;
|
||||
hpwm1.stim.sTimAHBFreqMHz = PROJSET.TIM_PWM_AHB_FREQ;
|
||||
hpwm1.GPIOx = TIMER_PWM1_GPIOx;
|
||||
hpwm1.GPIO_PIN_X1 = PROJSET.TIM_PWM1_GPIO_PIN_X1;
|
||||
hpwm1.GPIO_PIN_X2 = PROJSET.TIM_PWM1_GPIO_PIN_X2;
|
||||
hpwm1.PWM_Channel1 = PROJSET.TIM_PWM1_TIM_CHANNEL1;
|
||||
hpwm1.PWM_Channel2 = PROJSET.TIM_PWM1_TIM_CHANNEL2;
|
||||
hpwm1.hpwm2 = (void*)&hpwm2;
|
||||
hpwm1.hpwm3 = (void*)&hpwm3;
|
||||
|
||||
TIM_Base_Init(&hpwm1.stim);
|
||||
TIM_Output_PWM_Init(&hpwm1.stim.htim, &hpwm1.sConfigOC, hpwm1.PWM_Channel1, hpwm1.GPIOx, hpwm1.GPIO_PIN_X1);
|
||||
TIM_Output_PWM_Init(&hpwm1.stim.htim, &hpwm1.sConfigOC, hpwm1.PWM_Channel2, hpwm1.GPIOx, hpwm1.GPIO_PIN_X2);
|
||||
|
||||
|
||||
// PWM SLAVES INIT
|
||||
hpwm2.hMasterPWM = &hpwm1;
|
||||
hpwm2.stim = hpwm1.stim;
|
||||
hpwm2.stim.htim.Instance = (TIM_TypeDef*)PROJSET.TIM_PWM2_INSTANCE;
|
||||
hpwm2.GPIOx = (GPIO_TypeDef*)PROJSET.TIM_PWM2_GPIOx;
|
||||
hpwm2.GPIO_PIN_X1 = PROJSET.TIM_PWM2_GPIO_PIN_X1;
|
||||
hpwm2.GPIO_PIN_X2 = PROJSET.TIM_PWM2_GPIO_PIN_X2;
|
||||
hpwm2.PWM_Channel1 = PROJSET.TIM_PWM2_TIM_CHANNEL1;
|
||||
hpwm2.PWM_Channel2 = PROJSET.TIM_PWM2_TIM_CHANNEL2;
|
||||
|
||||
//hpwm2.Duty_Shift_Ratio = shiftPHASE1;
|
||||
hpwm2.Duty_Shift_Ratio = shiftPHASE1;
|
||||
|
||||
hpwm3.hMasterPWM = &hpwm1;
|
||||
hpwm3.stim = hpwm1.stim;
|
||||
hpwm3.stim.htim.Instance = (TIM_TypeDef*)PROJSET.TIM_PWM3_INSTANCE;
|
||||
hpwm3.GPIOx = (GPIO_TypeDef*)PROJSET.TIM_PWM3_GPIOx;
|
||||
hpwm3.GPIO_PIN_X1 = PROJSET.TIM_PWM3_GPIO_PIN_X1;
|
||||
hpwm3.GPIO_PIN_X2 = PROJSET.TIM_PWM3_GPIO_PIN_X2;
|
||||
hpwm3.PWM_Channel1 = PROJSET.TIM_PWM3_TIM_CHANNEL1;
|
||||
hpwm3.PWM_Channel2 = PROJSET.TIM_PWM3_TIM_CHANNEL2;
|
||||
|
||||
//hpwm3.Duty_Shift_Ratio = shiftPHASE2;
|
||||
hpwm3.Duty_Shift_Ratio = shiftPHASE2;
|
||||
|
||||
PWM_SlavePhase_Init(&hpwm2);
|
||||
PWM_SlavePhase_Init(&hpwm3);
|
||||
|
||||
//----------TIMERS START-------------
|
||||
HAL_TIM_Base_Start_IT(&hpwm1.stim.htim); // timer for PWM
|
||||
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm1.PWM_Channel1); // PWM channel 1
|
||||
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm1.PWM_Channel2); // PWM channel 2
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief PWM Handler.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Управляет скважностью ШИМ.
|
||||
* @note This called from TIM_PWM_Handler
|
||||
*/
|
||||
void PWM_Handler(PWM_HandleTypeDef* hpwm)
|
||||
{
|
||||
uint16_t rotate_ind_A;
|
||||
uint16_t rotate_ind_B;
|
||||
uint16_t rotate_ind_C;
|
||||
// rotate pwm
|
||||
rotate_ind_A = PWM_Get_Duty_Table_Ind(hpwm, hpwm->stim.sTimFreqHz);
|
||||
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
|
||||
{
|
||||
rotate_ind_B = PWM_SlavePhase_Calc_TableInd(PWM_Set_pSlaveHandle(hpwm, hpwm2), rotate_ind_A);
|
||||
rotate_ind_C = PWM_SlavePhase_Calc_TableInd(PWM_Set_pSlaveHandle(hpwm, hpwm3), rotate_ind_A);
|
||||
}
|
||||
if (hpwm->PWM_Value == 0) // if value = 0 reset all channels
|
||||
{
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
return;
|
||||
}
|
||||
//--------BRIDGE MODE DISABLE--------
|
||||
if (PWM_Get_Mode(&hpwm1, PWM_BRIDGE_MODE) == 0)
|
||||
{
|
||||
//-----------PWM DC MODE-------------
|
||||
if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE))
|
||||
PWM_SingleChannel_Mode(hpwm, rotate_ind_A, 0);
|
||||
//------------SINUS MODE-------------
|
||||
else
|
||||
PWM_SingleChannel_Mode(hpwm, rotate_ind_A, 1);
|
||||
}
|
||||
//---------BRIDGE MODE ENABLE--------
|
||||
else
|
||||
{
|
||||
if (PWM_Get_Mode(&hpwm1, PWM_DC_MODE))
|
||||
//-----------PWM DC MODE-------------
|
||||
PWM_DC_Bridge_Mode(hpwm, rotate_ind_A, rotate_ind_B, rotate_ind_C);
|
||||
//------------SINUS MODE-------------
|
||||
else
|
||||
PWM_Sine_Bridge_Mode(hpwm, rotate_ind_A, rotate_ind_B, rotate_ind_C);
|
||||
}
|
||||
|
||||
//-----CHECK CHANNELS FOR ERRORS-----
|
||||
uint16_t min_duty = PWM_Calc_Min_Duty(hpwm);
|
||||
uint16_t max_duty = PWM_Calc_Max_Duty(hpwm);
|
||||
// IF FIRST CHANNEL IS ACRIVE
|
||||
if (PWM_Get_Compare1(hpwm) != 0)
|
||||
{
|
||||
// Duty shoud be bigger or equeal than min duration
|
||||
if (PWM_Get_Compare1(hpwm) < min_duty)
|
||||
PWM_Set_Compare1(hpwm, min_duty);
|
||||
// Duty shoud be less or equeal than ARR-min duration
|
||||
if (PWM_Get_Compare1(hpwm) > max_duty)
|
||||
PWM_Set_Compare1(hpwm, max_duty);
|
||||
}
|
||||
// IF SECOND CHANNEL IS ACRIVE
|
||||
else if (PWM_Get_Compare2(hpwm) != 0)
|
||||
{
|
||||
// Duty shoud be bigger or equeal than min duration
|
||||
if (PWM_Get_Compare2(hpwm) < min_duty)
|
||||
PWM_Set_Compare2(hpwm, min_duty);
|
||||
// Duty shoud be less or equeal than ARR
|
||||
if (PWM_Get_Compare2(hpwm) > max_duty)
|
||||
PWM_Set_Compare2(hpwm, max_duty);
|
||||
}
|
||||
// IF BOTH CHANNEL IS ACRIVE
|
||||
if ((PWM_Get_Compare1(hpwm) != 0) && (PWM_Get_Compare2(hpwm) != 0))
|
||||
{
|
||||
// Only one channel shoud be active so disable all
|
||||
PWM_Set_Compare1(hpwm, 0);
|
||||
PWM_Set_Compare2(hpwm, 0);
|
||||
}
|
||||
PWM_SlavePhase_Check_Channels(PWM_Set_pSlaveHandle(hpwm, hpwm2));
|
||||
PWM_SlavePhase_Check_Channels(PWM_Set_pSlaveHandle(hpwm, hpwm3));
|
||||
|
||||
if (hpwm->PWM_DeadTime)
|
||||
{
|
||||
PWM_CreateDeadTime(hpwm, &DeadTimeCnt_Master, &ActiveChannelSHDW_Master);
|
||||
PWM_SlavePhase_CreateDeadTime(PWM_Set_pSlaveHandle(hpwm, hpwm2), &DeadTimeCnt_Slave2, &ActiveChannelSHDW_Slave2);
|
||||
PWM_SlavePhase_CreateDeadTime(PWM_Set_pSlaveHandle(hpwm, hpwm3), &DeadTimeCnt_Slave3, &ActiveChannelSHDW_Slave3);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
///**
|
||||
// * @brief .
|
||||
// * @param hspwm - указатель на хендл слейв ШИМ.
|
||||
// * @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
// * @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
// */
|
||||
//void PWM_Sine_SingleChannel_Mode(PWM_HandleTypeDef *hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
|
||||
//{
|
||||
// //----------MASTER PWM-----------
|
||||
// PWM_Set_Duty_From_Table(hpwm, rotate_ind_A); // set phase 1 (A)
|
||||
//
|
||||
// //----------SLAVE PWMs-----------
|
||||
// if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
|
||||
// {
|
||||
// PWM_SlaveHandleTypeDef *hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm2);
|
||||
// PWM_Set_SlaveDuty_From_Table(hspwm, rotate_ind_B); // set phase 2 (B)
|
||||
//
|
||||
// hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm3);
|
||||
// PWM_Set_SlaveDuty_From_Table(hspwm, rotate_ind_C); // set phase 3 (C)
|
||||
// }
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_Sine_Bridge_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
|
||||
{
|
||||
//----------MASTER PWM-----------
|
||||
// SET PHASE 1 (A)
|
||||
int Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_A);
|
||||
// если это первая полуволна
|
||||
if (Duty >= 0) {
|
||||
PWM_Set_Compare1(hpwm, Duty + PWM_Calc_Min_Duty(hpwm)); // set first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, (-Duty) + PWM_Calc_Min_Duty(hpwm)); // set second channel
|
||||
}
|
||||
|
||||
//----------SLAVE PWMs-----------
|
||||
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
|
||||
{
|
||||
// SET PHASE 2 (B)
|
||||
PWM_SlaveHandleTypeDef* hspwm = PWM_Set_pSlaveHandle(hpwm, hpwm2);
|
||||
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_B);
|
||||
// если это первая полуволна
|
||||
if (Duty > 0) {
|
||||
PWM_Set_Compare1(hspwm, Duty + PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set first channel
|
||||
PWM_Set_Compare2(hspwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hspwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hspwm, (-Duty) + PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set second channel
|
||||
}
|
||||
|
||||
// SET PHASE 3 (C)
|
||||
hspwm = PWM_Set_pSlaveHandle(hpwm, hpwm3);
|
||||
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_C);
|
||||
// если это первая полуволна
|
||||
if (Duty > 0) {
|
||||
PWM_Set_Compare1(hspwm, Duty + PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set first channel
|
||||
PWM_Set_Compare2(hspwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hspwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hspwm, (-Duty) + PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set second channel
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_SingleChannel_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint8_t SineOrDC)
|
||||
{
|
||||
PWM_SlaveHandleTypeDef* hspwm2 = PWM_Set_pSlaveHandle(hpwm, hpwm2);
|
||||
PWM_SlaveHandleTypeDef* hspwm3 = PWM_Set_pSlaveHandle(hpwm, hpwm3);
|
||||
|
||||
// PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
// PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
// PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
|
||||
// PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
|
||||
// PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
|
||||
// PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
|
||||
|
||||
|
||||
switch (PWM_Get_Mode(hpwm, PWM_ACTIVECHANNEL_MODE))
|
||||
{
|
||||
case PWM_ACTIVECHANNEL_A0:
|
||||
if (SineOrDC)
|
||||
PWM_Set_Duty_From_Table(hpwm, hpwm->PWM_Channel1, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_Duty_From_Value(hpwm, hpwm->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
case PWM_ACTIVECHANNEL_A1:
|
||||
if (SineOrDC)
|
||||
PWM_Set_Duty_From_Table(hpwm, hpwm->PWM_Channel2, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_Duty_From_Value(hpwm, hpwm->PWM_Channel2); // set second channel
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
case PWM_ACTIVECHANNEL_B0:
|
||||
if (SineOrDC)
|
||||
PWM_Set_SlaveDuty_From_Table(hspwm2, hspwm2->PWM_Channel1, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_SlaveDuty_From_Value(hspwm2, hspwm2->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
case PWM_ACTIVECHANNEL_B1:
|
||||
if (SineOrDC)
|
||||
PWM_Set_SlaveDuty_From_Table(hspwm2, hspwm2->PWM_Channel2, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_SlaveDuty_From_Value(hspwm2, hspwm2->PWM_Channel2); // set second channel
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
case PWM_ACTIVECHANNEL_C0:
|
||||
if (SineOrDC)
|
||||
PWM_Set_SlaveDuty_From_Table(hspwm3, hspwm3->PWM_Channel1, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_SlaveDuty_From_Value(hspwm3, hspwm3->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
case PWM_ACTIVECHANNEL_C1:
|
||||
if (SineOrDC)
|
||||
PWM_Set_SlaveDuty_From_Table(hspwm3, hspwm3->PWM_Channel2, rotate_ind_A);
|
||||
else
|
||||
PWM_Set_SlaveDuty_From_Value(hspwm3, hspwm3->PWM_Channel2); // set second channel
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
break;
|
||||
|
||||
default:
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_DC_Bridge_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
|
||||
{
|
||||
//----------MASTER PWM-----------
|
||||
// SET PHASE 1 (A)
|
||||
int Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_A);
|
||||
// если это первая полуволна
|
||||
if (Duty >= 0) {
|
||||
PWM_Set_Duty_From_DutyBridge(hpwm, hpwm->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare2(hpwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hpwm, 0); // reset first channel
|
||||
PWM_Set_Duty_From_DutyBridge(hpwm, hpwm->PWM_Channel2); // set second channel
|
||||
}
|
||||
|
||||
//----------SLAVE PWMs-----------
|
||||
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
|
||||
{
|
||||
// SET PHASE 2 (B)
|
||||
PWM_SlaveHandleTypeDef* hspwm = PWM_Set_pSlaveHandle(hpwm, hpwm2);
|
||||
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_B);
|
||||
// если это первая полуволна
|
||||
if (Duty > 0) {
|
||||
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare2(hspwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hspwm, 0); // reset first channel
|
||||
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel2); // set second channel
|
||||
}
|
||||
|
||||
// SET PHASE 3 (C)
|
||||
hspwm = PWM_Set_pSlaveHandle(hpwm, hpwm3);
|
||||
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_C);
|
||||
// если это первая полуволна
|
||||
if (Duty > 0) {
|
||||
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel1); // set first channel
|
||||
PWM_Set_Compare2(hspwm, 0); // reset second channel
|
||||
}
|
||||
// если это вторая полуволна
|
||||
else {
|
||||
PWM_Set_Compare1(hspwm, 0); // reset first channel
|
||||
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel2); // set second channel
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm2), 0); // reset second channel
|
||||
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset first channel
|
||||
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm, hpwm3), 0); // reset second channel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Update PWM parameters.
|
||||
* @note Проверка надо ли обновлять параметры ШИМ, и если надо - обновляет их.
|
||||
* @note This called from TIM_CTRL_Handler
|
||||
*/
|
||||
void Update_Params_For_PWM(PWM_HandleTypeDef* hpwm)
|
||||
{
|
||||
unsigned UpdateModeParams = 0;
|
||||
unsigned UpdateLog = 0;
|
||||
|
||||
// READ PWM_VALUE
|
||||
if (hpwm->hramp.setpoint != int_to_percent(pwm_ctrl[R_PWM_CTRL_PWM_VALUE]))
|
||||
{
|
||||
hpwm->hramp.setpoint = int_to_percent(pwm_ctrl[R_PWM_CTRL_PWM_VALUE]);
|
||||
if ((hpwm->hramp.setpoint == 0) || // if zero - force reset pwm value
|
||||
(hpwm->PWM_Value != hpwm->PWM_Value)) // or if PWM_Value isnt in range
|
||||
{
|
||||
PWM_Ramp_Reset(hpwm);
|
||||
}
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
// UPDATE RAMP
|
||||
if (hpwm->hramp.setpoint > 0) // if setpiont inst zero
|
||||
PWM_Ramp_ControlPWMValue(hpwm);
|
||||
|
||||
// READ PWM_ACTIVECHANNEL_MODE
|
||||
uint16_t activechannesls = (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL)) |
|
||||
(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL + 1) << 1) |
|
||||
(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL + 2) << 2);
|
||||
if (PWM_Get_Mode(hpwm, PWM_ACTIVECHANNEL_MODE) != (activechannesls << PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
{
|
||||
uint16_t tmpmode = hpwm->sPWM_Mode & (~PWM_ACTIVECHANNEL_MODE);
|
||||
tmpmode |= activechannesls << PWM_ACTIVECHANNEL_MODE_Pos;
|
||||
|
||||
hpwm->sPWM_Mode = tmpmode;
|
||||
|
||||
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
// READ PWM_DC_MODE
|
||||
if (PWM_Get_Mode(hpwm, PWM_DC_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_DC_MODE) << PWM_DC_MODE_Pos))
|
||||
{
|
||||
if (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_DC_MODE))
|
||||
{
|
||||
hpwm->sPWM_Mode |= PWM_DC_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpwm->sPWM_Mode &= ~PWM_DC_MODE;
|
||||
}
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
// READ PWM_BRIDGE_MODE
|
||||
if (PWM_Get_Mode(hpwm, PWM_BRIDGE_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_BRIDGE_MODE) << PWM_BRIDGE_MODE_Pos))
|
||||
{
|
||||
if (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_BRIDGE_MODE))
|
||||
{
|
||||
hpwm->sPWM_Mode |= PWM_BRIDGE_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpwm->sPWM_Mode &= ~PWM_BRIDGE_MODE;
|
||||
}
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
|
||||
// READ PWM_PHASE_MODE
|
||||
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_PHASE_MODE) << PWM_PHASE_MODE_Pos))
|
||||
{
|
||||
if (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_PHASE_MODE))
|
||||
{
|
||||
hpwm->sPWM_Mode |= PWM_PHASE_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpwm->sPWM_Mode &= ~PWM_PHASE_MODE;
|
||||
}
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// READ PWM_POLARITY
|
||||
uint16_t polarity_temp = MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_POLARITY);
|
||||
if (((hpwm->stim.htim.Instance->CCER & TIM_CCER_CC1P) || (hpwm->stim.htim.Instance->CCER & TIM_CCER_CC3P)) != (polarity_temp))
|
||||
{
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&hpwm->stim.htim, hpwm->PWM_Channel1, polarity_temp << 1);
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&hpwm->stim.htim, hpwm->PWM_Channel2, polarity_temp << 1);
|
||||
|
||||
PWM_SlaveHandleTypeDef* shpwm = PWM_Set_pSlaveHandle(hpwm, hpwm2);
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel1, polarity_temp << 1);
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel2, polarity_temp << 1);
|
||||
|
||||
shpwm = PWM_Set_pSlaveHandle(hpwm, hpwm3);
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel1, polarity_temp << 1);
|
||||
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel2, polarity_temp << 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// READ TABLE_SIZE
|
||||
if (hpwm->Duty_Table_Size != pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE])
|
||||
{
|
||||
hpwm->Duty_Table_Size = PWM_Fill_Sine_Table(&hpwm1, pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE]);
|
||||
pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE] = hpwm->Duty_Table_Size;
|
||||
}
|
||||
|
||||
// READ DUTY_BRIDGE
|
||||
if (hpwm->PWM_DutyBridge != pwm_ctrl[R_PWM_CTRL_DUTY_BRIDGE])
|
||||
{
|
||||
hpwm->PWM_DutyBridge = int_to_percent(pwm_ctrl[R_PWM_CTRL_DUTY_BRIDGE]);
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
// READ MIN PULSE DURATION
|
||||
if (hpwm->PWM_MinPulseDur != pwm_ctrl[R_PWM_CTRL_MIN_PULSE_DUR])
|
||||
{
|
||||
hpwm->PWM_MinPulseDur = pwm_ctrl[R_PWM_CTRL_MIN_PULSE_DUR];
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
// READ MAX PULSE DURATION
|
||||
if ((hpwm->PWM_MaxPulseDur != pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR]) &&
|
||||
(pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] <= PWM_Get_Autoreload(hpwm)) &&
|
||||
(pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] != 0))
|
||||
{
|
||||
hpwm->PWM_MaxPulseDur = pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR];
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
else if (((hpwm->PWM_MaxPulseDur != PWM_Get_Autoreload(hpwm)) && (pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] == 0)) ||
|
||||
((hpwm->PWM_MaxPulseDur != PWM_Get_Autoreload(hpwm)) && (pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] > PWM_Get_Autoreload(hpwm))))
|
||||
{
|
||||
hpwm->PWM_MaxPulseDur = PWM_Get_Autoreload(hpwm);
|
||||
// update mode params
|
||||
UpdateModeParams = 1;
|
||||
}
|
||||
|
||||
|
||||
// READ DEAD TIME
|
||||
if (hpwm->PWM_DeadTime != pwm_ctrl[R_PWM_CTRL_DEAD_TIME])
|
||||
{
|
||||
hpwm->PWM_DeadTime = pwm_ctrl[R_PWM_CTRL_DEAD_TIME];
|
||||
}
|
||||
|
||||
|
||||
// UPDATE PWM PARAMS
|
||||
if (UpdateModeParams)
|
||||
{
|
||||
// UPDATE DUTY TABLE SCALE
|
||||
PWM_Update_DutyTableScale(hpwm);
|
||||
|
||||
|
||||
// update logs params
|
||||
UpdateLog = 1;
|
||||
}
|
||||
|
||||
// UPDATE LOG PARAMS
|
||||
if (UpdateLog)
|
||||
{
|
||||
// set logs params
|
||||
Set_Log_Params();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PID for ramp.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note ПИД-регулятор, который управляет скважностью ШИМ и не дает её изменяться резко.
|
||||
*/
|
||||
void PWM_Ramp_ControlPWMValue(PWM_HandleTypeDef* hpwm) {
|
||||
|
||||
/*
|
||||
* Error signal
|
||||
*/
|
||||
float error = hpwm->hramp.setpoint - hpwm->PWM_Value;
|
||||
|
||||
|
||||
/*
|
||||
* Proportional
|
||||
*/
|
||||
float proportional = hpwm->hramp.Kp * error;
|
||||
|
||||
|
||||
/* Limiting the accelerate */
|
||||
if (error > hpwm->hramp.limMaxInt) {
|
||||
|
||||
error = hpwm->hramp.limMaxInt;
|
||||
|
||||
}
|
||||
else if (error < hpwm->hramp.limMinInt) {
|
||||
|
||||
error = hpwm->hramp.limMinInt;
|
||||
|
||||
}
|
||||
|
||||
/* * Integral
|
||||
*/
|
||||
hpwm->hramp.integrator = hpwm->hramp.integrator + 0.5f * hpwm->hramp.Ki * hpwm->hramp.SampleT * (error + hpwm->hramp.prevError);
|
||||
|
||||
/* Anti-wind-up via integrator clamping */
|
||||
if (hpwm->hramp.integrator > hpwm->hramp.limMax) {
|
||||
|
||||
hpwm->hramp.integrator = hpwm->hramp.limMax;
|
||||
|
||||
}
|
||||
else if (hpwm->hramp.integrator < hpwm->hramp.limMin) {
|
||||
|
||||
hpwm->hramp.integrator = hpwm->hramp.limMin;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Derivative (band-limited differentiator)
|
||||
*/
|
||||
|
||||
hpwm->hramp.differentiator = -(2.0f * hpwm->hramp.Kd * (hpwm->PWM_Value - hpwm->hramp.prevMeasurement) /* Note: derivative on measurement, therefore minus sign in front of equation! */
|
||||
+ (2.0f * hpwm->hramp.tau - hpwm->hramp.SampleT) * hpwm->hramp.differentiator)
|
||||
/ (2.0f * hpwm->hramp.tau + hpwm->hramp.SampleT);
|
||||
|
||||
|
||||
/*
|
||||
* Compute output and apply limits
|
||||
*/
|
||||
hpwm->PWM_Value = proportional + hpwm->hramp.integrator + hpwm->hramp.differentiator;
|
||||
if (hpwm->PWM_Value > hpwm->hramp.limMax) {
|
||||
|
||||
hpwm->PWM_Value = hpwm->hramp.limMax;
|
||||
|
||||
}
|
||||
else if (hpwm->PWM_Value < hpwm->hramp.limMin) {
|
||||
|
||||
hpwm->PWM_Value = hpwm->hramp.limMin;
|
||||
|
||||
}
|
||||
|
||||
/* Store error and measurement for later use */
|
||||
hpwm->hramp.prevError = error;
|
||||
hpwm->hramp.prevMeasurement = hpwm->PWM_Value;
|
||||
|
||||
// /* set PWM Value output */
|
||||
// *hpwm->hramp.out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset PID for ramp.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Сбрасывает переменные ПИД-регулятора, чтобы потом его запустить "с чистого листа".
|
||||
*/
|
||||
void PWM_Ramp_Reset(PWM_HandleTypeDef* hpwm)
|
||||
{
|
||||
hpwm->PWM_Value = 0;
|
||||
|
||||
/* Clear controller variables */
|
||||
hpwm->hramp.integrator = 0.0f;
|
||||
hpwm->hramp.prevError = 0.0f;
|
||||
|
||||
hpwm->hramp.differentiator = 0.0f;
|
||||
hpwm->hramp.prevMeasurement = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief reInitialization of PWM TIM.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl
|
||||
* ШИМ генерируется на одном канале.
|
||||
*/
|
||||
void PWM_Sine_ReInit(PWM_HandleTypeDef* hpwm)
|
||||
{
|
||||
Trace_PWM_reInit_Enter();
|
||||
TIM_Base_MspDeInit(&hpwm->stim.htim);
|
||||
hpwm1.stim.sTickBaseMHz = TIMER_PWM_TICKBASE;
|
||||
hpwm1.sConfigOC.OCPolarity = MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_POLARITY) << TIM_CCER_CC1P_Pos;
|
||||
TIM_Base_Init(&hpwm->stim);
|
||||
TIM_Output_PWM_Init(&hpwm->stim.htim, &hpwm->sConfigOC, hpwm->PWM_Channel1, hpwm->GPIOx, hpwm->GPIO_PIN_X1);
|
||||
TIM_Output_PWM_Init(&hpwm->stim.htim, &hpwm->sConfigOC, hpwm->PWM_Channel2, hpwm->GPIOx, hpwm->GPIO_PIN_X2);
|
||||
|
||||
|
||||
|
||||
PWM_Update_DutyTableScale(hpwm);
|
||||
|
||||
|
||||
//----------TIMERS START-------------
|
||||
HAL_TIM_Base_Start_IT(&hpwm1.stim.htim); // timer for PWM
|
||||
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm->PWM_Channel1); // PWM channel 1
|
||||
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm->PWM_Channel2); // PWM channel 2
|
||||
|
||||
Trace_PWM_reInit_Exit();
|
||||
}
|
||||
/**
|
||||
* @brief Getting ind for Duty Table.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @param FreqTIM - частота таймера ШИМ.
|
||||
* @note Рассчитывает индекс для таблицы скважностей.
|
||||
* PWM_Value в hpwm - частота с которой эта таблица должна выводиться на ШИМ
|
||||
* @note This called from TIM_PWM_Handler
|
||||
*/
|
||||
uint32_t PWM_Get_Duty_Table_Ind(PWM_HandleTypeDef* hpwm, float FreqTIM)
|
||||
{
|
||||
float sine_ind_step;
|
||||
// calc ind for sin table
|
||||
if (hpwm->PWM_Value != 0) // if there some frequency
|
||||
{
|
||||
sine_ind_step = hpwm->Duty_Table_Size / (FreqTIM / hpwm->PWM_Value);
|
||||
hpwm->Duty_Table_Ind += sine_ind_step;
|
||||
}
|
||||
else
|
||||
return hpwm->Duty_Table_Size;
|
||||
|
||||
// overflow check
|
||||
if (hpwm->Duty_Table_Ind >= hpwm->Duty_Table_Size)
|
||||
hpwm->Duty_Table_Ind -= hpwm->Duty_Table_Size;
|
||||
if (hpwm->Duty_Table_Ind >= hpwm->Duty_Table_Size)
|
||||
hpwm->Duty_Table_Ind = 0;
|
||||
|
||||
// if its too big (e.g. inf)
|
||||
if ((hpwm->Duty_Table_Ind >= 0xFFFF) ||
|
||||
(hpwm->Duty_Table_Ind != hpwm->Duty_Table_Ind)) // in nan case
|
||||
hpwm->Duty_Table_Ind = 0;
|
||||
|
||||
return hpwm->Duty_Table_Ind;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create Dead Time when switches channels.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
*/
|
||||
void PWM_CreateDeadTime(PWM_HandleTypeDef* hpwm, float* LocalDeadTimeCnt, unsigned* LocalActiveChannel)
|
||||
{
|
||||
// get current active channel
|
||||
hpwm->fActiveChannel = (PWM_Get_Compare2(hpwm) != 0); // if channel two is active - write 1, otherwise - 0
|
||||
// when channels are swithed and no dead time currently active
|
||||
if (*LocalActiveChannel != hpwm->fActiveChannel)
|
||||
{ // update active channel
|
||||
*LocalActiveChannel = hpwm->fActiveChannel;
|
||||
// set deadtime
|
||||
*LocalDeadTimeCnt = hpwm->PWM_DeadTime;
|
||||
Trace_PWM_DeadTime_Enter();
|
||||
}
|
||||
// decrement dead time
|
||||
*LocalDeadTimeCnt -= (PWM_Get_Autoreload(hpwm) + 1) * hpwm->stim.sTickBaseMHz;
|
||||
if (*LocalDeadTimeCnt > 0) // if dead time is still active
|
||||
{ // reset all channels
|
||||
// reset channels
|
||||
PWM_Set_Compare1(hpwm, 0);
|
||||
PWM_Set_Compare2(hpwm, 0);
|
||||
}
|
||||
else // if dead time is done
|
||||
{ // set it to zero
|
||||
*LocalDeadTimeCnt = 0;
|
||||
Trace_PWM_DeadTime_Exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Filling table with one period of sinus values.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @param table_size - размер таблицы.
|
||||
* @note Формирует таблицу синусов размером table_size.
|
||||
*/
|
||||
uint32_t PWM_Fill_Sine_Table(PWM_HandleTypeDef* hpwm, uint32_t table_size)
|
||||
{
|
||||
if ((hpwm == NULL) || (hpwm->pDuty_Table_Origin == NULL) || (table_size == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (table_size > SIN_TABLE_SIZE_MAX)
|
||||
table_size = SIN_TABLE_SIZE_MAX;
|
||||
|
||||
|
||||
hpwm->Duty_Table_Size = table_size;
|
||||
float pi_step = 2 * M_PI / (hpwm->Duty_Table_Size);
|
||||
float pi_val = 0;
|
||||
float sin_koef = 0;
|
||||
uint32_t sin_val = 0;
|
||||
|
||||
// fill table with sinus
|
||||
for (int i = 0; i < hpwm->Duty_Table_Size; i++)
|
||||
{
|
||||
// rotate pi
|
||||
pi_val += pi_step;
|
||||
// calc sin value
|
||||
sin_koef = (float)0xFFFF;
|
||||
sin_val = (sin(pi_val) + 1) * sin_koef / 2;
|
||||
sin_table[i] = sin_val;
|
||||
}
|
||||
// fill rest of table with zeros
|
||||
for (int i = hpwm->Duty_Table_Size; i < SIN_TABLE_SIZE_MAX; i++)
|
||||
sin_table[i] = 0;
|
||||
|
||||
// if second channel is enabled
|
||||
PWM_Update_DutyTableScale(hpwm);
|
||||
|
||||
return hpwm->Duty_Table_Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calc and update new Duty Table Scale.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Используется, когда изменяется значение регистра ARR.
|
||||
*/
|
||||
void PWM_Update_DutyTableScale(PWM_HandleTypeDef* hpwm)
|
||||
{
|
||||
// UPDATE DUTY TABLE SCALE
|
||||
if (PWM_Get_Mode(hpwm, PWM_BRIDGE_MODE)) // if second channel is enabled
|
||||
{
|
||||
hpwm->Duty_Table_Scale = PWM_Calc_Duty_Scale(&hpwm1, 0x8000);
|
||||
}
|
||||
else
|
||||
{
|
||||
hpwm->Duty_Table_Scale = PWM_Calc_Duty_Scale(&hpwm1, 0xFFFF);
|
||||
}
|
||||
// for case if min pulse dur is too big and scale is negative
|
||||
if (hpwm->Duty_Table_Scale < 0)
|
||||
hpwm->Duty_Table_Scale = 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//-----------------------THREEPHASE FUNCTIONS------------------------
|
||||
/**
|
||||
* @brief Initialization of Slave PWM TIM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Вызывает функции инициализации и включения слейв ШИМ.
|
||||
*/
|
||||
void PWM_SlavePhase_Init(PWM_SlaveHandleTypeDef* hspwm)
|
||||
{
|
||||
TIM_Base_Init(&hspwm->stim);
|
||||
TIM_Output_PWM_Init(&hspwm->stim.htim, &hspwm->hMasterPWM->sConfigOC, hspwm->PWM_Channel1, hspwm->GPIOx, hspwm->GPIO_PIN_X1);
|
||||
TIM_Output_PWM_Init(&hspwm->stim.htim, &hspwm->hMasterPWM->sConfigOC, hspwm->PWM_Channel2, hspwm->GPIOx, hspwm->GPIO_PIN_X2);
|
||||
|
||||
// if three phase enables
|
||||
//----------TIMERS START-------------
|
||||
HAL_TIM_Base_Start(&hspwm->stim.htim);
|
||||
HAL_TIM_PWM_Start(&hspwm->stim.htim, hspwm->PWM_Channel1); // PWM channel 1
|
||||
HAL_TIM_PWM_Start(&hspwm->stim.htim, hspwm->PWM_Channel2); // PWM channel 2
|
||||
|
||||
if (PWM_Get_Mode(hspwm->hMasterPWM, PWM_PHASE_MODE) == 0) // if three phase disabled
|
||||
{
|
||||
PWM_Set_Compare1(hspwm, 0); // reset first channel
|
||||
PWM_Set_Compare2(hspwm, 0); // reset second channel
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief reInitialization of Slave PWM TIM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl.
|
||||
*/
|
||||
void PWM_SlavePhase_reInit(PWM_SlaveHandleTypeDef* hspwm)
|
||||
{
|
||||
PWM_Slave_CopyTimSetting(hspwm, sTimFreqHz);
|
||||
TIM_Base_MspDeInit(&hspwm->stim.htim);
|
||||
|
||||
PWM_SlavePhase_Init(hspwm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Duty from table on Slave PWM at one channel by sin_ind of the Master PWM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
uint16_t PWM_SlavePhase_Calc_TableInd(PWM_SlaveHandleTypeDef* hspwm, uint16_t rotate_ind_Phase)
|
||||
{
|
||||
// if three phase enables
|
||||
if (hspwm->Duty_Shift_Ratio > 0)
|
||||
rotate_ind_Phase += hspwm->hMasterPWM->Duty_Table_Size * hspwm->Duty_Shift_Ratio;
|
||||
else
|
||||
rotate_ind_Phase += hspwm->hMasterPWM->Duty_Table_Size * (1 + hspwm->Duty_Shift_Ratio);
|
||||
|
||||
// overflow check
|
||||
if (rotate_ind_Phase > hspwm->hMasterPWM->Duty_Table_Size)
|
||||
rotate_ind_Phase -= hspwm->hMasterPWM->Duty_Table_Size;
|
||||
if (rotate_ind_Phase > hspwm->hMasterPWM->Duty_Table_Size)
|
||||
rotate_ind_Phase = 0;;
|
||||
|
||||
|
||||
return rotate_ind_Phase;
|
||||
//
|
||||
// PWM_Set_SlaveDuty_From_Table(hspwm, sin_ind); // set first channel
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check is all Slave channels works properly.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Проверка работает ли только один из каналов, и проверка чтобы CCRx <= ARR
|
||||
* @note В мастере проверка происходит напрямую в PWM_Handler.
|
||||
*/
|
||||
void PWM_SlavePhase_Check_Channels(PWM_SlaveHandleTypeDef* hspwm)
|
||||
{
|
||||
uint16_t min_duty = PWM_Calc_Min_Duty(hspwm->hMasterPWM);
|
||||
uint16_t max_duty = PWM_Calc_Max_Duty(hspwm->hMasterPWM);
|
||||
// IF FIRST CHANNEL IS ACRIVE
|
||||
if (PWM_Get_Compare1(hspwm) != 0)
|
||||
{
|
||||
// Duty shoud be bigger or equeal than min duration
|
||||
if (PWM_Get_Compare1(hspwm) < min_duty)
|
||||
PWM_Set_Compare1(hspwm, min_duty);
|
||||
// Duty shoud be less or equeal than ARR-min duration
|
||||
if (PWM_Get_Compare1(hspwm) > max_duty)
|
||||
PWM_Set_Compare1(hspwm, max_duty);
|
||||
}
|
||||
// IF SECOND CHANNEL IS ACRIVE
|
||||
else if (PWM_Get_Compare2(hspwm) != 0)
|
||||
// Duty shoud be bigger or equeal than min duration
|
||||
if (PWM_Get_Compare2(hspwm) < min_duty)
|
||||
PWM_Set_Compare2(hspwm, min_duty);
|
||||
// Duty shoud be less or equeal than ARR
|
||||
if (PWM_Get_Compare2(hspwm) > max_duty)
|
||||
PWM_Set_Compare2(hspwm, max_duty);
|
||||
// IF BOTH CHANNEL IS ACRIVE
|
||||
if ((PWM_Get_Compare1(hspwm) != 0) && (PWM_Get_Compare2(hspwm) != 0))
|
||||
{
|
||||
// Only one channel shoud be active so disable all
|
||||
PWM_Set_Compare1(hspwm, 0);
|
||||
PWM_Set_Compare2(hspwm, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create Dead Time for Slave PWM when switches channels.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param LocalDeadTimeCnt - указатель на переменную для отсчитывания дедтайма.
|
||||
* @param LocalActiveChannel - указатель на переменную для отслеживания смены канала.
|
||||
* @note Аналог функции PWM_CreateDeadTime но для слейв ШИМов.
|
||||
*/
|
||||
void PWM_SlavePhase_CreateDeadTime(PWM_SlaveHandleTypeDef* hspwm, float* LocalDeadTimeCnt, unsigned* LocalActiveChannel)
|
||||
{
|
||||
// get current active channel
|
||||
hspwm->fActiveChannel = (PWM_Get_Compare2(hspwm) != 0); // if channel two is active - write 1, otherwise - 0
|
||||
// when channels are swithed and no dead time currently active
|
||||
if (*LocalActiveChannel != hspwm->fActiveChannel)
|
||||
{ // update active channel
|
||||
*LocalActiveChannel = hspwm->fActiveChannel;
|
||||
// set deadtime
|
||||
*LocalDeadTimeCnt = hspwm->hMasterPWM->PWM_DeadTime;
|
||||
Trace_PWM_DeadTime_Enter();
|
||||
}
|
||||
// decrement dead time
|
||||
*LocalDeadTimeCnt -= (PWM_Get_Autoreload(hspwm) + 1) * hspwm->hMasterPWM->stim.sTickBaseMHz;
|
||||
if (*LocalDeadTimeCnt > 0) // if dead time is still active
|
||||
{ // reset all channels
|
||||
// reset channels
|
||||
PWM_Set_Compare1(hspwm, 0);
|
||||
PWM_Set_Compare2(hspwm, 0);
|
||||
}
|
||||
else // if dead time is done
|
||||
{ // set it to zero
|
||||
*LocalDeadTimeCnt = 0;
|
||||
Trace_PWM_DeadTime_Exit();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
//------------------------HANDLERS FUNCTIONS-------------------------
|
||||
//---------------PWM TIMER-----------------
|
||||
#if (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 10) // choose handler for TIM
|
||||
void TIM1_UP_TIM10_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 2)
|
||||
void TIM2_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 3)
|
||||
void TIM3_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 4)
|
||||
void TIM4_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 5)
|
||||
void TIM5_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 6)
|
||||
void TIM6_DAC_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 7)
|
||||
void TIM7_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 13)
|
||||
void TIM8_UP_TIM13_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 9)
|
||||
void TIM1_BRK_TIM9_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 11)
|
||||
void TIM1_TRG_COM_TIM11_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 12)
|
||||
void TIM8_BRK_TIM12_IRQHandler(void)
|
||||
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 14)
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void)
|
||||
#endif
|
||||
{
|
||||
/* TIM_PWM_Handler */
|
||||
Trace_PWM_TIM_Enter();
|
||||
HAL_TIM_IRQHandler(&hpwm1.stim.htim);
|
||||
PWM_Handler(&hpwm1);
|
||||
|
||||
Trace_PWM_TIM_Exit();
|
||||
}
|
||||
|
||||
471
научка/code/matlab_stm_emulate/Code/PWM/pwm.h
Normal file
471
научка/code/matlab_stm_emulate/Code/PWM/pwm.h
Normal file
@@ -0,0 +1,471 @@
|
||||
/********************************MODBUS*************************************
|
||||
Данный файл содержит объявления базовых функции и дефайны для реализации
|
||||
MODBUS.
|
||||
Данный файл необходимо подключить в rs_message.h. После подключать rs_message.h
|
||||
к основному проекту.
|
||||
***************************************************************************/
|
||||
#ifndef __PWM_H_
|
||||
#define __PWM_H_
|
||||
#include "control.h"
|
||||
|
||||
|
||||
|
||||
extern uint32_t sin_table[SIN_TABLE_SIZE_MAX];
|
||||
#define int_to_percent(_int_) ((float)_int_/100)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////---DEFINES---////////////////////////////
|
||||
//----------------------------PWM HANDLE----------------------------//
|
||||
/**
|
||||
* @brief Calc duration of maximum pulse in ticks.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @return _val_ - количество тиков кратчайшего импульса.
|
||||
*/
|
||||
#define PWM_Calc_Max_Duty(_hpwm_) ((_hpwm_)->PWM_MaxPulseDur/(_hpwm_)->stim.sTickBaseMHz)
|
||||
/**
|
||||
* @brief Calc duration of minimum pulse in ticks.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @return _val_ - количество тиков кратчайшего импульса.
|
||||
*/
|
||||
#define PWM_Calc_Min_Duty(_hpwm_) ((_hpwm_)->PWM_MinPulseDur/(_hpwm_)->stim.sTickBaseMHz)
|
||||
/**
|
||||
* @brief Calc Scale Koef for Table & AUTORELOAD REGISTER
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _scale_ - верхняя граница диапазона значений.
|
||||
* @return _koef_ - коэффициент для масштабирования.
|
||||
* @note Данный макрос рассчитывает коэффициент для приведения значений с диапазоном [0,_scale_]
|
||||
к регистру автозагрузки с диапазоном [min, max], где min, max - минимальная и максимальная длительность импульса в тактах.
|
||||
*/
|
||||
#define PWM_Calc_Duty_Scale(_hpwm_, _scale_) ((float)(PWM_Calc_Max_Duty(_hpwm_)-PWM_Calc_Min_Duty(_hpwm_))/(_scale_))
|
||||
|
||||
/**
|
||||
* @brief Get Table Element Scaled corresponding to TIM ARR register
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _ind_ - номер элемента из таблицы скважностей.
|
||||
* @return _val_ - масштабированный под регистры таймера значение.
|
||||
* @note Если задана минимальная длительность импульса в тактах n,
|
||||
то регистр ARR заполняется так, что диапазон его значений будет [n, ARR-n]
|
||||
*/
|
||||
#define PWM_Get_Table_Element_Unsigned(_hpwm_,_ind_) (*((_hpwm_)->pDuty_Table_Origin+_ind_)*((_hpwm_)->Duty_Table_Scale))
|
||||
|
||||
/**
|
||||
* @brief Get Table Element Scaled and Shifted corresponding to TIM ARR register
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _ind_ - номер элемента из таблицы скважностей.
|
||||
* @return _val_ - масштабированный под регистры таймера значение.
|
||||
* @note По сути такая же как PWM_Get_Table_Element_Unsigned но добавляется сдвиг на одну амплитуду для учитывания знака.
|
||||
(если точнее, то сдвиг добавляется для компенсации сдвига, который имитирует знак)
|
||||
* @note 0x8000*(_hpwm_)->Duty_Table_Scale - т.к. первая полуволна находится в диапазоне (0x8000-0xFFFF) вычитаем константу 0x8000 с масштабированием
|
||||
*/
|
||||
#define PWM_Get_Table_Element_Signed(_hpwm_,_ind_) ((int)(*((_hpwm_)->pDuty_Table_Origin+_ind_)*((_hpwm_)->Duty_Table_Scale))-0x8000*(_hpwm_)->Duty_Table_Scale)
|
||||
/**
|
||||
* @brief Create pointer to slave PWM from pointer to void in PWM_HandleTypeDef.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _slavepwm_ - имя слейв pwm.
|
||||
* @return _pslavepwm_ - указатель на структуру PWM_SlaveHandleTypeDef.
|
||||
*/
|
||||
#define PWM_Set_pSlaveHandle(_hpwm_,_slavepwm_) ((PWM_SlaveHandleTypeDef *)_hpwm_->_slavepwm_)
|
||||
/**
|
||||
* @brief Copy setting from master TIM_SettingsTypeDef to slave TIM_SettingsTypeDef.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @return _set_ - имя настройки.
|
||||
*/
|
||||
#define PWM_Slave_CopyTimSetting(_hspwm_, _set_) ((_hspwm_)->stim._set_ = (_hspwm_)->hMasterPWM->stim._set_)
|
||||
|
||||
//---------------------------TIMER REGS----------------------------//
|
||||
/**
|
||||
* @brief Set PWM autoreload value (max duty value).
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _val_ - значение, которое нужно записать в Compare.
|
||||
*/
|
||||
#define PWM_Get_Autoreload(_hpwm_) __HAL_TIM_GET_AUTORELOAD(&((_hpwm_)->stim.htim))
|
||||
|
||||
/**
|
||||
* @brief Get PWM Duty on corresponding channel.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _val_ - значение, которое нужно записать в Compare.
|
||||
*/
|
||||
#define PWM_Get_Compare1(_hpwm_) __HAL_TIM_GET_COMPARE(&((_hpwm_)->stim.htim), (_hpwm_)->PWM_Channel1)
|
||||
#define PWM_Get_Compare2(_hpwm_) __HAL_TIM_GET_COMPARE(&((_hpwm_)->stim.htim), (_hpwm_)->PWM_Channel2)
|
||||
|
||||
/**
|
||||
* @brief Set PWM Duty on corresponding channel.
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _val_ - значение, которое нужно записать в Compare.
|
||||
*/
|
||||
#define PWM_Set_Compare1(_hpwm_, _val_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), (_hpwm_)->PWM_Channel1, (_val_))
|
||||
#define PWM_Set_Compare2(_hpwm_, _val_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), (_hpwm_)->PWM_Channel2, (_val_))
|
||||
|
||||
/**
|
||||
* @brief Set PWM Duty From PWM_Value Percent
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
*/
|
||||
#define PWM_Set_Duty_From_Value(_hpwm_, _channel_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, ((_hpwm_)->PWM_Value/100)*(PWM_Get_Autoreload(_hpwm_)+1))
|
||||
/**
|
||||
* @brief Set PWM Duty From PWM_DutyBridge Percent
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
*/
|
||||
#define PWM_Set_Duty_From_DutyBridge(_hpwm_, _channel_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, ((_hpwm_)->PWM_DutyBridge/100)*(PWM_Get_Autoreload(_hpwm_)+1))
|
||||
/**
|
||||
* @brief Set PWM Duty From table
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
* @param _ind_ - номер элемента из таблицы скважностей.
|
||||
*/
|
||||
#define PWM_Set_Duty_From_Table(_hpwm_, _channel_, _ind_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, (PWM_Get_Table_Element_Unsigned((_hpwm_), (_ind_))+1))
|
||||
|
||||
/**
|
||||
* @brief Set PWM Duty From PWM_Value Percent
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
*/
|
||||
#define PWM_Set_SlaveDuty_From_Value(_hpwm_, _channel_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, ((_hpwm_)->hMasterPWM->PWM_Value/100)*(PWM_Get_Autoreload(_hpwm_)+1))
|
||||
|
||||
/**
|
||||
* @brief Set PWM Duty From PWM_DutyBridge Percent
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
*/
|
||||
#define PWM_Set_SlaveDuty_From_DutyBridge(_hpwm_, _channel_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, ((_hpwm_)->hMasterPWM->PWM_DutyBridge/100)*(PWM_Get_Autoreload(_hpwm_)+1))
|
||||
/**
|
||||
* @brief Set PWM Duty From table
|
||||
* @param _hpwm_ - указатель на хендл pwm.
|
||||
* @param _channel_ - канал для выставления скважности.
|
||||
* @param _ind_ - номер элемента из таблицы скважностей.
|
||||
*/
|
||||
#define PWM_Set_SlaveDuty_From_Table(_hpwm_, _channel_, _ind_) __HAL_TIM_SET_COMPARE(&((_hpwm_)->stim.htim), _channel_, (PWM_Get_Table_Element_Unsigned((_hpwm_)->hMasterPWM, (_ind_))+1))
|
||||
|
||||
|
||||
// MODE DEFINES
|
||||
#define PWM_DC_MODE_Pos (0) // 0 - PWM has Sine form duty, 1 - PWM has DC duty
|
||||
#define PWM_BRIDGE_MODE_Pos (1) // 0 - PWM generated only on one channel (@ref PWM_ACTIVECHANNEL_MODE)
|
||||
// 1 - PWM generated at two channels of phase (@ref PWM_PHASE_MODE)
|
||||
#define PWM_PHASE_MODE_Pos (2) // 0 - PWM generated only at phase "A", 1 - PWM generated and three phase "A", "B", "C"
|
||||
#define PWM_ACTIVECHANNEL_MODE_Pos (3) // 0 - One channel PWM doesnt generated, 1 - PWM generated on corresponting channel № "PWM_ACTIVECHANNEL_MODE"
|
||||
|
||||
#define PWM_DC_MODE (1<<(PWM_DC_MODE_Pos)) // 0 - PWM has Sine form duty, 1 - PWM has DC duty
|
||||
|
||||
#define PWM_BRIDGE_MODE (1<<(PWM_BRIDGE_MODE_Pos)) // 0 - PWM generated only on one channel (@ref PWM_ACTIVECHANNEL_MODE)
|
||||
// 1 - PWM generated at two channels of phase (@ref PWM_PHASE_MODE)
|
||||
#define PWM_PHASE_MODE (1<<(PWM_PHASE_MODE_Pos)) // 0 - PWM generated only at phase "A", 1 - PWM generated and three phase "A", "B", "C"
|
||||
|
||||
#define PWM_ACTIVECHANNEL_MODE (0x7<<(PWM_ACTIVECHANNEL_MODE_Pos)) // 0 - One channel PWM doesnt generated, 1 - PWM generated on corresponting channel № "PWM_ACTIVECHANNEL_MODE"
|
||||
#define PWM_ACTIVECHANNEL_DISABLE (0x0<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_A0 (0x1<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_A1 (0x2<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_B0 (0x3<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_B1 (0x4<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_C0 (0x5<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
#define PWM_ACTIVECHANNEL_C1 (0x6<<(PWM_ACTIVECHANNEL_MODE_Pos))
|
||||
|
||||
#define PWM_Get_Mode(_hpwm_, _mode_) ((_hpwm_)->sPWM_Mode&(_mode_))
|
||||
/* Structure for PWM modes */
|
||||
typedef enum
|
||||
{
|
||||
// SINE MODES
|
||||
PWM_SINE_SINGLE = 0, /* set pwm duty from table with PWM_Value Hz */
|
||||
PWM_SINE_BRIDGE = PWM_BRIDGE_MODE, /* set pwm duty from table with PWM_Value Hz on two channels (positive and negative halfes) */
|
||||
PWM_SINE_3PHASE = PWM_BRIDGE_MODE | PWM_PHASE_MODE, /* set pwm table duty on three phase with PWM_Value Hz */
|
||||
// DC MODES
|
||||
PWM_DC_SINGLE = PWM_DC_MODE, /* set pwm duty PWM_Value (in percent) on one channel (@ref PWM_ACTIVECHANNEL_MODE) */
|
||||
PWM_DC_BRIDGE = PWM_DC_MODE | PWM_BRIDGE_MODE, /* set pwm duty PWM_DutyBridge (in percent) on two channel with PWM_Value Hz */
|
||||
PWM_DC_3PHASE = PWM_DC_MODE | PWM_BRIDGE_MODE | PWM_PHASE_MODE, /* set pwm PWM_DutyBridge duty on three phase with PWM_Value Hz, with requested shift */
|
||||
|
||||
// Variables of signel channel modes
|
||||
PWM_SINE_SINGLE_A0 = PWM_ACTIVECHANNEL_A0, /* set sine pwm on Phase A channel 0 */
|
||||
PWM_SINE_SINGLE_A1 = PWM_ACTIVECHANNEL_A1, /* set sine pwm on Phase A channel 1 */
|
||||
PWM_SINE_SINGLE_B0 = PWM_ACTIVECHANNEL_B0, /* set sine pwm on Phase B channel 0 */
|
||||
PWM_SINE_SINGLE_B1 = PWM_ACTIVECHANNEL_B1, /* set sine pwm on Phase B channel 1 */
|
||||
PWM_SINE_SINGLE_C0 = PWM_ACTIVECHANNEL_C0, /* set sine pwm on Phase C channel 0 */
|
||||
PWM_SINE_SINGLE_C1 = PWM_ACTIVECHANNEL_C1, /* set sine pwm on Phase C channel 1 */
|
||||
PWM_SINE_BRIDGE_A0 = PWM_DC_MODE | PWM_ACTIVECHANNEL_A0, /* set DC pwm on Phase A channel 0) */
|
||||
PWM_SINE_BRIDGE_A1 = PWM_DC_MODE | PWM_ACTIVECHANNEL_A1, /* set DC pwm on Phase A channel 1) */
|
||||
PWM_SINE_BRIDGE_B0 = PWM_DC_MODE | PWM_ACTIVECHANNEL_B0, /* set DC pwm on Phase B channel 0) */
|
||||
PWM_SINE_BRIDGE_B1 = PWM_DC_MODE | PWM_ACTIVECHANNEL_B1, /* set DC pwm on Phase B channel 1) */
|
||||
PWM_SINE_BRIDGE_C0 = PWM_DC_MODE | PWM_ACTIVECHANNEL_C0, /* set DC pwm on Phase C channel 0) */
|
||||
PWM_SINE_BRIDGE_C1 = PWM_DC_MODE | PWM_ACTIVECHANNEL_C1, /* set DC pwm on Phase C channel 1) */
|
||||
}PWM_ModeTypeDef;
|
||||
|
||||
/**
|
||||
* @brief Structure for PWM modbus coils.
|
||||
*/
|
||||
typedef struct // PWM_ModeCoilsTypeDef
|
||||
{
|
||||
unsigned reserved : 1; /* reserved bits */
|
||||
unsigned DC : 1; /* DC mode: PWM duty, Sine mode: frequency*/
|
||||
unsigned BRIDGE : 1; /* Bridge mode: */
|
||||
unsigned PHASE : 1; /* minimum pulse duration for PWM in us*/
|
||||
unsigned POLARITY : 1; /* minimum pulse duration for PWM in us*/
|
||||
unsigned ACTIVECHANNEL : 3; /* minimum pulse duration for PWM in us*/
|
||||
|
||||
|
||||
}PWM_ModeCoilsTypeDef;
|
||||
|
||||
/**
|
||||
* @brief Structure for PWM modbus registers.
|
||||
*/
|
||||
typedef struct // PWM_ModeRegsTypeDef
|
||||
{
|
||||
|
||||
uint16_t Value; /* DC mode: PWM duty, Table mode: frequency*/
|
||||
uint16_t TIMFreqHz; /* frequency of pwm timer */
|
||||
uint16_t DutyBridge; /* frequency of pwm timer */
|
||||
uint16_t MaxPulseDur; /* maximum pulse duration for PWM in us*/
|
||||
uint16_t MinPulseDur; /* minimum pulse duration for PWM in us*/
|
||||
uint16_t DeadTime; /* dead-Time between switches half waves (channels) in us */
|
||||
uint16_t TableSize; /* */
|
||||
|
||||
}PWM_ModeRegsTypeDef;
|
||||
|
||||
/**
|
||||
* @brief Structure for PWM config.
|
||||
*/
|
||||
typedef struct // PWM_ConfigTypeDef
|
||||
{
|
||||
PWM_ModeCoilsTypeDef* PWM_Mode;
|
||||
PWM_ModeRegsTypeDef* PWM_Settings;
|
||||
}PWM_ConfigTypeDef;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* Controller gains */
|
||||
float Kp;
|
||||
float Ki;
|
||||
float Kd;
|
||||
|
||||
/* Derivative low-pass filter time constant */
|
||||
float tau;
|
||||
|
||||
/* Output limits */
|
||||
float limMin;
|
||||
float limMax;
|
||||
|
||||
/* Integrator limits */
|
||||
float limMinInt;
|
||||
float limMaxInt;
|
||||
|
||||
/* Sample time (in seconds) */
|
||||
float SampleT;
|
||||
|
||||
/* Controller "memory" */
|
||||
float integrator;
|
||||
float prevError; /* Required for integrator */
|
||||
float differentiator;
|
||||
float prevMeasurement; /* Required for differentiator */
|
||||
|
||||
/* input */
|
||||
float setpoint;
|
||||
|
||||
} PWM_RampHandleTypeDef;
|
||||
/**
|
||||
* @brief Handle for PWM.
|
||||
* @note Prefixes: h - handle, s - settings, f - flag
|
||||
*/
|
||||
typedef struct // PWM_HandleTypeDef
|
||||
{
|
||||
/* PWM VARIABLES */
|
||||
PWM_ModeTypeDef sPWM_Mode; /* PWM current mode */
|
||||
PWM_ConfigTypeDef sPWM_Config; /* PWM modbus config */
|
||||
float PWM_Value; /* DC mode: PWM duty, Table mode: frequency*/
|
||||
float PWM_DutyBridge; /* Duty for DC bridge mode */
|
||||
uint32_t PWM_MaxPulseDur; /* maximum pulse duration for PWM in us*/
|
||||
uint32_t PWM_MinPulseDur; /* minimum pulse duration for PWM in us*/
|
||||
uint32_t PWM_DeadTime; /* dead-Time between switches half waves (channels) in us */
|
||||
PWM_RampHandleTypeDef hramp; /* handle for ramp */
|
||||
uint8_t PWM_enHardware; /* enable PWM output on transistor */
|
||||
|
||||
/* SETTINGS FOR TIMER */
|
||||
TIM_SettingsTypeDef stim; /* settings for TIM */
|
||||
TIM_OC_InitTypeDef sConfigOC; /* settings for oc channel */
|
||||
unsigned fActiveChannel; /* flag for active oc channel: 0 - first channel, 1 - second channel */
|
||||
uint16_t PWM_Channel1; /* instance of first channel */
|
||||
uint16_t PWM_Channel2; /* instance of second channel */
|
||||
|
||||
/* VARIABLES FOR TABLE DUTY PARAMETERS */
|
||||
uint32_t* pDuty_Table_Origin; /* pointer to table of pwm duties */
|
||||
uint32_t Duty_Table_Size; /* size of duty table */
|
||||
float Duty_Table_Ind; /* current ind of duty table */
|
||||
float Duty_Table_Scale; /* scale for TIM ARR register */
|
||||
|
||||
/* SETTIGNS FOR PWM OUTPUT */
|
||||
GPIO_TypeDef* GPIOx; /* GPIO port for PWM output */
|
||||
uint32_t GPIO_PIN_X1; /* GPIO pin for PWM output */
|
||||
uint32_t GPIO_PIN_X2; /* GPIO pin for PWM output (second half wave) */
|
||||
|
||||
/* SLAVES PWM */
|
||||
void* hpwm2;
|
||||
void* hpwm3;
|
||||
|
||||
}PWM_HandleTypeDef;
|
||||
extern PWM_HandleTypeDef hpwm1;
|
||||
|
||||
/**
|
||||
* @brief Handle for Slave PWM.
|
||||
* @note Prefixes: h - handle, s - settings, f - flag
|
||||
*/
|
||||
typedef struct // PWM_SlaveHandleTypeDef
|
||||
{
|
||||
/* MASTER PWM*/
|
||||
PWM_HandleTypeDef* hMasterPWM; /* master pwm handle */
|
||||
|
||||
/* SETTINGS FOR TIMER */
|
||||
TIM_SettingsTypeDef stim; /* slave tim handle */
|
||||
unsigned fActiveChannel; /* flag for active oc channel: 0 - first channel, 1 - second channel */
|
||||
uint16_t PWM_Channel1; /* instance of first channel */
|
||||
uint16_t PWM_Channel2; /* instance of second channel */
|
||||
|
||||
/* VARIABLES FOR TABLE DUTY PARAMETERS */
|
||||
float Duty_Shift_Ratio; /* Ratio of table shift: 0.5 shift - shift = Table_Size/2 */
|
||||
|
||||
/* SETTIGNS FOR PWM OUTPUT */
|
||||
GPIO_TypeDef* GPIOx; /* GPIO port for PWM output */
|
||||
uint32_t GPIO_PIN_X1; /* GPIO pin for PWM output */
|
||||
uint32_t GPIO_PIN_X2; /* GPIO pin for PWM output (second half wave) */
|
||||
}PWM_SlaveHandleTypeDef;
|
||||
extern PWM_SlaveHandleTypeDef hpwm2;
|
||||
extern PWM_SlaveHandleTypeDef hpwm3;
|
||||
|
||||
//--------------------------------PWM FUNCTIONS----------------------------------
|
||||
/**
|
||||
* @brief reInitialization of PWM TIM.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl.
|
||||
*/
|
||||
void PWM_Sine_ReInit(PWM_HandleTypeDef* hpwm);
|
||||
|
||||
/**
|
||||
* @brief Initialization of Slave PWM TIM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Вызывает функции инициализации и включения слейв ШИМ.
|
||||
*/
|
||||
void PWM_SlavePhase_Init(PWM_SlaveHandleTypeDef* hspwm);
|
||||
/**
|
||||
* @brief reInitialization of Slave PWM TIM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl.
|
||||
*/
|
||||
void PWM_SlavePhase_reInit(PWM_SlaveHandleTypeDef* hspwm);
|
||||
|
||||
/**
|
||||
* @brief Filling table with one period of sinus values.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @param table_size - размер таблицы.
|
||||
* @note Формирует таблицу синусов размером table_size.
|
||||
*/
|
||||
uint32_t PWM_Fill_Sine_Table(PWM_HandleTypeDef* hpwm, uint32_t table_size);
|
||||
|
||||
/**
|
||||
* @brief Calc and update new Duty Table Scale.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Используется, когда изменяется значение регистра ARR.
|
||||
*/
|
||||
void PWM_Update_DutyTableScale(PWM_HandleTypeDef* hpwm);
|
||||
//---------------------this called from TIM_PWM_Handler()------------------------
|
||||
// MASTER PWM FUNCTIONS
|
||||
/**
|
||||
* @brief PWM Handler.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Управляет скважность ШИМ в режиме PWM_TABLE.
|
||||
* @note This called from TIM_PWM_Handler
|
||||
*/
|
||||
void PWM_Handler(PWM_HandleTypeDef* hpwm);
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_Sine_Bridge_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C);
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_SingleChannel_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint8_t SineOrDC);
|
||||
/**
|
||||
* @brief .
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
void PWM_DC_Bridge_Mode(PWM_HandleTypeDef* hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C);
|
||||
/**
|
||||
* @brief Getting ind for Duty Table.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @param FreqTIM - частота таймера ШИМ.
|
||||
* @note Рассчитывает индекс для таблицы скважностей.
|
||||
* PWM_Value в hpwm - частота с которой эта таблица должна выводиться на ШИМ
|
||||
* @note This called from TIM_PWM_Handler
|
||||
*/
|
||||
uint32_t PWM_Get_Duty_Table_Ind(PWM_HandleTypeDef* hpwm, float FreqTIM);
|
||||
|
||||
/**
|
||||
* @brief Create Dead Time when switches channels.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @param LocalDeadTimeCnt - указатель на переменную для отсчитывания дедтайма.
|
||||
* @param LocalActiveChannel - указатель на переменную для отслеживания смены канала.
|
||||
*/
|
||||
void PWM_CreateDeadTime(PWM_HandleTypeDef* hpwm, float* LocalDeadTimeCnt, unsigned* LocalActiveChannel);
|
||||
|
||||
// SLAVE PWM FUNCTIONS
|
||||
/**
|
||||
* @brief Set Duty from table on Slave PWM at one channel by sin_ind of the Master PWM.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param sin_ind - индекс таблицы для Мастер ШИМ.
|
||||
* @note Индекс для свейл ШИМ расчитывается в самой функции.
|
||||
*/
|
||||
uint16_t PWM_SlavePhase_Calc_TableInd(PWM_SlaveHandleTypeDef* hspwm, uint16_t sin_ind);
|
||||
|
||||
/**
|
||||
* @brief Check is all Slave channels works properly.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @note Проверка работает ли только один из каналов, и проверка чтобы CCRx <= ARR
|
||||
* @note В мастере проверка происходит напрямую в PWM_Handler.
|
||||
*/
|
||||
void PWM_SlavePhase_Check_Channels(PWM_SlaveHandleTypeDef* hspwm);
|
||||
/**
|
||||
* @brief Create Dead Time for Slave PWM when switches channels.
|
||||
* @param hspwm - указатель на хендл слейв ШИМ.
|
||||
* @param LocalDeadTimeCnt - указатель на переменную для отсчитывания дедтайма.
|
||||
* @param LocalActiveChannel - указатель на переменную для отслеживания смены канала.
|
||||
* @note Аналог функции PWM_CreateDeadTime но для слейв ШИМов.
|
||||
*/
|
||||
void PWM_SlavePhase_CreateDeadTime(PWM_SlaveHandleTypeDef* hspwm, float* LocalDeadTimeCnt, unsigned* LocalActiveChannel);
|
||||
//---------------------this called from TIM_CTRL_Handler()-----------------------
|
||||
/**
|
||||
* @brief Update PWM parameters.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Проверка надо ли обновлять параметры ШИМ, и если надо - обновляет их.
|
||||
* @note This called from TIM_CTRL_Handler
|
||||
*/
|
||||
void Update_Params_For_PWM(PWM_HandleTypeDef* hpwm);
|
||||
/**
|
||||
* @brief PID for ramp.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note ПИД-регулятор, который управляет скважностью ШИМ и не дает её изменяться резко.
|
||||
*/
|
||||
void PWM_Ramp_ControlPWMValue(PWM_HandleTypeDef* hpwm);
|
||||
/**
|
||||
* @brief Reset PID for ramp.
|
||||
* @param hpwm - указатель на хендл ШИМ.
|
||||
* @note Сбрасывает переменные ПИД-регулятора, чтобы потом его запустить "с чистого листа".
|
||||
*/
|
||||
void PWM_Ramp_Reset(PWM_HandleTypeDef* hpwm);
|
||||
|
||||
|
||||
//---------------------------this called from main()-----------------------------
|
||||
/**
|
||||
* @brief First set up of PWM Two Channel.
|
||||
* @note Первый инит ШИМ. Заполняет структуры и инициализирует таймер для генерации синуоидального ШИМ.
|
||||
* Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1)
|
||||
* ШИМ генерируется на одном канале.
|
||||
* @note This called from main OR by setted coil
|
||||
*/
|
||||
void PWM_Sine_FirstInit(void);
|
||||
|
||||
|
||||
#endif // __PWM_H_
|
||||
265
научка/code/matlab_stm_emulate/Code/PWM/settings.c
Normal file
265
научка/code/matlab_stm_emulate/Code/PWM/settings.c
Normal file
@@ -0,0 +1,265 @@
|
||||
#include "control.h"
|
||||
ProjectSettings_TypeDef PROJSET;
|
||||
uint32_t PageError = 0x00;
|
||||
uint8_t UpdateSettings = 0;
|
||||
|
||||
void WriteSettingsToMem(void)
|
||||
{
|
||||
FillStructWithDefines();
|
||||
//HAL_FLASH_Unlock();
|
||||
//
|
||||
//CheckSettingsInFLASH();
|
||||
//
|
||||
//if(CheckIsSettingsValid(&PROJSET)) // if new settings are invalid
|
||||
// PROJSET = *PROJSET_MEM; // take the old settings from mem
|
||||
//else // if new settings are valid
|
||||
// SetFlagUpdateSettingsInMem(); // save the new settings in mem (set flag to do this)
|
||||
//
|
||||
//HAL_FLASH_Lock();
|
||||
|
||||
}
|
||||
|
||||
void SetFlagUpdateSettingsInMem(void)
|
||||
{
|
||||
//UpdateSettings = 0;
|
||||
//// MODBUS settings
|
||||
//if(PROJSET_MEM->MB_DEVICE_ID != PROJSET.MB_DEVICE_ID)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->MB_SPEED != PROJSET.MB_SPEED)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->MB_GPIOX != PROJSET.MB_GPIOX)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->MB_GPIO_PIN_RX != PROJSET.MB_GPIO_PIN_RX)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->MB_GPIO_PIN_RX != PROJSET.MB_GPIO_PIN_RX)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->MB_MAX_TIMEOUT != PROJSET.MB_MAX_TIMEOUT)
|
||||
// UpdateSettings = 1;
|
||||
//
|
||||
//// PWM settings
|
||||
//if(PROJSET_MEM->TIM_PWM_TICKBASE != PROJSET.TIM_PWM_TICKBASE)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM_AHB_FREQ != PROJSET.TIM_PWM_AHB_FREQ)
|
||||
// UpdateSettings = 1;
|
||||
//
|
||||
//if(PROJSET_MEM->TIM_PWM1_TIM_CHANNEL1 != PROJSET.TIM_PWM1_TIM_CHANNEL1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM1_TIM_CHANNEL2 != PROJSET.TIM_PWM1_TIM_CHANNEL2)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM1_GPIOx != PROJSET.TIM_PWM1_GPIOx)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM1_GPIO_PIN_X1 != PROJSET.TIM_PWM1_GPIO_PIN_X1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM1_GPIO_PIN_X2 != PROJSET.TIM_PWM1_GPIO_PIN_X2)
|
||||
// UpdateSettings = 1;
|
||||
//
|
||||
//if(PROJSET_MEM->TIM_PWM2_INSTANCE != PROJSET.TIM_PWM2_INSTANCE)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM2_TIM_CHANNEL1 != PROJSET.TIM_PWM2_TIM_CHANNEL1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM2_TIM_CHANNEL2 != PROJSET.TIM_PWM2_TIM_CHANNEL2)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM2_GPIOx != PROJSET.TIM_PWM2_GPIOx)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM2_GPIO_PIN_X1 != PROJSET.TIM_PWM2_GPIO_PIN_X1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM2_GPIO_PIN_X2 != PROJSET.TIM_PWM2_GPIO_PIN_X2)
|
||||
// UpdateSettings = 1;
|
||||
//
|
||||
//if(PROJSET_MEM->TIM_PWM3_INSTANCE != PROJSET.TIM_PWM3_INSTANCE)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM3_TIM_CHANNEL1 != PROJSET.TIM_PWM3_TIM_CHANNEL1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM3_TIM_CHANNEL2 != PROJSET.TIM_PWM3_TIM_CHANNEL2)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM3_GPIOx != PROJSET.TIM_PWM3_GPIOx)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM3_GPIO_PIN_X1 != PROJSET.TIM_PWM3_GPIO_PIN_X1)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_PWM3_GPIO_PIN_X2 != PROJSET.TIM_PWM3_GPIO_PIN_X2)
|
||||
// UpdateSettings = 1;
|
||||
//
|
||||
//// CTRL settings
|
||||
//if(PROJSET_MEM->TIM_CTRL_TICKBASE != PROJSET.TIM_CTRL_TICKBASE)
|
||||
// UpdateSettings = 1;
|
||||
//if(PROJSET_MEM->TIM_CTRL_AHB_FREQ != PROJSET.TIM_CTRL_AHB_FREQ)
|
||||
// UpdateSettings = 1;
|
||||
}
|
||||
|
||||
|
||||
void UpdateSettingsInMem(void)
|
||||
{
|
||||
//if(UpdateSettings)
|
||||
//{
|
||||
// FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
// PageError = 0x00;
|
||||
//
|
||||
// EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;// erase pages
|
||||
// EraseInitStruct.Banks = FLASH_BANK_1;
|
||||
// EraseInitStruct.Sector = FLASH_SECTOR_4; //first sector for erase
|
||||
// EraseInitStruct.NbSectors = 1;// num of sector that need to be erased
|
||||
//
|
||||
// HAL_FLASH_Unlock();
|
||||
// HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
|
||||
//
|
||||
//
|
||||
// /* Wait for last operation to be completed */
|
||||
// if(FLASH_WaitForLastOperation((uint32_t)50000U) == HAL_OK)
|
||||
// {
|
||||
// /* If the previous operation is completed, proceed to program the new data */
|
||||
// CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
|
||||
// FLASH->CR |= FLASH_PSIZE_WORD;
|
||||
// FLASH->CR |= FLASH_CR_PG;
|
||||
// *PROJSET_MEM = PROJSET; // save the new settings in mem
|
||||
// }
|
||||
// HAL_FLASH_Lock();
|
||||
// UpdateSettings = 0;
|
||||
//}
|
||||
}
|
||||
|
||||
void FillSettingsWithDefines(void)
|
||||
{
|
||||
// rewrite all setting corresponding to defines
|
||||
|
||||
//FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
//PageError = 0x00;
|
||||
//
|
||||
//EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;// erase pages
|
||||
//EraseInitStruct.Banks = FLASH_BANK_1;
|
||||
//EraseInitStruct.Sector = FLASH_SECTOR_4; //first sector for erase
|
||||
//EraseInitStruct.NbSectors = 1;// num of sector that need to be erased
|
||||
//
|
||||
//HAL_FLASH_Unlock();
|
||||
//HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
|
||||
//// MODBUS settings
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_DEVICE_ID, MODBUS_DEVICE_ID);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_SPEED, MODBUS_SPEED);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_GPIOX, (uint32_t)MODBUS_GPIOX);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_GPIO_PIN_RX, MODBUS_GPIO_PIN_RX);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_GPIO_PIN_TX, MODBUS_GPIO_PIN_TX);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_MAX_TIMEOUT, MODBUS_MAX_TIMEOUT);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->MB_TIM_AHB_FREQ, MODBUS_TIM_AHB_FREQ);
|
||||
//
|
||||
//// PWM settings
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM_TICKBASE, TIMER_PWM_TICKBASE);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM_AHB_FREQ, TIMER_PWM_AHB_FREQ);
|
||||
//
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM1_TIM_CHANNEL1, TIMER_PWM1_TIM_CHANNEL1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM1_TIM_CHANNEL2, TIMER_PWM1_TIM_CHANNEL2);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM1_GPIOx, (uint32_t)TIMER_PWM1_GPIOx);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM1_GPIO_PIN_X1, TIMER_PWM1_GPIO_PIN_X1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM1_GPIO_PIN_X2, TIMER_PWM1_GPIO_PIN_X2);
|
||||
//
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_INSTANCE, (uint32_t)TIMER_PWM2_INSTANCE);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_TIM_CHANNEL1, TIMER_PWM2_TIM_CHANNEL1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_TIM_CHANNEL2, TIMER_PWM2_TIM_CHANNEL2);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_GPIOx, (uint32_t)TIMER_PWM2_GPIOx);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_GPIO_PIN_X1, TIMER_PWM2_GPIO_PIN_X1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM2_GPIO_PIN_X2, TIMER_PWM2_GPIO_PIN_X2);
|
||||
//
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_INSTANCE, (uint32_t)TIMER_PWM3_INSTANCE);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_TIM_CHANNEL1, TIMER_PWM3_TIM_CHANNEL1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_TIM_CHANNEL2, TIMER_PWM3_TIM_CHANNEL2);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_GPIOx, (uint32_t)TIMER_PWM3_GPIOx);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_GPIO_PIN_X1, TIMER_PWM3_GPIO_PIN_X1);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_PWM3_GPIO_PIN_X2, TIMER_PWM3_GPIO_PIN_X2);
|
||||
//
|
||||
//// CTRL settings
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_CTRL_TICKBASE, TIMER_CTRL_TICKBASE);
|
||||
//FLASH_WRITE_SETTING(PROJSET_MEM->TIM_CTRL_AHB_FREQ, TIMER_CTRL_AHB_FREQ);
|
||||
//HAL_FLASH_Lock();
|
||||
|
||||
}
|
||||
|
||||
void FillStructWithDefines(void)
|
||||
{
|
||||
// rewrite all setting corresponding to defines
|
||||
|
||||
|
||||
// MODBUS settings
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_DEVICE_ID, MODBUS_DEVICE_ID);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_SPEED, MODBUS_SPEED);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_GPIOX, MODBUS_GPIOX);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_GPIO_PIN_RX, MODBUS_GPIO_PIN_RX);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_GPIO_PIN_TX, MODBUS_GPIO_PIN_TX);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_MAX_TIMEOUT, MODBUS_MAX_TIMEOUT);
|
||||
STRUCT_WRITE_SETTING(PROJSET.MB_TIM_AHB_FREQ, MODBUS_TIM_AHB_FREQ);
|
||||
|
||||
// PWM settings
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM_TICKBASE, TIMER_PWM_TICKBASE);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM_AHB_FREQ, TIMER_PWM_AHB_FREQ);
|
||||
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM1_TIM_CHANNEL1, TIMER_PWM1_TIM_CHANNEL1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM1_TIM_CHANNEL2, TIMER_PWM1_TIM_CHANNEL2);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM1_GPIOx, TIMER_PWM1_GPIOx);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM1_GPIO_PIN_X1, TIMER_PWM1_GPIO_PIN_X1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM1_GPIO_PIN_X2, TIMER_PWM1_GPIO_PIN_X2);
|
||||
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_INSTANCE, TIMER_PWM2_INSTANCE);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_TIM_CHANNEL1, TIMER_PWM2_TIM_CHANNEL1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_TIM_CHANNEL2, TIMER_PWM2_TIM_CHANNEL2);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_GPIOx, TIMER_PWM2_GPIOx);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_GPIO_PIN_X1, TIMER_PWM2_GPIO_PIN_X1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM2_GPIO_PIN_X2, TIMER_PWM2_GPIO_PIN_X2);
|
||||
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_INSTANCE, TIMER_PWM3_INSTANCE);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_TIM_CHANNEL1, TIMER_PWM3_TIM_CHANNEL1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_TIM_CHANNEL2, TIMER_PWM3_TIM_CHANNEL2);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_GPIOx, TIMER_PWM3_GPIOx);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_GPIO_PIN_X1, TIMER_PWM3_GPIO_PIN_X1);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_PWM3_GPIO_PIN_X2, TIMER_PWM3_GPIO_PIN_X2);
|
||||
|
||||
// CTRL settings
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_CTRL_TICKBASE, TIMER_CTRL_TICKBASE);
|
||||
STRUCT_WRITE_SETTING(PROJSET.TIM_CTRL_AHB_FREQ, TIMER_CTRL_AHB_FREQ);
|
||||
|
||||
}
|
||||
void CheckSettingsInFLASH(void)
|
||||
{
|
||||
//if(CheckIsSettingsValid(PROJSET_MEM))
|
||||
// FillSettingsWithDefines();
|
||||
//
|
||||
//PROJSET = *PROJSET_MEM;
|
||||
}
|
||||
int CheckIsSettingsValid(ProjectSettings_TypeDef *set_struct)
|
||||
{
|
||||
// if some of setting are missing
|
||||
// chech MODBUS
|
||||
if((!IS_UART_BAUDRATE(set_struct->MB_SPEED) || (set_struct->MB_SPEED ) == 0) ||
|
||||
(!IS_GPIO_ALL_INSTANCE((GPIO_TypeDef *)set_struct->MB_GPIOX)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->MB_GPIO_PIN_TX)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->MB_GPIO_PIN_RX)) ||
|
||||
((set_struct->MB_TIM_AHB_FREQ) == 0))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// chech control tim
|
||||
if((set_struct->TIM_CTRL_AHB_FREQ) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// chech PWM tims
|
||||
if((set_struct->TIM_PWM_AHB_FREQ) == 0 ||
|
||||
(!IS_GPIO_ALL_INSTANCE((GPIO_TypeDef *)set_struct->TIM_PWM1_GPIOx)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM1_GPIO_PIN_X1)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM1_GPIO_PIN_X2)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM1_TIM_CHANNEL1)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM1_TIM_CHANNEL2)) ||
|
||||
(!IS_TIM_INSTANCE((TIM_TypeDef *)set_struct->TIM_PWM2_INSTANCE)) ||
|
||||
(!IS_GPIO_ALL_INSTANCE((GPIO_TypeDef *)set_struct->TIM_PWM2_GPIOx)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM2_GPIO_PIN_X1)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM2_GPIO_PIN_X2)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM2_TIM_CHANNEL1)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM2_TIM_CHANNEL2)) ||
|
||||
(!IS_TIM_INSTANCE((TIM_TypeDef *)set_struct->TIM_PWM3_INSTANCE)) ||
|
||||
(!IS_GPIO_ALL_INSTANCE((GPIO_TypeDef *)set_struct->TIM_PWM3_GPIOx)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM3_GPIO_PIN_X1)) ||
|
||||
(!IS_GPIO_PIN((GPIO_TypeDef *)set_struct->TIM_PWM3_GPIO_PIN_X2)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM3_TIM_CHANNEL1)) ||
|
||||
(!IS_TIM_CHANNELS(set_struct->TIM_PWM3_TIM_CHANNEL2)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
162
научка/code/matlab_stm_emulate/Code/PWM/settings.h
Normal file
162
научка/code/matlab_stm_emulate/Code/PWM/settings.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/********************************MODBUS*************************************
|
||||
Данный файл содержит объявления базовых функции и дефайны для реализации
|
||||
MODBUS.
|
||||
Данный файл необходимо подключить в rs_message.h. После подключать rs_message.h
|
||||
к основному проекту.
|
||||
***************************************************************************/
|
||||
#ifndef __PROJ_SETTINGS_H_
|
||||
#define __PROJ_SETTINGS_H_
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
//--------DEFINES FOR SETTING OF SETTINGS-----------
|
||||
#define SETTINGS_FLASH_ADDRESS_SHIFT (0x10000)
|
||||
#define SETTINGS_FLASH_ADDRESS (FLASH_BASE + SETTINGS_FLASH_ADDRESS_SHIFT)
|
||||
|
||||
#define EEPROM_BASE
|
||||
#define SETTINGS_EEPROM_ADDRESS_SHIFT
|
||||
#define SETTINGS_EEPROM_ADDRESS (EEPROM_BASE + SETTINGS_EEPROM_ADDRESS_SHIFT)
|
||||
|
||||
#ifdef USE_EEPROM
|
||||
#define SETTINGS_ADDRESS SETTINGS_EEPROM_ADDRESS
|
||||
#else // USE_EEPROM
|
||||
#define SETTINGS_ADDRESS SETTINGS_FLASH_ADDRESS
|
||||
#endif // USE_EEPROM
|
||||
//--------------------------------------------------
|
||||
//------------DEFINES FOR PWM SETTING---------------
|
||||
// settings defines
|
||||
#define HZ_TIMER_CTRL 400
|
||||
#define HZ_TIMER_PWM 1000
|
||||
#define PWM_RAMP_SPEED 20
|
||||
|
||||
|
||||
// TIM PWM1 SETTINGS
|
||||
#define PWM_MASTER_TIM_NUMB 4
|
||||
#define TIMER_PWM_TICKBASE TIM_TickBase_1US
|
||||
#define TIMER_PWM_AHB_FREQ 84
|
||||
|
||||
#define TIMER_PWM1_INSTANCE TIM4
|
||||
#define TIMER_PWM1_TIM_CHANNEL1 TIM_CHANNEL_1
|
||||
#define TIMER_PWM1_TIM_CHANNEL2 TIM_CHANNEL_2
|
||||
#define TIMER_PWM1_GPIOx GPIOD
|
||||
#define TIMER_PWM1_GPIO_PIN_X1 GPIO_PIN_12
|
||||
#define TIMER_PWM1_GPIO_PIN_X2 GPIO_PIN_13
|
||||
|
||||
|
||||
|
||||
// TIM PWM2 SETTINGS
|
||||
#define TIMER_PWM2_INSTANCE TIM3
|
||||
#define TIMER_PWM2_TIM_CHANNEL1 TIM_CHANNEL_3
|
||||
#define TIMER_PWM2_TIM_CHANNEL2 TIM_CHANNEL_4
|
||||
#define TIMER_PWM2_GPIOx GPIOB
|
||||
#define TIMER_PWM2_GPIO_PIN_X1 GPIO_PIN_0
|
||||
#define TIMER_PWM2_GPIO_PIN_X2 GPIO_PIN_1
|
||||
|
||||
|
||||
|
||||
// TIM PWM3 SETTINGS
|
||||
#define TIMER_PWM3_INSTANCE TIM1
|
||||
#define TIMER_PWM3_TIM_CHANNEL1 TIM_CHANNEL_1
|
||||
#define TIMER_PWM3_TIM_CHANNEL2 TIM_CHANNEL_2
|
||||
#define TIMER_PWM3_GPIOx GPIOE
|
||||
#define TIMER_PWM3_GPIO_PIN_X1 GPIO_PIN_9
|
||||
#define TIMER_PWM3_GPIO_PIN_X2 GPIO_PIN_11
|
||||
|
||||
// TIM CTRL SETTINGS
|
||||
#define TIMER_CTRL_INSTANCE TIM13
|
||||
#define TIMER_CTRL_TICKBASE TIM_TickBase_1US
|
||||
#define TIMER_CTRL_AHB_FREQ 84
|
||||
|
||||
// TIM ENCODER SETTINGS
|
||||
#define TIMER_ENCODER_INSTANCE TIM5
|
||||
#define TIMER_ENCODER_TICKBASE (TIM_TickBase_1US)
|
||||
#define TIMER_ENCODER_AHB_FREQ 84
|
||||
#define TIMER_ENCODER_PORT GPIOA
|
||||
#define TIMER_ENCODER_PIN1 GPIO_PIN_0
|
||||
#define TIMER_ENCODER_PIN2 GPIO_PIN_1
|
||||
#define TIMER_ENCODER_PIN_SW GPIO_PIN_2
|
||||
|
||||
// PWM SETTINGS
|
||||
#define SIN_TABLE_ORIGIN sin_table
|
||||
#define SIN_TABLE_SIZE_MAX 1000
|
||||
//--------------------------------------------------
|
||||
|
||||
//----------DEFINES FOR MODBUS SETTING--------------
|
||||
#define MODBUS_UART_NUMB 3 // number of used uart
|
||||
#define MODBUS_SPEED 115200
|
||||
#define MODBUS_GPIOX GPIOB
|
||||
#define MODBUS_GPIO_PIN_RX GPIO_PIN_11
|
||||
#define MODBUS_GPIO_PIN_TX GPIO_PIN_10
|
||||
/* accord to this define sets define USED_MB_UART = USARTx */
|
||||
#define MODBUS_TIM_NUMB 7 // number of used uart
|
||||
#define MODBUS_TIM_AHB_FREQ 84
|
||||
/* accord to this define sets define USED_MB_TIM = TIMx */
|
||||
|
||||
/* defines for modbus behaviour */
|
||||
#define MODBUS_DEVICE_ID 1 // number of used uart
|
||||
#define MODBUS_MAX_TIMEOUT 5000 // is ms
|
||||
// custom define for size of receive message
|
||||
//--------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// ctrl periph settings
|
||||
uint32_t TIM_CTRL_TICKBASE;
|
||||
uint32_t TIM_CTRL_AHB_FREQ;
|
||||
// pwm peripth settings
|
||||
uint32_t TIM_PWM_TICKBASE;
|
||||
uint32_t TIM_PWM_AHB_FREQ;
|
||||
|
||||
// uint32_t TIM_PWM1_INSTANCE;
|
||||
uint32_t TIM_PWM1_TIM_CHANNEL1;
|
||||
uint32_t TIM_PWM1_TIM_CHANNEL2;
|
||||
uint32_t TIM_PWM1_GPIOx;
|
||||
uint32_t TIM_PWM1_GPIO_PIN_X1;
|
||||
uint32_t TIM_PWM1_GPIO_PIN_X2;
|
||||
|
||||
uint32_t TIM_PWM2_INSTANCE;
|
||||
uint32_t TIM_PWM2_TIM_CHANNEL1;
|
||||
uint32_t TIM_PWM2_TIM_CHANNEL2;
|
||||
uint32_t TIM_PWM2_GPIOx;
|
||||
uint32_t TIM_PWM2_GPIO_PIN_X1;
|
||||
uint32_t TIM_PWM2_GPIO_PIN_X2;
|
||||
|
||||
uint32_t TIM_PWM3_INSTANCE;
|
||||
uint32_t TIM_PWM3_TIM_CHANNEL1;
|
||||
uint32_t TIM_PWM3_TIM_CHANNEL2;
|
||||
uint32_t TIM_PWM3_GPIOx;
|
||||
uint32_t TIM_PWM3_GPIO_PIN_X1;
|
||||
uint32_t TIM_PWM3_GPIO_PIN_X2;
|
||||
|
||||
|
||||
// modbus peripth settings
|
||||
uint32_t MB_DEVICE_ID;
|
||||
uint32_t MB_SPEED;
|
||||
uint32_t MB_GPIOX;
|
||||
uint32_t MB_GPIO_PIN_RX;
|
||||
uint32_t MB_GPIO_PIN_TX;
|
||||
uint32_t MB_MAX_TIMEOUT;
|
||||
uint32_t MB_TIM_AHB_FREQ;
|
||||
|
||||
// uint32_t MB_UART_NUMB;
|
||||
// uint32_t MB_TIM_NUMB;
|
||||
}ProjectSettings_TypeDef;
|
||||
extern ProjectSettings_TypeDef PROJSET;
|
||||
|
||||
#define PROJSET_MEM ((ProjectSettings_TypeDef *)SETTINGS_ADDRESS)
|
||||
|
||||
|
||||
//#define HAL_FLASH_GET_TYPEPROGRAM(_val_) (sizeof(PROJSET_MEM->MB_DEVICE_ID)/2 - 1)
|
||||
#define HAL_FLASH_GET_TYPEPROGRAM(_val_) FLASH_TYPEPROGRAM_WORD
|
||||
#define FLASH_WRITE_SETTING(_setting_, _val_) HAL_FLASH_Program(HAL_FLASH_GET_TYPEPROGRAM(_setting_), (uint32_t)(&_setting_), (uint32_t)_val_);
|
||||
#define STRUCT_WRITE_SETTING(_setting_, _val_) (_setting_ = _val_)
|
||||
|
||||
|
||||
void FillStructWithDefines(void);
|
||||
void SetFlagUpdateSettingsInMem(void);
|
||||
void UpdateSettingsInMem(void);
|
||||
void WriteSettingsToMem(void);
|
||||
void FillSettingsWithDefines(void);
|
||||
void CheckSettingsInFLASH(void);
|
||||
int CheckIsSettingsValid(ProjectSettings_TypeDef* set_struct);
|
||||
|
||||
#endif // __PROJ_SETTINGS_H_
|
||||
Reference in New Issue
Block a user