Skip to main content
Visitor II
March 3, 2017
Solved

One pulse with repitition counter

  • March 3, 2017
  • 4 replies
  • 4772 views
Posted on March 03, 2017 at 08:14

Hi all,

I am a newbie developer for STM I am developing an application using the STM32F746 Discovery board and KEIL uVision. I need to output two pulses on GPIO that I will feed to another board. The first pulse is a simple PWM with 250kHz frequency and 60% duty cycle. This part was easy as I simply modified the examples of PWM given in DFP 2.8 using HAL library and I outputted it on TIM3 Channel 1.

The tricky part is the second pulse. It should start on the falling edge of pulse 1 and out put a fixed number of pulses and then stop and start on next falling edge. The processor should never be involved in this. So I searched for solutions and found that it could be done using One Pulse mode and Repetition Counter register.

Also I figured out that only TIM1 and TIM8 have repetition counter.

So my question is how can I start the One Pulse Mode with N-Pulse generation using TIM3 Channel 1 falling edge as trigger? The reason I am asking is because in the HAL library there is a function HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel). So it requires two channels of same timer (One for Input i.e trigger and other for the desired waveform output). So do we need to physically short the output of TIM3 channel 1 to TIM1 Channel 2?

Or can we set the trigger internally without doing any such thing?

Also is there any example of this available? Anyone who has completed this who can share their work? I am a newbie and facing great difficulty in my first STM32 project.

0690X00000603i0QAA.jpg

