cancel
Showing results for 
Search instead for 
Did you mean: 

TIM1 CHxN aren't disabled by setting CCNE bit to 0

veblor
Associate

Hello everyone, I am trying to implement the 6-Step Trapezoidal Control using the COMG event in STM32F411RE as said in the datasheet.

 

Situation:

I am using 3 half bridges each driven by a single IR2110, IR2110 requires only one input signal to be high at a time to drive each half bridge as planned. I am using TIM1 PWM mode CH1-3 for HINs and CH1N-3N for LINs of each half bridge's IR2110. So in theory, for example, for first commutation, I only need CH1 & CH3N to be active. But as far as my understanding goes, if CH1 is active, I will be getting a complementary signal at CH1N as well. If IR2110 receives signal at HIN and LIN, it might cause overshoot for MOSFETs. There is a dead-time between both signals but, the point is I don't need the signal from CH1N so in my understanding the best way is to set the CC1NE bit to 0. 

 

Problem : When I set CC1NE bit to 0, MCU still outputs the complementary signal although it shouldn't. I suspect this because I set the OSSR bit in BDTR to 1 - which might be keeping the complementary channel active. 

 

The above is all my understanding and analysis. I would love to be corrected. I am pasting my code below.

What am I doing wrong? or it's more about my concept and approach of enabling/disabling channels is wrong? I am not sure how else it could be done. I just don't want the complementary signal to be there when the main channel is active. Out of 6 channels of TIM1, CH1,CH1N,CH2,CH2N,CH3,CH3N, I only want 2 of them active at one time and they must not be from the same channel.

 

timer.c

void TIM1_PWM(void){

 

 ---------------------- Reset TIM1 ----------------------

 

RCC->APB2RSTR |= RCC_APB2RSTR_TIM1RST;

RCC->APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;

 

// ---------------------- TIMER BASE CONFIGURATION ----------------------

TIM1->PSC = 0; // Prescaler = 0 -> Timer clock = 16 MHz (no division)

TIM1->ARR = 800 - 1; // Auto Reload = 799 -> 16 MHz / 800 = 20 kHz PWM frequency

TIM1->CNT = 0; // Clear counter to start from 0

 

 ---------------------- CHANNEL 1 CONFIGURATION ----------------------

TIM1->CCMR1 &= ~(0b111 << 4); // Clear bits [6:4] to ensure OC1M is empty

TIM1->CCMR1 |= (0b110 << 4); // Set OC1M = 110 (PWM mode 1)

TIM1->CCMR1 |= (1U << 3); // Set OC1PE = 1 (Preload enable)

 

TIM1->CCER &= ~ (1U << 1); // Clear CC1P = 0 -> Active High

TIM1->CCER |= (1U << 3); // CC1NP = 1 -> Complementary output active low

 

---------------------- CHANNEL 2 CONFIGURATION ----------------------

 

TIM1->CCMR1 &= ~(0b111 << 12); // Clear bits [14:12]

TIM1->CCMR1 |= (0b110 << 12); // Set OC2M = 110 (PWM mode 1)

TIM1->CCMR1 |= (1U << 11); // Set OC2PE = 1 (Preload enable)

 

TIM1->CCER &= ~(1U << 5); // Clear CC2P = 0 -> Active High

TIM1->CCER |= (1U << 7); // CC2NP = 1 -> Complementary output active low

 

---------------------- CHANNEL 3 CONFIGURATION ------------------------

TIM1->CCMR2 &= ~(0b111 << 4); // Clear bits [6:4]

TIM1->CCMR2 |= (0b110 << 4); // Set OC3M = 110 (PWM mode 1)

TIM1->CCMR2 |= (1U << 3); // Set OC3PE = 1 (Preload enable)

 

TIM1->CCER &= ~(1U << 9); // Clear CC3P = 0 -> Active High

TIM1->CCER |= (1U << 11); // CC3NP = 1 -> Complementary output active low

 

---------------------- BDTR CONFIGURATION ----------------------

TIM1->BDTR = 0;

TIM1->BDTR |= (1U << 15);  --Set MOE = 1 (Output signals enabled)

TIM1->BDTR |= (1U << 11); --Set OSSR = 1 (Off-State Selection for Run mode)

TIM1->BDTR |= (0x20 << 0); -- 2µs dead time for 16MHz

 

// ---------------------- CR1 OPTIONAL SETTINGS ----------------------

TIM1->CR1 &=~ (0b11<<5); // CMS = 00

TIM1->CR1 &=~ (1U<<4);

 

// ---------------------- CR2 OPTIONAL SETTINGS ----------------------

TIM1->CR2 &= ~(0x3F << 8); // Clear OIS bits [13:8] for CH1–CH3

TIM1->CR2 &= ~ (1U << 8); // OIS1 = 0 -> CH1 idle low

TIM1->CR2 &= ~(1U << 9); // OIS1N = 0 -> CH1N idle low

TIM1->CR2 &= ~(1U << 10); // OIS2 = 0 -> CH2 idle low

TIM1->CR2 &= ~(1U << 11); // OIS2N = 0 -> CH2N idle low

TIM1->CR2 &= ~(1U << 12); // OIS3 = 0 -> CH3 idle low

TIM1->CR2 &= ~(1U << 13); // OIS3N = 0 -> CH3N idle low

 

TIM1->CR2 |= (1U << 2); // CCUS = 1 -> capture/compare control bits are preloaded

TIM1->CR2 |= (1U << 0); // CCPC = 1 -> CCxE, CCxNE and OCxM bits are preloaded

// ---------------------- SET DUTY CYCLES ----------------------

TIM1->CCR1 = 200; // 20% Duty Cycle for Channel 1

TIM1->CCR2 = 200; // 20% Duty Cycle for Channel 2

TIM1->CCR3 = 200; // 20% Duty Cycle for Channel 3

 

// ---------------------- FINAL ENABLE SEQUENCE ----------------------

 

 

TIM1->CR1 |= (1U << 7); // ARPE = 1 -> Auto-Reload Preload Enable

 

TIM1->EGR = TIM_EGR_UG; // Generate update to load preload registers

 

TIM1->CR1 |= (1U << 0); // CEN = 1 -> Enable Counter, start PWM generation

 

TIM1->SR &= ~TIM_SR_UIF; // Clear the UG Flag in the SR

 

}
motor.c

 

