Loading...
Searching...
No Matches
stm32f4xx_matlab_tim.c
Go to the documentation of this file.
/**
**************************************************************************
* @file stm32f4xx_matlab_tim.c
* @brief Исходный код симулятора таймеров.
**************************************************************************
@details
Данный файл содержит функции для симуляции таймеров STM32F407xx.
**************************************************************************/
#include "stm32f4xx_matlab_tim.h"
struct SlaveChannels Slave_Channels; ///< структура для связи и синхронизации таймеров
//----------------------TIMER BASE FUNCTIONS-----------------------//
/**
* @brief Симуляция таймера на один такт симуляции.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Это базовая функция для симуляции таймера: она вызывается каждый шаг симуляции
* и вызывает все другие функции, необходимые для симуляции:
* - Overflow_Check()
* - Slave_Mode_Check_Source()
* - TIMx_Count()
* - Channels_Simulation()
*/
void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{
Overflow_Check(TIMx, TIMS);
// Выбор режима работы таймера
switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE
{
// обычный счет
case(TIM_SLAVEMODE_DISABLE):// NORMAL MODE counting
TIMx_Count(TIMx, TIMS);
Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
break;
// включение слейв таймера по ивенту
case(TIM_SLAVEMODE_TRIGGER): // SLAVE MODE: TRIGGER MODE
Slave_Mode_Check_Source(TIMx, TIMS);
TIMx_Count(TIMx, TIMS);
Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
break;
}
}
/**
* @brief Симуляция счетчика таймера на один такт симуляции.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция проверяет направление таймера и увеличивает или уменьшает
* значение счетчика на то число, на которое оно бы увеличилось за шаг симуляции.
* @note Для счетчика используется double формат, т.к. кол-во счетов за шаг симуляции
может быть дробным. После в конце функции double счетчик записывает с округлением
в регистр таймера CNT.
*/
void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
if ((TIMx->CR1 & TIM_CR1_DIR) && TIMx->CR1) // up COUNTER and COUNTER ENABLE
TIMS->tx_cnt -= TIMS->tx_step / TIMx->PSC;
else if (((TIMx->CR1 & TIM_CR1_DIR) == 0) && TIMx->CR1) // down COUNTER and COUNTER ENABLE
TIMS->tx_cnt += TIMS->tx_step / TIMx->PSC;
TIMx->CNT = (uint32_t)TIMS->tx_cnt;
}
/**
* @brief Проверка на переполнение и дальнейшая его обработка.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция проверяет когда таймер переполниться и если надо,
вызывает соответствующее прерывание:
- call_IRQHandller()
*/
void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
// Переполнение таймера: сброс таймера и вызов прерывания
if ((TIMx->CR1 & TIM_CR1_UDIS) == 0) // UPDATE enable
{
if ((TIMx->CR1 & TIM_CR1_ARPE) == 0) TIMS->RELOAD = TIMx->ARR; // PRELOAD disable - update ARR every itteration
if (TIMS->tx_cnt > TIMS->RELOAD || TIMS->tx_cnt < 0) // OVERFLOW
{
TIMS->RELOAD = TIMx->ARR; // RELOAD ARR
if (TIMS->tx_cnt > TIMx->ARR) // reset COUNTER
TIMS->tx_cnt = 0;
else if (TIMS->tx_cnt < 0)
TIMS->tx_cnt = TIMx->ARR;
if(TIMx->DIER & TIM_DIER_UIE) // if update interrupt enable
call_IRQHandller(TIMx); // call HANDLER
}
}
}
//-----------------------------------------------------------------//
//----------------------------CHANNELS-----------------------------//
/**
* @brief Симуляция каналов таймера.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция симулирует работу всех каналов таймера.
* Она вызывает функции:
* - CC_PWM_Ch1_Simulation()
* - CC_PWM_Ch2_Simulation()
* - CC_PWM_Ch3_Simulation()
* - CC_PWM_Ch4_Simulation()
* - Write_OC_to_GPIO()
* - Write_OC_to_TRGO()
*/
void Channels_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
CC_PWM_Ch1_Simulation(TIMx, TIMS);
CC_PWM_Ch2_Simulation(TIMx, TIMS);
CC_PWM_Ch3_Simulation(TIMx, TIMS);
CC_PWM_Ch4_Simulation(TIMx, TIMS);
Write_OC_to_GPIO(TIMx, TIMS);
Write_OC_to_TRGO(TIMx, TIMS);
}
//-----------------CAPTURE COPMARE & PWM FUNCTIONS------------------//
/**
* @brief Выбор режима первого канала и его симуляция.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция по регистрам таймера проверяет как настроен
первый канал и соответствующе симулирует его работу.
*/
void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR1 & TIM_CCMR1_OC1M)
{
case (TIM_OCMODE_ACTIVE): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
TIMS->Channels.OC1REF = 1;
break;
case (TIM_OCMODE_INACTIVE): // INACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
TIMS->Channels.OC1REF = 0;
break;
case (TIM_OCMODE_TOGGLE): // TOOGLE mode
if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step)
TIMS->Channels.OC1REF = ~TIMS->Channels.OC1REF;
break;
case (TIM_OCMODE_PWM1): // PWM MODE 1 mode
if (TIMx->CNT < TIMx->CCR1)
TIMS->Channels.OC1REF = 1;
else
TIMS->Channels.OC1REF = 0;
break;
case (TIM_OCMODE_PWM2): // PWM MODE 2 mode
if (TIMx->CNT < TIMx->CCR1)
TIMS->Channels.OC1REF = 0;
else
TIMS->Channels.OC1REF = 1;
break;
case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode
TIMS->Channels.OC1REF = 1; break;
case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode
TIMS->Channels.OC1REF = 0; break;
}
}
/**
* @brief Выбор режима второго канала и его симуляция.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция по регистрам таймера проверяет как настроен
второй канал и соответствующе симулирует его работу.
*/
void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR1 & TIM_CCMR1_OC2M)
{
case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
TIMS->Channels.OC2REF = 1;
break;
case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
TIMS->Channels.OC2REF = 0;
break;
case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode
if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step)
TIMS->Channels.OC2REF = ~TIMS->Channels.OC2REF;
break;
case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode
if (TIMx->CNT < TIMx->CCR2)
TIMS->Channels.OC2REF = 1;
else
TIMS->Channels.OC2REF = 0;
break;
case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode
if (TIMx->CNT < TIMx->CCR2)
TIMS->Channels.OC2REF = 0;
else
TIMS->Channels.OC2REF = 1;
break;
case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode
TIMS->Channels.OC2REF = 1; break;
case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode
TIMS->Channels.OC2REF = 0; break;
}
}
/**
* @brief Выбор режима третьего канала и его симуляция.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция по регистрам таймера проверяет как настроен
третий канал и соответствующе симулирует его работу.
*/
void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR2 & TIM_CCMR1_OC1M)
{
case (TIM_OCMODE_ACTIVE): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
TIMS->Channels.OC3REF = 1;
break;
case (TIM_OCMODE_INACTIVE): // INACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
TIMS->Channels.OC3REF = 0;
break;
case (TIM_OCMODE_TOGGLE): // Toogle mode
if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
TIMS->Channels.OC3REF = ~TIMS->Channels.OC3REF;
break;
case (TIM_OCMODE_PWM1): // PWM mode 1 mode
if (TIMx->CNT < TIMx->CCR3)
TIMS->Channels.OC3REF = 1;
else
TIMS->Channels.OC3REF = 0;
break;
case (TIM_OCMODE_PWM2): // PWM mode 2 mode
if (TIMx->CNT < TIMx->CCR3)
TIMS->Channels.OC3REF = 0;
else
TIMS->Channels.OC3REF = 1;
break;
case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode
TIMS->Channels.OC3REF = 1; break;
case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode
TIMS->Channels.OC3REF = 0; break;
}
}
/**
* @brief Выбор режима четвертого канала и его симуляция.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура таймера для симуляции.
* @details Данная функция по регистрам таймера проверяет как настроен
четвертый канал и соответствующе симулирует его работу.
*/
void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR2 & TIM_CCMR1_OC2M)
{
case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
TIMS->Channels.OC4REF = 1;
break;
case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
TIMS->Channels.OC4REF = 0;
break;
case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode
if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
TIMS->Channels.OC4REF = ~TIMS->Channels.OC4REF;
break;
case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode
if (TIMx->CNT < TIMx->CCR4)
TIMS->Channels.OC4REF = 1;
else
TIMS->Channels.OC4REF = 0;
break;
case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode
if (TIMx->CNT < TIMx->CCR4)
TIMS->Channels.OC4REF = 0;
else
TIMS->Channels.OC4REF = 1;
break;
case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode
TIMS->Channels.OC4REF = 1; break;
case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode
TIMS->Channels.OC4REF = 0; break;
}
}
/**
* @brief Запись каналов таймера в порты GPIO.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура того же таймера для симуляции.
* @details Данная функция записывает каналы OC в порты GPIO, определенные в TIMS.
* Запись происходит только если пин настроен на альтернативную функцию.
*/
void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{
// write gpio pin if need
if (Check_OC1_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
{
uint32_t temp2 = ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
if (TIMx->CCER & TIM_CCER_CC1P) // POLARITY check
{ // low POLARITY
if (TIMS->Channels.OC1REF)
TIMS->Channels.OC1_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
else
TIMS->Channels.OC1_GPIOx->ODR |= 1 << (TIMS->Channels.OC1_PIN_SHIFT);
}
else
{ // high POLARITY
if (TIMS->Channels.OC1REF)
TIMS->Channels.OC1_GPIOx->ODR |= 1 << (TIMS->Channels.OC1_PIN_SHIFT);
else
TIMS->Channels.OC1_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC1_PIN_SHIFT));
}
}
if (Check_OC2_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
{
if (TIMx->CCER & TIM_CCER_CC2P) // POLARITY check
{ // low POLARITY
if (TIMS->Channels.OC2REF)
TIMS->Channels.OC2_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC2_PIN_SHIFT));
else
TIMS->Channels.OC2_GPIOx->ODR |= 1 << (TIMS->Channels.OC2_PIN_SHIFT);
}
else
{ // high POLARITY
if (TIMS->Channels.OC2REF)
TIMS->Channels.OC2_GPIOx->ODR |= 1 << (TIMS->Channels.OC2_PIN_SHIFT);
else
TIMS->Channels.OC2_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC2_PIN_SHIFT));
}
}
if (Check_OC3_GPIO_Output(TIMS)) // check OC OUTPUT 4 enable (GPIO AF MODE)
{
if (TIMx->CCER & TIM_CCER_CC3P) // POLARITY check
{ // low POLARITY
if (TIMS->Channels.OC3REF)
TIMS->Channels.OC3_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC3_PIN_SHIFT));
else
TIMS->Channels.OC3_GPIOx->ODR |= 1 << (TIMS->Channels.OC3_PIN_SHIFT);
}
else
{ // high POLARITY
if (TIMS->Channels.OC3REF)
TIMS->Channels.OC3_GPIOx->ODR |= 1 << (TIMS->Channels.OC3_PIN_SHIFT);
else
TIMS->Channels.OC3_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC3_PIN_SHIFT));
}
}
if (Check_OC4_GPIO_Output(TIMS)) // check OC CHANNEL 4 enable (GPIO AF MODE)
{
if (TIMx->CCER & TIM_CCER_CC4P) // POLARITY check
{ // low POLARITY
if (TIMS->Channels.OC4REF)
TIMS->Channels.OC4_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC4_PIN_SHIFT));
else
TIMS->Channels.OC4_GPIOx->ODR |= (1) << (TIMS->Channels.OC4_PIN_SHIFT);
}
else
{ // high POLARITY
if (TIMS->Channels.OC4REF)
TIMS->Channels.OC4_GPIOx->ODR |= (1) << (TIMS->Channels.OC4_PIN_SHIFT);
else
TIMS->Channels.OC4_GPIOx->ODR &= ~(uint32_t)(1 << (TIMS->Channels.OC4_PIN_SHIFT));
}
}
}
/** Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
/**
* @brief Запись каналов таймера в глабальную структуру с TRIGGER OUTPUT.
* @param TIMx – таймер, каналы которого надо записать.
* @param TIMS – структура того же таймера для симуляции.
* @details Данная функция считывает каналы OC и записывает их в внешний канал триггера TRGO.
*/
void Write_OC_to_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
// write trigger output from OCxREF pin if need
unsigned temp_trgo;
if ((TIMx->CR2 & TIM_CR2_MMS) == (0b100 << TIM_CR2_MMS_Pos))
{
temp_trgo = TIMS->Channels.OC1REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b101 << TIM_CR2_MMS_Pos))
{
temp_trgo = TIMS->Channels.OC2REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b110 << TIM_CR2_MMS_Pos))
{
temp_trgo = TIMS->Channels.OC3REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b111 << TIM_CR2_MMS_Pos))
{
temp_trgo = TIMS->Channels.OC4REF;
}
// select TIMx TRGO
if (TIMx == TIM1)
Slave_Channels.TIM1_TRGO = temp_trgo;
else if (TIMx == TIM2)
Slave_Channels.TIM2_TRGO = temp_trgo;
else if (TIMx == TIM3)
Slave_Channels.TIM3_TRGO = temp_trgo;
else if (TIMx == TIM4)
Slave_Channels.TIM4_TRGO = temp_trgo;
else if (TIMx == TIM5)
Slave_Channels.TIM5_TRGO = temp_trgo;
else if (TIMx == TIM6)
Slave_Channels.TIM6_TRGO = temp_trgo;
else if (TIMx == TIM7)
Slave_Channels.TIM7_TRGO = temp_trgo;
else if (TIMx == TIM8)
Slave_Channels.TIM8_TRGO = temp_trgo;
temp_trgo = 0;
}
//------------------------------------------------------------------//
//--------------------MISC (temporary) FUNCTIONS--------------------//
/** Определение источника для запуска таймера в SLAVE MODE */
/**
* @brief Определение источника для запуска таймера в SLAVE MODE.
* @param TIMx – таймер, который надо включить.
* @param TIMx – таймер, прерываний которого надо вызвать.
* @details Данная функция проверяет какой триггер выбран для запуска таймера,
* после записывает значение канала триггера в бит включения таймера.
* Таким образом, при лог.1 в канале триггера - таймер включиться.
*/
void Slave_Mode_Check_Source(TIM_TypeDef* TIMx)
{
if (TIMx == TIM2)
{
if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
TIMx->CR1 |= (Slave_Channels.TIM1_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
TIMx->CR1 |= (Slave_Channels.TIM8_TRGO << TIM_CR1_CEN_Pos);
}
else if (TIMx == TIM3)
{
if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
TIMx->CR1 |= (Slave_Channels.TIM8_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
TIMx->CR1 |= (Slave_Channels.TIM2_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
TIMx->CR1 |= (Slave_Channels.TIM2_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
}
else if (TIMx == TIM4)
{
if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
TIMx->CR1 |= (Slave_Channels.TIM5_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
TIMx->CR1 |= (Slave_Channels.TIM3_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
}
else if (TIMx == TIM5)
{
if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR0)
TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR1)
TIMx->CR1 |= (Slave_Channels.TIM4_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR2)
TIMx->CR1 |= (Slave_Channels.TIM7_TRGO << TIM_CR1_CEN_Pos);
else if ((TIMx->SMCR & TIM_SMCR_TS) == TIM_TS_ITR3)
TIMx->CR1 |= (Slave_Channels.TIM7_TRGO << TIM_CR1_CEN_Pos);
}
}
//------------------------------------------------------------------//
//------------------------SIMULINK FUNCTIONS------------------------//
/** Симулирование выбранных через дефайн таймеров */
/**
* @brief Симуляция выбранных таймеров.
* @details Таймеры для симуляции выбираются через дефайны в stm32f4xx_matlab_conf.h.
Функция вызывается на каждом шаге симуляции.
*/
void Simulate_TIMs(void)
{
#ifdef USE_TIM1
TIM_Simulation(TIM1, &tim1s);
#endif
#ifdef USE_TIM2
TIM_Simulation(TIM2, &tim2s);
#endif
#ifdef USE_TIM3
TIM_Simulation(TIM3, &tim3s);
#endif
#ifdef USE_TIM4
TIM_Simulation(TIM4, &tim4s);
#endif
#ifdef USE_TIM5
TIM_Simulation(TIM5, &tim5s);
#endif
#ifdef USE_TIM6
TIM_Simulation(TIM6, &tim6s);
#endif
#ifdef USE_TIM7
TIM_Simulation(TIM7, &tim7s);
#endif
#ifdef USE_TIM8
TIM_Simulation(TIM8, &tim8s);
#endif
#ifdef USE_TIM9
TIM_Simulation(TIM9, &tim9s);
#endif
#ifdef USE_TIM10
TIM_Simulation(TIM10, &tim10s);
#endif
#ifdef USE_TIM11
TIM_Simulation(TIM11, &tim11s);
#endif
#ifdef USE_TIM12
TIM_Simulation(TIM12, &tim12s);
#endif
#ifdef USE_TIM13
TIM_Simulation(TIM13, &tim13s);
#endif
#ifdef USE_TIM14
TIM_Simulation(TIM14, &tim14s);
#endif
}
/**
* @brief Деинициализирование выбранных таймеров.
* @details Таймеры для деинициализизации выбираются через дефайны в stm32f4xx_matlab_conf.h.
Функция вызывается в конце симуляции.
*/
void TIM_SIM_DEINIT(void)
{
#ifdef USE_TIM1
memset(&tim1s, 0, sizeof(tim1s));
#endif
#ifdef USE_TIM2
memset(&tim2s, 0, sizeof(tim2s));
#endif
#ifdef USE_TIM3
memset(&tim3s, 0, sizeof(tim3s));
#endif
#ifdef USE_TIM4
memset(&tim4s, 0, sizeof(tim4s));
#endif
#ifdef USE_TIM5
memset(&tim5s, 0, sizeof(tim5s));
#endif
#ifdef USE_TIM6
memset(&tim6s, 0, sizeof(tim6s));
#endif
#ifdef USE_TIM7
memset(&tim7s, 0, sizeof(tim7s));
#endif
#ifdef USE_TIM8
memset(&tim8s, 0, sizeof(tim8s));
#endif
#ifdef USE_TIM9
memset(&tim9s, 0, sizeof(tim9s));
#endif
#ifdef USE_TIM10
memset(&tim10s, 0, sizeof(tim10s));
#endif
#ifdef USE_TIM11
memset(&tim11s, 0, sizeof(tim11s));
#endif
#ifdef USE_TIM12
memset(&tim12s, 0, sizeof(tim12s));
#endif
#ifdef USE_TIM13
memset(&tim13s, 0, sizeof(tim13s));
#endif
#ifdef USE_TIM14
memset(&tim14s, 0, sizeof(tim14s));
#endif
}
//------------------------------------------------------------------//
//------------------TIM'S HANDLERS (BETA) FUNCTIONS-----------------//
// Определение обработчиков, которые не используются
// Т.к. в MSVC нет понятия weak function, необходимо объявить все колбеки
// И если какой-то колбек не используется, его надо определить
#ifndef USE_TIM1_UP_TIM10_HANDLER
void TIM1_UP_TIM10_IRQHandler(void) {}
#endif
#ifndef USE_TIM2_HANDLER
void TIM2_IRQHandler(void) {}
#endif
#ifndef USE_TIM3_HANDLER
void TIM3_IRQHandler(void) {}
#endif
#ifndef USE_TIM4_HANDLER
void TIM4_IRQHandler(void) {}
#endif
#ifndef USE_TIM5_HANDLER
void TIM5_IRQHandler(void) {}
#endif
#ifndef USE_TIM6_HANDLER
void TIM6_DAC_IRQHandler(void) {}
#endif
#ifndef USE_TIM7_HANDLER
void TIM7_IRQHandler(void) {}
#endif
#ifndef USE_TIM8_UP_TIM13_HANDLER
void TIM8_UP_TIM13_IRQHandler(void) {}
#endif
#ifndef USE_TIM1_BRK_TIM9_HANDLER
void TIM1_BRK_TIM9_IRQHandler(void) {}
#endif
#ifndef USE_TIM1_TRG_COM_TIM11_HANDLER
void TIM1_TRG_COM_TIM11_IRQHandler(void) {}
#endif
#ifndef USE_TIM8_BRK_TIM12_HANDLER
void TIM8_BRK_TIM12_IRQHandler(void) {}
#endif
#ifndef USE_TIM8_TRG_COM_TIM14_HANDLER
void TIM8_TRG_COM_TIM14_IRQHandler(void) {}
#endif
/**
* @brief Вызов прерывания таймера TIMx.
* @param TIMx – таймер, прерываний которого надо вызвать.
* @details Данная функция симулирует аппаратный вызов прерывания
таймера по какому-либо событию.
*/
void call_IRQHandller(TIM_TypeDef* TIMx)
{ // calling HANDLER
if ((TIMx == TIM1) || (TIMx == TIM10))
TIM1_UP_TIM10_IRQHandler();
else if (TIMx == TIM2)
TIM2_IRQHandler();
else if (TIMx == TIM3)
TIM3_IRQHandler();
else if (TIMx == TIM4)
TIM4_IRQHandler();
else if (TIMx == TIM5)
TIM5_IRQHandler();
else if (TIMx == TIM6)
TIM6_DAC_IRQHandler();
else if (TIMx == TIM7)
TIM7_IRQHandler();
else if ((TIMx == TIM8) || (TIMx == TIM13))
TIM8_UP_TIM13_IRQHandler();
else if ((TIMx == TIM1) || (TIMx == TIM9))
TIM1_BRK_TIM9_IRQHandler();
else if ((TIMx == TIM1) || (TIMx == TIM11))
TIM1_TRG_COM_TIM11_IRQHandler();
else if ((TIMx == TIM8) || (TIMx == TIM12))
TIM8_BRK_TIM12_IRQHandler();
else if ((TIMx == TIM8) || (TIMx == TIM14))
TIM8_TRG_COM_TIM14_IRQHandler();
}
//------------------------------------------------------------------//
Overflow_Check
void Overflow_Check(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Проверка на переполнение и дальнейшая его обработка.
Definition stm32f4xx_matlab_tim.c:80
Check_OC3_GPIO_Output
#define Check_OC3_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 3 на GPIO (настроен ли GPIO на альтернативную функцию)
Definition stm32f4xx_matlab_tim.h:46
Write_OC_to_GPIO
void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Запись каналов таймера в порты GPIO.
Definition stm32f4xx_matlab_tim.c:330
Simulate_TIMs
void Simulate_TIMs(void)
Симуляция выбранных таймеров.
Definition stm32f4xx_matlab_tim.c:521
TIM_Simulation
void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция таймера на один такт симуляции.
Definition stm32f4xx_matlab_tim.c:28
Write_OC_to_TRGO
void Write_OC_to_TRGO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Запись каналов таймера в глабальную структуру с TRIGGER OUTPUT.
Definition stm32f4xx_matlab_tim.c:410
TIM_SIM_DEINIT
void TIM_SIM_DEINIT(void)
Деинициализирование выбранных таймеров.
Definition stm32f4xx_matlab_tim.c:571
TIMx_Count
void TIMx_Count(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция счетчика таймера на один такт симуляции.
Definition stm32f4xx_matlab_tim.c:63
CC_PWM_Ch1_Simulation
void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима первого канала и его симуляция.
Definition stm32f4xx_matlab_tim.c:137
Slave_Mode_Check_Source
void Slave_Mode_Check_Source(TIM_TypeDef *TIMx)
Определение источника для запуска таймера в SLAVE MODE.
Definition stm32f4xx_matlab_tim.c:464
Channels_Simulation
void Channels_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Симуляция каналов таймера.
Definition stm32f4xx_matlab_tim.c:118
Check_OC1_GPIO_Output
#define Check_OC1_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 1 на GPIO (настроен ли GPIO на альтернативную функцию)
Definition stm32f4xx_matlab_tim.h:38
CC_PWM_Ch3_Simulation
void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима третьего канала и его симуляция.
Definition stm32f4xx_matlab_tim.c:233
call_IRQHandller
void call_IRQHandller(TIM_TypeDef *TIMx)
Вызов прерывания таймера TIMx.
Definition stm32f4xx_matlab_tim.c:665
Check_OC2_GPIO_Output
#define Check_OC2_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 2 на GPIO (настроен ли GPIO на альтернативную функцию)
Definition stm32f4xx_matlab_tim.h:42
CC_PWM_Ch4_Simulation
void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима четвертого канала и его симуляция.
Definition stm32f4xx_matlab_tim.c:281
Check_OC4_GPIO_Output
#define Check_OC4_GPIO_Output(_tims_)
Дефайн для проверки выводить ли канал 4 на GPIO (настроен ли GPIO на альтернативную функцию)
Definition stm32f4xx_matlab_tim.h:50
TIM_OCMODE_SECOND_SHIFT
#define TIM_OCMODE_SECOND_SHIFT
Дефайн для сдвига между первой и второй половиной CCMRx регистров
Definition stm32f4xx_matlab_tim.h:28
CC_PWM_Ch2_Simulation
void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
Выбор режима второго канала и его симуляция.
Definition stm32f4xx_matlab_tim.c:185
tim1s
struct TIM_Sim tim1s
tim4s
struct TIM_Sim tim4s
tim12s
struct TIM_Sim tim12s
tim3s
struct TIM_Sim tim3s
tim7s
struct TIM_Sim tim7s
TIM6_DAC_IRQHandler
void TIM6_DAC_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:638
TIM1_TRG_COM_TIM11_IRQHandler
void TIM1_TRG_COM_TIM11_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:650
TIM8_BRK_TIM12_IRQHandler
void TIM8_BRK_TIM12_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:653
TIM2_IRQHandler
void TIM2_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:626
TIM1_BRK_TIM9_IRQHandler
void TIM1_BRK_TIM9_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:647
TIM8_TRG_COM_TIM14_IRQHandler
void TIM8_TRG_COM_TIM14_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:656
TIM5_IRQHandler
void TIM5_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:635
Slave_Channels
struct SlaveChannels Slave_Channels
структура для связи и синхронизации таймеров
Definition stm32f4xx_matlab_tim.c:13
TIM4_IRQHandler
void TIM4_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:632
TIM8_UP_TIM13_IRQHandler
void TIM8_UP_TIM13_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:644
TIM7_IRQHandler
void TIM7_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:641
TIM3_IRQHandler
void TIM3_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:629
TIM1_UP_TIM10_IRQHandler
void TIM1_UP_TIM10_IRQHandler(void)
Definition stm32f4xx_matlab_tim.c:623
stm32f4xx_matlab_tim.h
Заголовочный файл для симулятора таймеров.
Channels_Sim::OC2_GPIOx
GPIO_TypeDef * OC2_GPIOx
Порт второго канала
Definition stm32f4xx_matlab_tim.h:88
Channels_Sim::OC4REF
unsigned OC4REF
Четвертый канал
Definition stm32f4xx_matlab_tim.h:82
Channels_Sim::OC1_PIN_SHIFT
uint32_t OC1_PIN_SHIFT
Пин первого канала
Definition stm32f4xx_matlab_tim.h:86
Channels_Sim::OC1_GPIOx
GPIO_TypeDef * OC1_GPIOx
Порт первого канала
Definition stm32f4xx_matlab_tim.h:85
Channels_Sim::OC3_GPIOx
GPIO_TypeDef * OC3_GPIOx
Порт третьего канала
Definition stm32f4xx_matlab_tim.h:91
Channels_Sim::OC4_GPIOx
GPIO_TypeDef * OC4_GPIOx
Порт четвертого канала
Definition stm32f4xx_matlab_tim.h:94
Channels_Sim::OC2REF
unsigned OC2REF
Второй канал
Definition stm32f4xx_matlab_tim.h:80
Channels_Sim::OC4_PIN_SHIFT
uint32_t OC4_PIN_SHIFT
Пин четвертого канала
Definition stm32f4xx_matlab_tim.h:95
Channels_Sim::OC1REF
unsigned OC1REF
Первый канал
Definition stm32f4xx_matlab_tim.h:79
Channels_Sim::OC3REF
unsigned OC3REF
Третьий канал
Definition stm32f4xx_matlab_tim.h:81
Channels_Sim::OC3_PIN_SHIFT
uint32_t OC3_PIN_SHIFT
Пин третьего канала
Definition stm32f4xx_matlab_tim.h:92
Channels_Sim::OC2_PIN_SHIFT
uint32_t OC2_PIN_SHIFT
Пин второго канала
Definition stm32f4xx_matlab_tim.h:89
SlaveChannels
Структура для управления Слейв Таймерами
Definition stm32f4xx_matlab_tim.h:61
SlaveChannels::TIM1_TRGO
unsigned TIM1_TRGO
Синган синхронизации таймера 1.
Definition stm32f4xx_matlab_tim.h:62
SlaveChannels::TIM6_TRGO
unsigned TIM6_TRGO
Синган синхронизации таймера 6.
Definition stm32f4xx_matlab_tim.h:67
SlaveChannels::TIM8_TRGO
unsigned TIM8_TRGO
Синган синхронизации таймера 8
Definition stm32f4xx_matlab_tim.h:69
SlaveChannels::TIM2_TRGO
unsigned TIM2_TRGO
Синган синхронизации таймера 2.
Definition stm32f4xx_matlab_tim.h:63
SlaveChannels::TIM7_TRGO
unsigned TIM7_TRGO
Синган синхронизации таймера 7.
Definition stm32f4xx_matlab_tim.h:68
SlaveChannels::TIM5_TRGO
unsigned TIM5_TRGO
Синган синхронизации таймера 5.
Definition stm32f4xx_matlab_tim.h:66
SlaveChannels::TIM3_TRGO
unsigned TIM3_TRGO
Синган синхронизации таймера 3.
Definition stm32f4xx_matlab_tim.h:64
SlaveChannels::TIM4_TRGO
unsigned TIM4_TRGO
Синган синхронизации таймера 4.
Definition stm32f4xx_matlab_tim.h:65
TIM_Sim
Структура для моделирования таймера
Definition stm32f4xx_matlab_tim.h:103
TIM_Sim::RELOAD
int RELOAD
Буфер для периода таймера (для реализации функции PRELOAD)
Definition stm32f4xx_matlab_tim.h:106
TIM_Sim::tx_cnt
double tx_cnt
Счетчик таймера (double, т.к. кол-во тактов за шаг симуляции может быть дробным)
Definition stm32f4xx_matlab_tim.h:104
TIM_Sim::Channels
struct Channels_Sim Channels
Структура для симуляции каналов
Definition stm32f4xx_matlab_tim.h:107
TIM_Sim::tx_step
double tx_step
Шаг счета за один шаг симуляции (double, т.к. кол-во тактов за шаг симуляции может быть дробным)
Definition stm32f4xx_matlab_tim.h:105