AnsweredAssumed Answered

Trigering ADC in the Middle of PWM ON Duty Cycle

Question asked by slimsly on Feb 7, 2013
Latest reply on Feb 8, 2013 by jj.sprague
Hello,

My intention is using TIM1 Complementary PWM Channel 1-3 for Brushless Motor Control. I want to sample the Phase Voltage at the middle of PWM ON Duty Cycle. I have configure TIM1 to output 6 Channel PWM but there seems to be a problem in triggering an event at the middle on the High Duty Cycle.I configure TIM1 CH1-3 & CH1-3N as 20Khz PWM output while CH4 is configure in Timing Output Compare  with interrupt enable.I toggle PB8-PB9 on CH4 Output Compare match Interrupt.

The Problem is I get multiple toggle in one PWM period. I was hoping to see one  PA8-9 Toggle per PWM Period.I plan on triggering the ADC in the CC4 Interrupt which should happen at the middle of the PWM ON duty cycle with little delay.I have change CCR4 Value but it still stay thesame.

I am Microchip Fan and new to STM32F.In Microchip dsPIC30F Microcontroller, it is pretty easy and straight forward.I have attached logic analyzer screen shot of PWM Channels and PA8-9 .

Logic Analyzer Channel Identification.
Channel0 =>CH1
Channel1=>CH1N
Channel2 =>CH2
Channel3=>CH2N
Channel4 =>CH3
Channel5=>CH3N
Channel6=>PA8
Channel7=>PA9

My Source Code

#include "stm32f10x.h"

void Init_6CHPWM();
void TIM1_CC_IRQHandler(void);

int main(void)
{

  RCC-> CFGR |= RCC_CFGR_ADCPRE_DIV4;     //ADC divided by 4
  /*Enable all GPIO Clock & Alternate Function Clock*/
  RCC->APB2ENR = RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN;
  /*Enable ADC1 & ADC2 Clock*/
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN;
  /*Enable TIMER1 & USART1 Clock*/
  RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_USART1EN;
  /*Enable TIMER2, TIMER3 & I2C1 Clock*/
  RCC->APB1ENR = RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN |RCC_APB1ENR_I2C1EN | RCC_APB1ENR_TIM4EN;
  RCC->AHBENR = RCC_AHBENR_DMA1EN ;   //DMA1 clock enable

  GPIOB->CRL = 0x444444AA;    //Configure PB0 & PB1 as Alternate Function Push Pull Output
  GPIOB->CRH = 0x44444222;    //Configure PB8 & PB9 as Output (Push Pull)
  GPIOA->CRL = 0xA4444444;   //PA7 Alternate Function Push Pull Output
  GPIOA->CRH = 0x44444AAA;  //PA8 - PA10 Alternate Function Push Pull Output

  /*Partial remap TIM1: CH1/PA8,CH2/PA9,CH3/PA10,CH4/PA11,CH1N/PA7,CH2N/PB0,CH3N/PB1
   * Remap USART1: TX/PB6, RXPB7   */
  AFIO->MAPR |= AFIO_MAPR_TIM1_REMAP_PARTIALREMAP | AFIO_MAPR_USART1_REMAP;

  Init_6CHPWM();                       //Initialize 20KHz PWM on CH 1-3

    while(1)
    {

    }
}


void Init_6CHPWM()
{

    TIM1->CCMR1 |= 0x00006878; //CH1 & CH2 Output Compare, Preload, PWM1 Enable
    //CH3 Output Compare, Preload, PWM1 Enable | CH4 Output Compare, Timing Enable
    TIM1->CCMR2 |= 0x00008878;
    /*CH1, CH2, CH3 and their Corresponding  Complement Output Enable*/
    TIM1->CCER  |= 0x00000555;
    TIM1->CR1 |= 0x00000080;   // Centre Align Mode 1 & Auto-reload Preload enable
    TIM1->PSC = 0;
    TIM1->ARR = (2800 - 1);    // Auto reload value 1400 (Period = 50us)
    TIM1->CCR1 = 1400;         // Start PWM duty for channel 1
    TIM1->CCR2 = 1000;        // Start PWM duty for channel 2
    TIM1->CCR3 = 600;         // Start PWM duty for channel 3
    TIM1->CCR4 = 1700;         //CH4 Compare Value
    TIM1->BDTR |= 0x00008800;  // Enable Main O/P & Enable OSSR
    TIM1->CR1 |= 0x00000001;   //Counter Enable

    TIM1->DIER |= 0x00000010;  //Capture/Compare 4 interrupt enable
    NVIC_EnableIRQ(TIM1_CC_IRQn); // Enable interrupt from TIM1 Compare (NVIC level)
}

void TIM1_CC_IRQHandler(void)
{
  if(TIM1->SR & TIM_SR_CC4IF)          // if CC4IF flag is set
    {
      TIM3->SR &= ~TIM_SR_CC4IF;     //Clear CC4IF Flag
      GPIOB->ODR ^= (1 << 8);       // toggle LED state
      GPIOB->ODR ^= (1 << 9);
    }
}

I will like to know if it is possible?. if if Yes How?.

Regards
SLim
Please forgive my english

Attachments

Outcomes