Changing CRR for three channels in TIM1 everytime ARR is reached?
Hello!
I have never before worked with a microcontroller so all of this is very new to me. I am using the MC-kit IHM07M1 with the NUCLEO-F302R8 as a control board. I am trying to implement chaotic PWM in the microcontroller like in the figure attached. The sawtooth pulse is, as seen in the figure, an upcounting timer.
The ARR needs to be constant and the CCRx values of each channel are going to vary chaoticly. My problem is that no matter what I do I simply can't implement this in my code. I am starting with a project in MotorControl Workbench (just a default Bull-Running-Program), and from there I generete my code. This is how I set up the workflow for my code:
- Timer 1 and all the PWM-channels are already initiated in the Bull Running Program. The only thing I change here is the initial ARR and CRRx.
- Interrupt Handler Function calculates the new CCRx value and assign it to channel 1-3.
This is my main()-function:
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_DAC_Init();
MX_TIM1_Init();
MX_USART2_UART_Init();
MX_MotorControl_Init();
/* Initialize interrupts */
MX_NVIC_Init();
while (1)
{
}
}The MX_NVIC_INIT(void)-function:
static void MX_NVIC_Init(void)
{
/* TIM1_BRK_TIM15_IRQn interrupt configuration */
HAL_NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 4, 1);
HAL_NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);
/* TIM1_UP_TIM16_IRQn interrupt configuration */
HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
/* ADC1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(ADC1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(ADC1_IRQn);
/* USART2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART2_IRQn, 3, 1);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* EXTI15_10_IRQn interrupt configuration */
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
/* Capture Compare interrupt for TIM1 */
HAL_NVIC_SetPriority(TIM1_CC_IRQn, 4, 1);
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
}The MX_TIM1_Init(void)-function:
static void MX_TIM1_Init(void)
{
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = ((TIM_CLOCK_DIVIDER) - 1);
htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
htim1.Init.Period = 2399;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;
htim1.Init.RepetitionCounter = (REP_COUNTER);
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR1;
if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1199;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM2;
sConfigOC.Pulse = (2399 - (HTMIN));
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_ENABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_LOW;
sBreakDeadTimeConfig.Break2Filter = 7;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim1);
}An at last the Interrupt Handler
void TIM1_UP_TIM16_IRQHandler(void){
HAL_TIM_IRQHandler(&htim1);
volatile unsigned int Delta_f; //Change in frequency
volatile unsigned int fc; //Center frequency
volatile float f[200]; //Timer frequency
volatile float x[200]; //Array for pseudorandom variable
volatile unsigned int D; //Duty cycle
volatile unsigned int F_CLK; //Clock frequency
volatile int i = 0; //Iteration variable
volatile const int mu = 4; //Constant in logistic map
volatile int FirstSwitchPeriod;
volatile int FirstSwitchCycle;
volatile unsigned int UpdateCycle;
volatile unsigned int UpdatePeriod;
Delta_f = 10000; //Hz
fc = 30000; //Hz
D = 50; //%
F_CLK = 72000000;
x[0] = 0.15; //Initialization of Logistic Map variable
f[0] = fc;
//Calculate the needed number to fulfill the next switching cycle period and duty cycle
FirstSwitchPeriod = (F_CLK/fc) - 1; //30kHz makes the switching frequency 50kHz
FirstSwitchCycle = (FirstSwitchPeriod + 1)*D/(100-1);
i++;
/* The math that makes the PWM chaotic: */
//Logistic map
x[i] = mu*x[i-1]*(1-x[i-1]);
//Timer frequency
f[i] = fc + (2*x[i] - 1)*Delta_f;
//Calculate the needed number to fulfill the next switching cycle period and duty cycle:
UpdateCycle = (F_CLK/f[i])*D/(100-1);
//Set up PWN period register and duty cycle register:
htim1.Instance->CCR1 = UpdateCycle;
htim1.Instance->CCR2 = UpdateCycle;
htim1.Instance->CCR3 = UpdateCycle;
//The ARR statys the same, which is the value initiated in MX_TIM1_INIT
}There's more code, but these are the only functions I have made changes in. The problem is that when debugging the IRQ-Handler is never entered and therefore the CRRx's is never assigned their new values.
When I run the code simply nothing happens, all the channels in Timer 1 is constantly on low (I have a LA to check this) and the motor won't run (of course) because of that.
I have been stuck for days, I hope someone can help me!
