cancel
Showing results for 
Search instead for 
Did you mean: 

Advanced-control timers (TIM1&TIM8) Center-aligned mode (up/down counting)

joe239955_stm1_st
Associate
Posted on November 08, 2012 at 15:23

Evaluating the STM32F207 for a project.

I need to create a triangle waveform, starting from an arbitrary point between two limits, and it needs to be able to start in both incrementing or decrementing fashion. I intend to use DMA to play this waveform out to a DAC

I am looking at Advanced-control timers (TIM1&TIM8) Center-aligned mode (up/down counting), I understand that this only works between 0 and TIMx_ARR but I can offset the waveform to the correct point

From the manual page 297 I understand that

“In center-aligned mode, the counter counts from 0 to the auto-reload value (content of the TIMx_ARR register) – 1�

and that

“In this mode, the DIR direction bit in the TIMx_CR1 register cannot be written. It is updated

by hardware and gives the current direction of the counter.�

This indicates to me that when the mode is set the Counter register (TIMx_CNT) is cleared and the DIR direction bit is set to increment.

Question

1>Can the Counter register (TIMx_CNT) be loaded to an arbitrary value after the mode is set if the waveform needs to increment

2>If the waveform needs to start decrementing, could the TIMx_ARR register be set to a small value the timer run until the the limit is hit (now in the right state). Timer disabled (Bit 0 CEN: Counter enable). Then the TIMx_ARR and the Counter register (TIMx_CNT) register set to the proper value, and then reenabled

Thanks in advance

Joe

From the manual

******************************************

Advanced-control timers (TIM1&TIM8)

Page 297

Center-aligned mode (up/down counting)

In center-aligned mode, the counter counts from 0 to the auto-reload value (content of the

TIMx_ARR register) – 1, generates a counter overflow event, then counts from the autoreload

value down to 1 and generates a counter underflow event. Then it restarts counting

from 0.

In this mode, the DIR direction bit in the TIMx_CR1 register cannot be written. It is updated

by hardware and gives the current direction of the counter.

Page 329

Bits 6:5 CMS[1:0]: Center-aligned mode selection

….

….

11: Center-aligned mode 3. The counter counts up and down alternatively. Output compare

interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set

both when the counter is counting up or down.

Note: It is not allowed to switch from edge-aligned mode to center-aligned mode as long as

the counter is enabled (CEN=1)

Bit 4 DIR: Direction

0: Counter used as upcounter

1: Counter used as downcounter

Note: This bit is read only when the timer is configured in Center-aligned mode or Encoder

mode.

******************************************

3 REPLIES 3
Posted on November 08, 2012 at 20:52

While the manual is not crystal clear in this matter, I'd say that the timer would start from the value you write to it and count in the direction you set in the DIR bit just before setting the up/down counting mode. In other words, I don't believe that setting the mode would affect/clear the TIMx_CNT register and the DIR bit; and I believe that the description is meant to say ''if the counter is in its reset state and then the up/down mode is enabled, it will count from 0 up and then down''.

But why don't you just try it with a simple program?

JW

Posted on November 09, 2012 at 14:20

OK I tried and yes, it works exactly as I expected - after setting DIR and TIMx_CNT, setting the up/down mode and enabling the timer does not clear DIR/TIMx_CNT, but it starts off where they were set.

JW

#include ''stm32f4xx.h''

#define AND &

#define OR  |

extern volatile uint32_t a;

volatile uint32_t a;

int main(void) {

  // default HSI clock = 16MHz

  RCC->CFGR |= 0

    OR  RCC_CFGR_HPRE_DIV1    // AHB prescaler set to 1 -> AHB clock = 16MHz

    OR  RCC_CFGR_PPRE1_DIV4   // APB1 prescaler set to 4 -> APB1 clock = 4MHz (required to be < 42MHz)

    OR  RCC_CFGR_PPRE2_DIV2   // APB2 prescaler set to 2 -> APB2 clock = 8MHz (required to be < 84MHz)

  ;

  RCC->AHB1ENR |= 0           // enable clock to all IOs

    OR  RCC_AHB1ENR_GPIOAEN

    OR  RCC_AHB1ENR_GPIOAEN

    OR  RCC_AHB1ENR_GPIOBEN

    OR  RCC_AHB1ENR_GPIOCEN

    OR  RCC_AHB1ENR_GPIODEN

    OR  RCC_AHB1ENR_GPIOEEN

    OR  RCC_AHB1ENR_GPIOFEN

    OR  RCC_AHB1ENR_GPIOGEN

    OR  RCC_AHB1ENR_GPIOHEN

    OR  RCC_AHB1ENR_GPIOIEN

  ;

  RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;          // enable clock to timer

  RCC->APB2RSTR |= RCC_APB2RSTR_TIM8RST;       // pulse to reset timer

  RCC->APB2RSTR &= ~RCC_APB2RSTR_TIM8RST;

  // set PA0 to alternative, select for TIM8_ETR

  GPIOA->MODER |= 0

    OR (GPIO_Mode_AlternateFunction * GPIO_MODER_MODER0_0)

  ;

  GPIOA->AFR[0] |= 0

    OR (GPIO_AlternateFunction_TIM8 * GPIO_AFRL_AFRL0_0)

  ;

  // set clock input to ETR, external clock source mode 2 - no prescaler, but apply the heaviest filter in futile attempt to reduce the bouncing somewhat 🙂

  TIM8->SMCR = 0

    OR ( 0b1111 * TIM_SMCR_ETF_0 )

    OR ( 1      * TIM_SMCR_ECE   )

  ;

  // set reload value to some ''normal'' value so we can ''see'' how it's working through the debugger

  TIM8->ARR = 20;

  // set counter somewhere in the middle

  TIM8->CNT = 10;

  // set DIR to where we want it to go at start, CMS[1:0] as up/down, mode is toggle, and enable the timer

  TIM8->CR1 |= 0

    OR (0b11 * TIM_CR1_CMS)

    OR (1    * TIM_CR1_DIR)  // 0 - count up; 1 - count down

    OR (1    * TIM_CR1_CEN)

  ;

  // and an infinite loop to observe the behaviour in the simulator

  while(1) {

    a = TIM8->CNT;

  };

}

joe239955_stm1_st
Associate
Posted on November 13, 2012 at 16:00

Thank you very much for the input.

The fact that they can be controlled before setting th up/dwn mode will make life much easier.

I will pass this on to my embedded guy

Thanks

Joe