Note: this post was migrated and contained many threaded conversations, some content may be missing.
    This topic has been closed for replies.
    Best answer by waclawek.jan

    Posted on March 04, 2017 at 01:51

    Perhaps not, but my inference is that micro-managing TIM registers on a cycle-to-cycle basis is done with an IRQ or DMA.

    Or the built-in facilities of timers themselves - these manage individual bits rather than complete registers, of course. One-time mode (in timers where available, sure) is one of them - if set, the (repetition-)update event will clear CR1.CEN. Trigger mode of slave controller is other - it sets CR1.CEN upon TRGI leading edge. Incidentally, we don't need anything else here.

    Have a 'L476 DISCO?

    www.efton.sk/STM32/slave_onex3.zip (needs headers from www.efton.sk/STM32/stm32l476xx.zip )

    Enjoy! ;)

    Jan

    4 replies

    Visitor II
    March 3, 2017
    Posted on March 03, 2017 at 13:05

    There should be few ways to implement this. Try to use DMA to Output Capture, cycling through a list of compare values, if the chosen timer and STM32 is able to do this. Otherwise, use another timer trigged by the PWM to repeat counts as initially thoughts.

    Graduate II
    March 3, 2017
    Posted on March 03, 2017 at 17:49

    +1 Use a DMA pattern buffer to drive a cyclic pattern into the TIMx->CCRx (zero disables the output). You could trigger the DMA from the TIM outputting the pattern

    Super User
    March 3, 2017
    Posted on March 03, 2017 at 22:04

    IMO DMA is an overkill in this case. This calls for two timer being linked, one providing the output pulse and a TRGO to the other, which is set to one-pulse mode with repetition counter, and as a slave linked to first and set to trigger mode.

    I am a newbie and facing great difficulty in my first STM32 project.

    We all were newbies and faced difficulties, and believe me, I still face them today, but I believe I will prevail simply by continued learning, however boring this may sound.

    Your first STM32 project is an overkill.  The first project in whatever mcu should be a plain blinky, and then evolve from that. You can achieve spectacular effects with modifying existing cube or whatever projects, but beyond those, having achieved no firm foundations, you get quickly lost.

    http://norvig.com/21-days.html

    JW

    Visitor II
    March 6, 2017
    Posted on March 06, 2017 at 09:26

    I wont be able to try any suggestion till next week as I have to go outside of my city for a week..... I will let you know about the result or any problem that I will face....

    Visitor II
    March 16, 2017
    Posted on March 16, 2017 at 05:47

    Here is the final version of working code for Discovery 746NG boards. This is for someone in future who will come here looking for same issue....

    // (C)2017 wek at efton dot sk
    // example for:
    // -- linked timers, slave in trigger mode, i.e. counter enabled from the master
    // -- (slave) timer in one-pulse-mode with repetition
    void TIM_TEST(void)
    {
    #define F_CPU 216000000UL
    #define TIM_CCMR_CCS__OUTPUT 0
    #define TIM_CCMR_OCM__PWM1 6 
    #define TIM_CCMR_OCM__PWM2 7 
    #define TIM_CR2_MMS__OC1REF 4
    #define TIM_CR2_MMS__OC2REF 5
    #define TIM1_SMCR_TS__TIM2 1
    #define TIM1_SMCR_TS__TIM3 2
    #define TIM_SMCR_SMS__TRIGGER 6
    GPIO_InitTypeDef GPIO_InitStruct;
     /*##-1- Enable peripherals and GPIO Clocks #################################*/
     /* TIMx Peripheral clock enable */
     __TIM2_CLK_ENABLE();
    //__TIM1_CLK_ENABLE();//For future use if any...
    __TIM8_CLK_ENABLE();
     /* Enable all GPIO Channels Clock requested */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
     /* Configure PA.15 (pin 2 in CN7 connector) (TIM2_Channel1), 
     PA.08 (pin 6 in CN4 connector) (TIM1_Channel1), 
     PC.06 (pin 2 in CN4 connector) (TIM8_Channel1)
     in output, push-pull, alternate function mode
     */
     /* Common configuration for all channels */
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_PULLUP;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
     GPIO_InitStruct.Pin = GPIO_PIN_15;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
     GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
     GPIO_InitStruct.Pin = GPIO_PIN_8;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
     GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
     GPIO_InitStruct.Pin = GPIO_PIN_6;
     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    // setup TIM2 to provide the continued PWM waveform, 250kHz period and 60:40% duty
     TIM2->PSC = 0;// this sets prescaler shadow
     TIM2->ARR = 432;// want 250 kHz. Formula is Update Event Frequency = TIM_CLK / (Prescaler +1) * (Autoreload +1) 
     TIM2->EGR = TIM_EGR_UG; // through forced update load prescaler from shadow
     TIM2->CCMR1 = 0
     | (TIM_CCMR_CCS__OUTPUT * TIM_CCMR1_CC1S_0) // output compare on CH2
     | (TIM_CCMR_OCM__PWM2 * TIM_CCMR1_OC1M_0) // PWM2 mode on CH2
     ;
     TIM2->CCER = 0
     | (1 * TIM_CCER_CC1P) // invert TIM2_CH2 
     | (1 * TIM_CCER_CC1E) // enable TIM2_CH2
     ;
     TIM2->CCR1 = (60ULL * 432/ 100);//60% duty cycle. Here 432 is ARR set above. If changed above change here also...
     TIM2->CR2 = 0
     | (TIM_CR2_MMS__OC1REF * TIM_CR2_MMS_0) // select OC1Ref as TRGO
     ;
     TIM2->CR1 = 0
     | (1 * TIM_CR1_CEN) // finally, counter enable
     ;
    // now setup TIM8 - we want it to disable itself i.e. one-pulse mode; 16 pulses, that goes to repetition counter.
    TIM8->PSC = 0; // this sets prescaler shadow
     TIM8->ARR = 12; // want 16 MHz
     TIM8->RCR = 16 - 1; // want 16 pulses until CR1.CEN goes off
     TIM8->EGR = TIM_EGR_UG; // through forced update load prescaler from shadow
     TIM8->CCMR1 = 0
     | (TIM_CCMR_CCS__OUTPUT * TIM_CCMR1_CC1S_0) // output compare
     | (TIM_CCMR_OCM__PWM2 * TIM_CCMR1_OC1M_0) // PWM2 mode - low, then high
     ;
    TIM8->CCER = 0
     | (1 * TIM_CCER_CC1E) // enable TIM8_CH1
     ;
     TIM8->BDTR = 0
     | (1 * TIM_BDTR_MOE) // and the advanced-timers' gotcha: main output enable
     ;
     TIM8->CCR1 = (50ULL * 12 / 100); // this is to achieve 50: Note here 12 is ARR. So if change ARR above then also change here. 
     TIM8->SMCR = 0
     | (TIM1_SMCR_TS__TIM2 * TIM_SMCR_TS_0) // select TIM1/TIM8 as TRGI source
     | (TIM_SMCR_SMS__TRIGGER * TIM_SMCR_SMS_0) // and set trigger mode for slave controller
     ;
    // Notes By Imran.... Above register setting for SMCR means
    // SMS 0110: Trigger Mode - The counter starts at a rising edge of the trigger TRGI.
    // TS 001: Internal Trigger 1 (ITR1) i.e From TIM2 to TIM1/TIM8 (Slave)
    // See refernce manual page 672 for details.... 
     TIM8->CR1 = 0
     | (1 * TIM_CR1_OPM) // want one-time mode
     | (0 * TIM_CR1_CEN) // we don't set CEN bit in CR1, it will be set from the slave controller by the trigger mode
     ;
    while(1); // and, as promised, this is all, folks. Lean back and enjoy! :-)
    }
     �?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    Super User
    April 1, 2024

    Those links got damaged due to the forum migration, I've fixed them. But basically you will find there the same code as is posted above.

    JW