#define Phase_A_High (TIM_CCER_CC1E)

#define Phase_A_Low (TIM_CCER_CC1NE)

#define Phase_B_High (TIM_CCER_CC2E)

#define Phase_B_Low (TIM_CCER_CC2NE)

#define Phase_C_High (TIM_CCER_CC3E)

#define Phase_C_Low (TIM_CCER_CC3NE)

 

#define CCER_ENABLE_MASK (Phase_A_High | Phase_A_Low | Phase_B_High | Phase_B_Low | Phase_C_High | Phase_C_Low)

 

 

static uint8_t step = 0;

 

static Step_Configuration config_table[6] = {

 

// 0. A+, B-

{

.ccer = (Phase_A_High | Phase_B_Low),

//.ccr = {200,200,0},

},

 

// 1. A+, C-

{

.ccer = Phase_A_High | Phase_C_Low,

//.ccr = {200,0,200},

 

},

// 2. B+, C-

{

.ccer = Phase_B_High | Phase_C_Low,

//.ccr = {0,200,200},

 

},

// 3. B+, A-

{

.ccer = Phase_B_High | Phase_A_Low,

//.ccr = {200,200,0},

 

},

// 4. C+, A-

{

.ccer = Phase_C_High | Phase_A_Low,

//.ccr = {200,0,200},

 

},

// 5. C+, B-

{

.ccer = Phase_C_High | Phase_B_Low,

//.ccr = {0,200,200},

 

},

 

};

 

 

 

void commutation(void){

 

//Step_Configuration* config = &config_table[step];

 

TIM1->CCER |= (TIM1->CCER &~ CCER_ENABLE_MASK) | config_table[step].ccer;

 

// TIM1->CCR1 = config->ccr[0];

// TIM1->CCR2 = config->ccr[1];

// TIM1->CCR3 = config->ccr[2];

 

TIM1->EGR = TIM_EGR_COMG;

 

delay_us(10);

 

step++;

 

if(step >= 6){ // this is for testing only

 

step = 4;

 

}

 

 

}

 

main.c

..... code ....

TIM1_PWM();

 

while(1){

 

commutation();

 

delay_us(100);

 

}

 

 

0 REPLIES 0