cancel
Showing results for 
Search instead for 
Did you mean: 

TIM3 Problem

ctechguy
Associate II
Posted on November 04, 2011 at 05:50

I’m having a lot of problems with timer 3. What I’m trying to simply do now is remap TIM3 to the leds and have the blue led stay one for 1sec and the green to stay on for 1.5sec. Now when I tried to do this the leds didn’t turn off. I saw if I did the operation twice it appeared to worked the second time. So now I turn the timer on wait 2sec and turn it off and it seems to work except when it overflows it turns the leds on then stops. Is there a warmup required for the timers, this doesn’t seem like the correct solution. In other tasks I’ve been working on I keep having issues with TIM3, especially not working the first time. I have attached my current code with delay and I would like to remove the delay if possible. I think the second part of the overflow and staying on is doing what I said. Is there a way to stop the counter before turning the leds back on?

Thanks so much Chris.

#include ''stm32f10x.h''
#define eint() asm volatile(''cpsie i'')
#define dint() asm volatile(''cpsid i'')
#define PCDDR_HIGH GPIOC->CRH

int tick=0;
int main(void) {
 dint();
 initializeHW();
 initializeTimersAndInterrupts();

 SysTick->CTRL = 3;
 SysTick->LOAD = 1000;

 eint();
 int curr=tick;
 while(tick<curr+2000){}//2sec delay, warmup????
 TIM3->CR1=0;//Turn off timer
 TIM3->CCR3=1000;//Blue led 1sec
 TIM3->CCR4=1500;//Green led 1.5sec

 TIM3->CCMR2=0x6060;//Set compare 3 and 4 to pwm
 TIM3->CNT=0;//Set counter to 0
 TIM3->CR1=9;//Run once!

 while(1){}
 return 0;
}

void initializeHW(){
 RCC->APB2ENR = 0x74A3D; // enable the GPIO devices and timers
 RCC -> APB1ENR = 0x1ff;
 AFIO -> MAPR = 0x02008000;
 AFIO->MAPR |= 0x00000C00;// remap tim3
 PCDDR_HIGH=0x11111199;//Set Leds to timer
}
void initializeTimersAndInterrupts(void){
 TIM3->PSC=7999;
 TIM3->CCER=0x1100; // enable compare 3 and 4
 TIM3->CCMR2=0x4040;//Force off
 TIM3->CR1=1;//Start timer
}
void systick_isr(void) {
 tick++;
}


#define STACK_TOP 0x20002000
extern void _start(void);
unsigned int *myvectors[] __attribute__((section(''.vectors''))) = {
 //(unsigned int*) STACK_TOP,
 //(unsigned int*) _start
 (void(*)(void)) STACK_TOP, // stack pointer
 _start, // code entry point
 0, // handle non-maskable interrupts
 0, // handle hard faults
 0,0,0,0, /* ..1f */
 0,0,0,0, /* ..2f */
 0,0,0,systick_isr, /* ..3f */
};

6 REPLIES 6
Posted on November 04, 2011 at 15:41

It does not need to warmup. It's a synchronous design and will work as soon as it is started. If you use the PLL you might need to wait for that to lock, but that is handled by a spin-loop in the startup code. It looks like you're assuming an 8 MHz HSI clock. If the processor is running, the timer certainly can.
 You'd find life easier if you use the library code.
 APB2ENR is only 16-bits wide.
 If you want the LEDs to cycle, you'll need to define a period for the timer, perhaps 3 seconds, and then setup the PWM widths for 1 and 1.5 seconds respectively.
 If you need a 50/50 duty cycle, the PWM mode is not capable of generating two frequencies from the same timer, you could use a toggle mode, but you'd need to chase the compare interrupts and advance the CCR for each.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
rmteo
Associate II
Posted on November 04, 2011 at 15:44

As Clive suggested, using the STD Peripheral Library will save you a lot of pain down the road (and immediately as well).

// System Clocks Configuration

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |

                        RCC_APB2Periph_USART1, ENABLE);    

// Initialize LEDs

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

// PB.0 Alternate function TIM3_CH3

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

// USART1 Tx (PA9)

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    

GPIO_Init(GPIOA, &GPIO_InitStructure);

// USART1 Rx (PA10)

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

Posted on November 04, 2011 at 16:04

Here's a ten minute solution/demonstration, TIM3 works just fine.

#include ''stm32F10x.h'' #include ''STM32vldiscovery.h'' /**************************************************************************************/ void RCC_Configuration(void) { // clock for GPIO (C, AFIO=REMAP) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO , ENABLE); // clock for TIM3 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); } /**************************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // PC8,9 Remapped TIM3 CH3,4 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); } /**************************************************************************************/ void TIM3_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // use 8000-1 for an 8 MHz startup implementation TIM_TimeBaseStructure.TIM_Prescaler = 24000-1; // 24 MHz div 24000 (1 KHz tick) TIM_TimeBaseStructure.TIM_Period = 3000-1; // 3 Second Period TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 1; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // channel 3 configuration (PC.08) Remapped TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1000; // 1 Second On TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM3, &TIM_OCInitStructure); // channel 4 configuration (PC.09) Remapped TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1500; // 1.5 Second On TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC4Init(TIM3, &TIM_OCInitStructure); // turning on TIM3 and PWM outputs TIM_Cmd(TIM3, ENABLE); TIM_CtrlPWMOutputs(TIM3, ENABLE); } /**************************************************************************************/ int main(void) { RCC_Configuration(); GPIO_Configuration(); TIM3_Configuration(); while(1); }


Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ctechguy
Associate II
Posted on November 04, 2011 at 16:32

That sounds good, I'll try that later. Ya I only need to do one cylce and will start the cycle over again manually.

ctechguy
Associate II
Posted on November 04, 2011 at 23:28

Thanks so much it is actually working with out warmup. The library is a bit confusing right now but I'm sure it will be very helpful in the future. Is there a way to have it only cycle once? I thought that is what RepetitionCounter = 1, but it still loops. If I remove the period the leds are always on. I was also thinking that if I had too I could try and put a overflow interrupt to stop the timer. See I want to have a new cycle when I receive a interrupt from something else but only last once. Thanks again

Chris

Posted on November 05, 2011 at 13:26

I don't have a specific answer on the TIM one-shot setting, but for the kind of timebase you're talking about I would probably manage the LEDs in the SysTick interrupt (say 1ms or 100ms, depending on application needs), and expire each on their own counter. A lot of RTOS applications use a single timer in this fashion with enough granularity to fit the resolution required.
 On the TIM, you can of course catch the update or compare interrupts. The LEDs however will not be independent, and you'll have more fun resetting the timer.
 You might want to look at using this
 /* One Pulse Mode selection */
 TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single);

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..