2012-11-08 06:23 AM
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.
******************************************
2012-11-08 11:52 AM
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? JW2012-11-09 05:20 AM
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; }; }2012-11-13 07:00 AM