Сделана документация на то, что есть сейчас
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_matlab_gpio.c
|
||||
* @brief Исходный код симулятора портов.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит функции для симуляции портов STM32F407xx.
|
||||
**************************************************************************/
|
||||
#include "stm32f4xx_matlab_gpio.h"
|
||||
#include "modbus.h"
|
||||
|
||||
/**
|
||||
* @brief Запись буфера выходов S-Function из GPIO.
|
||||
* @param out_buff - указатель на буфер выходов S-Function.
|
||||
* @details Функция для записи буфера выходов S-Function из GPIO.
|
||||
После в @ref SIM_writeOutputs() из out_buff формируются выходы S-Function.
|
||||
|
||||
* @attention Тело функции пишется пользователем!
|
||||
*/
|
||||
void GPIO_to_SFUNC(real_T* out_buff)
|
||||
{
|
||||
for (int i = 0; i < PORT_WIDTH; i++)
|
||||
{
|
||||
if (GPIOB->ODR & (1 << i))
|
||||
{
|
||||
out_buff[i] = 1;
|
||||
}
|
||||
|
||||
if (GPIOD->ODR & (1 << i))
|
||||
{
|
||||
out_buff[PORT_WIDTH + i] = 1;
|
||||
}
|
||||
|
||||
if (GPIOE->ODR & (1 << i))
|
||||
{
|
||||
out_buff[2*PORT_WIDTH + i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Считывание входов S-Function в МК.
|
||||
* @param out_buff - указатель на буфер выходов S-Function.
|
||||
* @details Функция для считывания входов S-Function в МК.
|
||||
Можно абстрагироваться от считывания в GPIO и записывать напрямую в переменные МК.
|
||||
|
||||
* @attention Тело функции пишется пользователем!
|
||||
*/
|
||||
void SFUNC_to_GPIO(real_T* in)
|
||||
{
|
||||
// write pwm ctrl registers
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pwm_ctrl[i] = in[i];
|
||||
}
|
||||
// write pwm ctrl coils
|
||||
if (in[5] > 0.5)
|
||||
{
|
||||
MB_Set_Coil_Local(coils_regs, COIL_PWM_DC_MODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
MB_Reset_Coil_Local(coils_regs, COIL_PWM_DC_MODE);
|
||||
}
|
||||
if (in[6] > 0.5)
|
||||
{
|
||||
MB_Set_Coil_Local(coils_regs, COIL_PWM_CH_MODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
MB_Reset_Coil_Local(coils_regs, COIL_PWM_CH_MODE);
|
||||
}
|
||||
if (in[7] > 0.5)
|
||||
{
|
||||
MB_Set_Coil_Local(coils_regs, COIL_PWM_PHASE_MODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
MB_Reset_Coil_Local(coils_regs, COIL_PWM_PHASE_MODE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_matlab_gpio.h
|
||||
* @brief Заголовочный файл для симулятора портов.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит объявления всякого для симуляции портов STM32F407xx.
|
||||
**************************************************************************/
|
||||
#ifndef _MATLAB_GPIO_H_
|
||||
#define _MATLAB_GPIO_H_
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "simstruc.h"
|
||||
#include "mcu_wrapper_conf.h"
|
||||
|
||||
/**
|
||||
* @addtogroup GPIO_SIMULATOR GPIO Simulator
|
||||
* @ingroup MAIN_SIMULATOR
|
||||
* @brief Симулятор для портов ввода-вывода
|
||||
* @details Определяет взаимодействие портов МК и оболочки (S-Function)
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Функция для записи буфера выходов S-Function из GPIO */
|
||||
void SFUNC_to_GPIO(real_T* out_buff);
|
||||
/* Функция для считывания входов S-Function в МК */
|
||||
void GPIO_to_SFUNC(real_T* in);
|
||||
|
||||
/** GPIO_SIMULATOR
|
||||
* @}
|
||||
*/
|
||||
#endif // _MATLAB_GPIO_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_matlab_rcc.c
|
||||
* @brief Èñõîäíûé êîä ñèìóëÿòîðà êëîêà.
|
||||
**************************************************************************
|
||||
@details
|
||||
Äàííûé ôàéë ñîäåðæèò ôóíêöèè äëÿ ñèìóëÿöèè êëîêà STM32F407xx.
|
||||
**************************************************************************/
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_matlab_rcc.h
|
||||
* @brief Заголовочный файл для симулятора клока.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит объявления всякого для симуляции клока STM32F407xx.
|
||||
**************************************************************************/
|
||||
#ifndef _MATLAB_RCC_H_
|
||||
#define _MATLAB_RCC_H_
|
||||
|
||||
#include "mcu_wrapper_conf.h"
|
||||
|
||||
/**
|
||||
* @addtogroup RCC_SIMULATOR RCC Simulator
|
||||
* @ingroup MAIN_SIMULATOR
|
||||
* @brief Симулятор для RCC и часов таймера
|
||||
* @details Определ¤ет параметры тактирования МК.
|
||||
Содержит дефайны дл¤ скипа бесконечных циклов ожидающих выставление флагов
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
//#define SYSLCK_Value ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)
|
||||
//#define AHB_Prescaler ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)
|
||||
//#define AHB_Prescaler ((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)
|
||||
|
||||
#define HCLK_Value (double)72000000;
|
||||
#define ABP1_Value (double)72000000;
|
||||
#define ABP1_TIMS_Value (double)72000000;
|
||||
#define ABP2_Value (double)72000000;
|
||||
#define ABP2_TIMS_Value (double)72000000;
|
||||
|
||||
/* Эти дефайны добавлены в код stm32f4xx_hal_rcc.c, чтобы не попасть в бесконечный цикл */
|
||||
/* Мб перенести в MCU_Periph_Simulation(), но чет не хочется нагружать симуляцию этой херней */
|
||||
#define _RCC_SET_FLAG(__FLAG__) \
|
||||
if(((__FLAG__) >> 5U) == 1U) RCC->CR |= (1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else if(((__FLAG__) >> 5U) == 2U) RCC->BDCR |= (1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else if(((__FLAG__) >> 5U) == 3U) RCC->CSR |= (1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else RCC->CIR |= (1U << ((__FLAG__) & RCC_FLAG_MASK))
|
||||
|
||||
#define _RCC_CLEAR_FLAG(__FLAG__) \
|
||||
if(((__FLAG__) >> 5U) == 1U) RCC->CR &= ~(1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else if(((__FLAG__) >> 5U) == 2U) RCC->BDCR &= ~(1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else if(((__FLAG__) >> 5U) == 3U) RCC->CSR &= ~(1U << ((__FLAG__) & RCC_FLAG_MASK)); \
|
||||
else RCC->CIR &= ~(1U << ((__FLAG__) & RCC_FLAG_MASK))
|
||||
|
||||
#define Set_Flag_If_Its_Expected(_flag_, _condition_) \
|
||||
if(_condition_) _RCC_CLEAR_FLAG(_flag_)
|
||||
|
||||
#define Clear_Flag_If_Its_Expected(_flag_, _condition_) \
|
||||
if(_condition_) _RCC_SET_FLAG(_flag_)
|
||||
|
||||
/** RCC_SIMULATOR
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // _MATLAB_RCC_H_
|
||||
692
MCU_STM32F4xx_Matlab/STM32F4xx_SIMULINK/stm32f4xx_matlab_tim.c
Normal file
692
MCU_STM32F4xx_Matlab/STM32F4xx_SIMULINK/stm32f4xx_matlab_tim.c
Normal file
@@ -0,0 +1,692 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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();
|
||||
}
|
||||
//------------------------------------------------------------------//
|
||||
158
MCU_STM32F4xx_Matlab/STM32F4xx_SIMULINK/stm32f4xx_matlab_tim.h
Normal file
158
MCU_STM32F4xx_Matlab/STM32F4xx_SIMULINK/stm32f4xx_matlab_tim.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_matlab_tim.h
|
||||
* @brief Заголовочный файл для симулятора таймеров.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл содержит объявления всякого для симуляции таймеров STM32F407xx.
|
||||
**************************************************************************/
|
||||
#ifndef _MATLAB_TIM_H_
|
||||
#define _MATLAB_TIM_H_
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "stm32f4xx_it.h"
|
||||
#include "mcu_wrapper_conf.h"
|
||||
|
||||
/**
|
||||
* @addtogroup TIM_SIMULATOR TIM Simulator
|
||||
* @ingroup MAIN_SIMULATOR
|
||||
* @brief Симулятор для таймеров
|
||||
* @details Дефайны и функции для симуляции таймеров.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/////////////////////////////---DEFINES---/////////////////////////////
|
||||
/**
|
||||
* @brief Дефайн для сдвига между первой и второй половиной CCMRx регистров
|
||||
*/
|
||||
#define TIM_OCMODE_SECOND_SHIFT (TIM_CCMR1_OC2M_Pos - TIM_CCMR1_OC1M_Pos)
|
||||
|
||||
/**
|
||||
* @brief Дефайн для проверки выводить ли канал таймера на GPIO
|
||||
* @details Данный дефайн проверяет, настроен ли пин GPIO на альтернативную функцию. Если да - то таймер выводиться на этот пин
|
||||
*/
|
||||
#define Check_OCx_GPIO_Output(_tims_, _OCx_GPIOx_, _OCx_PIN_SHIFT_) (_tims_->Channels._OCx_GPIOx_->MODER & (0b11<<(2*_tims_->Channels._OCx_PIN_SHIFT_))) == (0b10<<(2*_tims_->Channels._OCx_PIN_SHIFT_))
|
||||
/**
|
||||
* @brief Дефайн для проверки выводить ли канал 1 на GPIO (настроен ли GPIO на альтернативную функцию)
|
||||
*/
|
||||
#define Check_OC1_GPIO_Output(_tims_) Check_OCx_GPIO_Output(_tims_, OC1_GPIOx, OC1_PIN_SHIFT)
|
||||
/**
|
||||
* @brief Дефайн для проверки выводить ли канал 2 на GPIO (настроен ли GPIO на альтернативную функцию)
|
||||
*/
|
||||
#define Check_OC2_GPIO_Output(_tims_) Check_OCx_GPIO_Output(_tims_, OC2_GPIOx, OC2_PIN_SHIFT)
|
||||
/**
|
||||
* @brief Дефайн для проверки выводить ли канал 3 на GPIO (настроен ли GPIO на альтернативную функцию)
|
||||
*/
|
||||
#define Check_OC3_GPIO_Output(_tims_) Check_OCx_GPIO_Output(_tims_, OC3_GPIOx, OC3_PIN_SHIFT)
|
||||
/**
|
||||
* @brief Дефайн для проверки выводить ли канал 4 на GPIO (настроен ли GPIO на альтернативную функцию)
|
||||
*/
|
||||
#define Check_OC4_GPIO_Output(_tims_) Check_OCx_GPIO_Output(_tims_, OC4_GPIOx, OC4_PIN_SHIFT)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////---STRUCTURES---//////////////////////////
|
||||
/**
|
||||
* @brief Структура для управления Слейв Таймерами
|
||||
*/
|
||||
struct SlaveChannels
|
||||
{
|
||||
unsigned TIM1_TRGO : 1; ///< Синган синхронизации таймера 1
|
||||
unsigned TIM2_TRGO : 1; ///< Синган синхронизации таймера 2
|
||||
unsigned TIM3_TRGO : 1; ///< Синган синхронизации таймера 3
|
||||
unsigned TIM4_TRGO : 1; ///< Синган синхронизации таймера 4
|
||||
unsigned TIM5_TRGO : 1; ///< Синган синхронизации таймера 5
|
||||
unsigned TIM6_TRGO : 1; ///< Синган синхронизации таймера 6
|
||||
unsigned TIM7_TRGO : 1; ///< Синган синхронизации таймера 7
|
||||
unsigned TIM8_TRGO : 1; ///< Синган синхронизации таймера 8
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Структура для моделирования каналов таймера
|
||||
*/
|
||||
struct Channels_Sim
|
||||
{
|
||||
// Каналы таймера
|
||||
unsigned OC1REF:1; ///< Первый канал
|
||||
unsigned OC2REF:1; ///< Второй канал
|
||||
unsigned OC3REF:1; ///< Третьий канал
|
||||
unsigned OC4REF:1; ///< Четвертый канал
|
||||
|
||||
// связанные с каналами GPIO порты и пины
|
||||
GPIO_TypeDef *OC1_GPIOx; ///< Порт первого канала
|
||||
uint32_t OC1_PIN_SHIFT; ///< Пин первого канала
|
||||
|
||||
GPIO_TypeDef *OC2_GPIOx; ///< Порт второго канала
|
||||
uint32_t OC2_PIN_SHIFT; ///< Пин второго канала
|
||||
|
||||
GPIO_TypeDef *OC3_GPIOx; ///< Порт третьего канала
|
||||
uint32_t OC3_PIN_SHIFT; ///< Пин третьего канала
|
||||
|
||||
GPIO_TypeDef *OC4_GPIOx; ///< Порт четвертого канала
|
||||
uint32_t OC4_PIN_SHIFT; ///< Пин четвертого канала
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Структура для моделирования таймера
|
||||
*/
|
||||
struct TIM_Sim
|
||||
{
|
||||
double tx_cnt; ///< Счетчик таймера (double, т.к. кол-во тактов за шаг симуляции может быть дробным)
|
||||
double tx_step; ///< Шаг счета за один шаг симуляции (double, т.к. кол-во тактов за шаг симуляции может быть дробным)
|
||||
int RELOAD; ///< Буфер для периода таймера (для реализации функции PRELOAD)
|
||||
struct Channels_Sim Channels; ///< Структура для симуляции каналов
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||
|
||||
//----------------------TIMER BASE FUNCTIONS-----------------------//
|
||||
/* Базовая функция для симуляции таймера: она вызывается каждый шаг симуляции */
|
||||
void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS);
|
||||
/* Счет таймера за один такт */
|
||||
void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
/* Проверка на переполнение и дальнейшая его обработка */
|
||||
void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
/* Вызов прерывания */
|
||||
void call_IRQHandller(TIM_TypeDef *TIMx);
|
||||
//-----------------------------------------------------------------//
|
||||
|
||||
|
||||
//------------------------CHANNELS FUNCTIONS-----------------------//
|
||||
/* Симуляция каналов таймера */
|
||||
void Channels_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS);
|
||||
/*---------------- - CAPTURE COPMARE & PWM FUNCTIONS------------------*/
|
||||
/* Выбор режима CaptureCompare или PWM и симуляция для каждого канала */
|
||||
void CC_PWM_Ch1_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
void CC_PWM_Ch2_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
void CC_PWM_Ch3_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
void CC_PWM_Ch4_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
/* Запись каналов таймера в порты GPIO */
|
||||
void Write_OC_to_GPIO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
/* Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
|
||||
void Write_OC_to_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
|
||||
//------------------------------------------------------------------//
|
||||
|
||||
|
||||
//--------------------MISC (temporary) FUNCTIONS--------------------//
|
||||
/* Определение источника для запуска таймера в SLAVE MODE */
|
||||
void Slave_Mode_Check_Source(TIM_TypeDef* TIMx);
|
||||
//------------------------------------------------------------------//
|
||||
|
||||
|
||||
//------------------------SIMULINK FUNCTIONS------------------------//
|
||||
// Симулирование выбранных таймеров
|
||||
void Simulate_TIMs(void);
|
||||
// Деинициализирование выбранных таймеров (вызывается в конце симуляции)
|
||||
void TIM_SIM_DEINIT(void);
|
||||
//------------------------------------------------------------------//
|
||||
/** TIM_SIMULATOR
|
||||
* @}
|
||||
*/
|
||||
#endif // _MATLAB_TIM_H_
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @dir ../MCU_STM32F4xx_Matlab/STM32F4xx_SIMULINK
|
||||
* @brief <b>
|
||||
* Папка с исходным кодом симулятора МК. </b>
|
||||
* @details
|
||||
В этой папке содержаться файлы для эмуляции периферии STM32 в MATLAB.
|
||||
Структура файлов такая же, как в библиотеке HAL:
|
||||
- название серии МК, который эмулируется (stm32f4xx),
|
||||
- идентификатор, что это для MATLAB (matlab),
|
||||
- периферия, функции для эмуляции которой содержит конкретный файл (gpio, tim).
|
||||
|
||||
Пример: "stm32f4xx_matlab_tim.c/.h"
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file stm32f4xx_periph_registers.c
|
||||
* @brief Исходный код с переменными регистров периферии.
|
||||
**************************************************************************
|
||||
@details
|
||||
Данный файл необходим для объявления структур для отображения их в watch
|
||||
В оригинальном stm32f407xx они объявлены дефайнами, которые не видны в watch.
|
||||
Поэтому дополнительно объявлены данные структуры.
|
||||
|
||||
Называются также, как CMSISные, только в нижнем регистре.
|
||||
**************************************************************************/
|
||||
#include "stm32f407xx_matlab.h"
|
||||
|
||||
/**
|
||||
* @addtogroup PERIPH_VARS_FOR_DEBUG Periphs Variables for Debugging
|
||||
* @ingroup STM_SIMULATION
|
||||
* @brief Переменные для доступа к периферии в дебаге
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
TIM_TypeDef* tim2 = TIM2;
|
||||
TIM_TypeDef* tim3 = TIM3;
|
||||
TIM_TypeDef* tim4 = TIM4;
|
||||
TIM_TypeDef* tim5 = TIM5;
|
||||
TIM_TypeDef* tim6 = TIM6;
|
||||
TIM_TypeDef* tim7 = TIM7;
|
||||
TIM_TypeDef* tim12 = TIM12;
|
||||
TIM_TypeDef* tim13 = TIM13;
|
||||
TIM_TypeDef* tim14 = TIM14;
|
||||
RTC_TypeDef* rtc = RTC;
|
||||
WWDG_TypeDef* wwdg = WWDG;
|
||||
IWDG_TypeDef* iwdg = IWDG;
|
||||
SPI_TypeDef* i2s2ext = I2S2ext;
|
||||
SPI_TypeDef* spi2 = SPI2;
|
||||
SPI_TypeDef* spi3 = SPI3;
|
||||
SPI_TypeDef* i2s3ext = I2S3ext;
|
||||
USART_TypeDef* usart2 = USART2;
|
||||
USART_TypeDef* usart3 = USART3;
|
||||
USART_TypeDef* uart4 = UART4;
|
||||
USART_TypeDef* uart5 = UART5;
|
||||
I2C_TypeDef* i2c1 = I2C1;
|
||||
I2C_TypeDef* i2c2 = I2C2;
|
||||
I2C_TypeDef* i2c3 = I2C3;
|
||||
CAN_TypeDef* can1 = CAN1;
|
||||
CAN_TypeDef* can2 = CAN2;
|
||||
PWR_TypeDef* pwr = PWR;
|
||||
DAC_TypeDef* dac1 = DAC1;
|
||||
DAC_TypeDef* dac = DAC; /* Kept for legacy purpose = DAC */
|
||||
TIM_TypeDef* tim1 = TIM1;
|
||||
TIM_TypeDef* tim8 = TIM8;
|
||||
USART_TypeDef* usart1 = USART1;
|
||||
USART_TypeDef* usart6 = USART6;
|
||||
ADC_TypeDef* adc1 = ADC1;
|
||||
ADC_TypeDef* adc2 = ADC2;
|
||||
ADC_TypeDef* adc3 = ADC3;
|
||||
ADC_Common_TypeDef* adc123_common = ADC123_COMMON; /* Legacy define */
|
||||
ADC_Common_TypeDef* adc = ADC123_COMMON;
|
||||
SDIO_TypeDef* sdio = SDIO;
|
||||
SPI_TypeDef* spi1 = SPI1;
|
||||
SYSCFG_TypeDef* syscfg = SYSCFG;
|
||||
EXTI_TypeDef* exti = EXTI;
|
||||
TIM_TypeDef* tim9 = TIM9;
|
||||
TIM_TypeDef* tim10 = TIM10;
|
||||
TIM_TypeDef* tim11 = TIM11;
|
||||
GPIO_TypeDef* gpioa = GPIOA;
|
||||
GPIO_TypeDef* gpiob = GPIOB;
|
||||
GPIO_TypeDef* gpioc = GPIOC;
|
||||
GPIO_TypeDef* gpiod = GPIOD;
|
||||
GPIO_TypeDef* gpioe = GPIOE;
|
||||
GPIO_TypeDef* gpiof = GPIOF;
|
||||
GPIO_TypeDef* gpiog = GPIOG;
|
||||
GPIO_TypeDef* gpioh = GPIOH;
|
||||
GPIO_TypeDef* gpioi = GPIOI;
|
||||
CRC_TypeDef* crc = CRC;
|
||||
RCC_TypeDef* rcc = RCC;
|
||||
FLASH_TypeDef* flash_r = FLASH;
|
||||
DMA_TypeDef* dma1 = DMA1;
|
||||
DMA_Stream_TypeDef* dma1_stream0 = DMA1_Stream0;
|
||||
DMA_Stream_TypeDef* dma1_stream1 = DMA1_Stream1;
|
||||
DMA_Stream_TypeDef* dma1_stream2 = DMA1_Stream2;
|
||||
DMA_Stream_TypeDef* dma1_stream3 = DMA1_Stream3;
|
||||
DMA_Stream_TypeDef* dma1_stream4 = DMA1_Stream4;
|
||||
DMA_Stream_TypeDef* dma1_stream5 = DMA1_Stream5;
|
||||
DMA_Stream_TypeDef* dma1_stream6 = DMA1_Stream6;
|
||||
DMA_Stream_TypeDef* dma1_stream7 = DMA1_Stream7;
|
||||
DMA_TypeDef* dma2 = DMA2;
|
||||
DMA_Stream_TypeDef* dma2_stream0 = DMA2_Stream0;
|
||||
DMA_Stream_TypeDef* dma2_stream1 = DMA2_Stream1;
|
||||
DMA_Stream_TypeDef* dma2_stream2 = DMA2_Stream2;
|
||||
DMA_Stream_TypeDef* dma2_stream3 = DMA2_Stream3;
|
||||
DMA_Stream_TypeDef* dma2_stream4 = DMA2_Stream4;
|
||||
DMA_Stream_TypeDef* dma2_stream5 = DMA2_Stream5;
|
||||
DMA_Stream_TypeDef* dma2_stream6 = DMA2_Stream6;
|
||||
DMA_Stream_TypeDef* dma2_stream7 = DMA2_Stream7;
|
||||
ETH_TypeDef* eth = ETH;
|
||||
DCMI_TypeDef* dcmi = DCMI;
|
||||
RNG_TypeDef* rng = RNG;
|
||||
FSMC_Bank1_TypeDef* fsmc_bank1_r = FSMC_Bank1;
|
||||
FSMC_Bank1E_TypeDef* fsmc_bank1e_r = FSMC_Bank1E;
|
||||
FSMC_Bank2_3_TypeDef* fsmc_bank2_3_r = FSMC_Bank2_3;
|
||||
FSMC_Bank4_TypeDef* fsmc_bank4_r = FSMC_Bank4;
|
||||
DBGMCU_TypeDef* dbgmcu = DBGMCU;
|
||||
USB_OTG_GlobalTypeDef* usb_otg_fs_periph = USB_OTG_FS;
|
||||
USB_OTG_GlobalTypeDef* usb_otg_hs_periph = USB_OTG_HS;
|
||||
|
||||
|
||||
/** PERIPH_VARS_FOR_DEBUG
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user