AnsweredAssumed Answered

How to measure a PWM Output Signal with PWM Input

Question asked by rottm.oliver on Apr 15, 2011
Hello, I'm a beginner with microcontrollers and this post is about my first project with a STM32F100 Discovery microcontroller.

I need to generate a PWM with MCB1(MicroControllerBoard1) and with another board, the MCB2, I should measure the PWM that is generated by MCB1 using the PWM Input mode.

My assignment is to measure the PWM, that is generated by MCB1 as Beats per Minute which vary from 60-180 Bpm, with MCB2 using the PWM Input function. I am able to see the Bpm blinking on the transmitting board(MCB1) but I don't know how to detect the correct Bpm on MCB2 with PWM Input mode.

I say "board" because we built a board to connect some peripherals to the stm32. Here is a picture of how it looks like.



The lcd display should show us the measured PWM as Beats per Minute from the Input Pin.

Now here are my questions... I'm not sure if the initializations I used are correct.

I initialized the MCB1 which should generate the PWM Output this way:
I used Timer3 and Output Pins PC6-9 and Internal Clock is set to 24Mhz:

/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
u16 CCR1_Val = 250;
u16 CCR2_Val = 250;
u16 CCR3_Val = 250;
u16 CCR4_Val = 250;
u16 Periode = 999;
u16 Prescaler = 11999;

.
.
.


/* -----------------------------------------------------------------------
    TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles:
    TIM3CLK = 36 MHz, Prescaler = 0x0, TIM3 counter clock = 36 MHz
    TIM3 ARR Register = 999 => TIM3 Frequency = TIM3 counter clock/(ARR + 1)
    TIM3 Frequency = 36 KHz.
 PC06   TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
 PC07   TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
 PC08   TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
 PC09   TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
  ----------------------------------------------------------------------- */
 void TIM_Setup(void)
{
   /* TIM3 enable counter */
  //TIM_Cmd(TIM3, DISABLE);
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = Periode;
  TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  TIM_OC3Init(TIM3, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;

  TIM_OC4Init(TIM3, &TIM_OCInitStructure);

  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

  TIM_ARRPreloadConfig(TIM3, ENABLE);

  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);
  }

.
.
.

/* Configure GPIOC port pins  *************************************************/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);


  /* Configure C6 - C9 for PWM leds *********************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* TIM3 Full Remap */
  GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

.
.
.


And I initialized the MCB2 which should measure the PWM with a PWM Input Pin this way:
I used Timer2 and Input Pin PA.01 and Internal Clock is set to 24Mhz:

/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_ICInitTypeDef  TIM_ICInitStructure;

.
.
.

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

.
.
.

void PWM_Input_Mode(void)
  {
  TIM_ICInitTypeDef TIM_ICInitStructure;

      /* TIM2 clock enable     */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  //TIM_ETRClockMode1Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0);
--> I don't know... do I need this function to be synchronized with the PWM output signal

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);

  /* Select the TIM2 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

  /* Enable the Master/Slave Mode */
  TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

  /* TIM enable counter */
  TIM_Cmd(TIM2, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
  }

And I also configured the NVIC for Tim2.

The Interrupt service routine for Tim2 looks like this:

void TIM2_IRQHandler(void)
{
  /* Clear TIM2 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM2);


  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM2) * 100) / IC2Value;
    /* Frequency computation */
    Frequency = 24000000 / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

I think I have a problem with the configuration of the PWM Input but I don't know whats missing or wrong..

Once again my assignment is to measure the PWM, that is generated by MCB1 as Beats per Minute which vary from 60-180 Bpm, with MCB2 using the PWM Input function. I am able to see the Bpm blinking on the transmitting board(MCB1) but I don't know how to detect the correct Bpm on MCB2 with PWM Input mode.

And I don't know when do I jump into the Interrupt Service Routine of Tim2?! 

Outcomes