Selasa, 14 Desember 2010

Timer di STM32

Timer (TIM) di STM32 ternyata sangat kompleks, liat contoh2nya diperiperal driver ada banyak bangat. Untungnya ketemu tutorial timer di youtube walaupun dalam bahasa thailand tapi source codenya bisa dimengerti.

Untuk mendapatkan timer sebesar 1ms formulanya begini:

Time = SystemCoreClock \ ((TIM_Period+1) * (TIM_Prescaler+1))



1ms = 72MHz \ ((35999+1) * (1+1))

with prescaler 1 and TIM_CounterClock 24MHz:

1us = 24MHz \ ((23+1) * (0 + 1))

1ms = 24MHz \ ((23999+1) * (0+1))

with prescaler 999 and TIM_CounterClock 24KHz:
500ms = 24MHz \ ((1199+1) * (999+1))

1s = 24MHz \ ((23999+1) * (999+1))


or another formula is:

prescaler = (SystemCoreClock \ TIM_CounterClock) - 1;
prescaler = (24MHz \ 1MHz) - 1
prescaler = 23

1uS = 1MHz
1MHz = TIM_CounterClock \ (TIM_Period + 1)
1MHz = 1MHz \ (0 + 1)

with prescler 23 and TIM_CounterClock 1MHz:

to get 1us timer TIM_Period is 0

to get 1ms timer TIM_Period is 999


Note: cara lain untuk mendapatkan timer adalah menggunakan systick timer.

Source Code menggunakan STM32F100 Valueline discovery kit.
Hasil: Led hijau (PC9) akan toggle setiap 1s dan led biru (PC8) toggle setiap 500ms

main.c




/* Includes */
#include
#include "stm32f10x.h"


void setupHardware(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

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

/* GPIOC clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

/* Enable green led PC9 and blue led PC8 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);
}

void setupTimer()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/*------------------------------------------
SystemCoreClock
Time = -----------------------------
(TIM_Period+1) * (TIM_Prescaler+1)


1ms = 72MHz \ ((35999+1) * (1+1))

with prescaler 1 and TIM_CounterClock 24MHz:

1us = 24MHz \ ((23+1) * (0 + 1))

1ms = 24MHz \ ((23999+1) * (0+1))

with prescaler 999 and TIM_CounterClock 24KHz:
500ms = 24MHz \ ((1199+1) * (999+1))

1s = 24MHz \ ((23999+1) * (999+1))


or another formula is:

prescaler = (SystemCoreClock \ TIM_CounterClock) - 1;
prescaler = (24MHz \ 1MHz) - 1
prescaler = 23

1uS = 1MHz
1MHz = TIM_CounterClock \ (TIM_Period + 1)
1MHz = 1MHz \ (0 + 1)

with prescler 23 and TIM_CounterClock 1MHz:

to get 1us timer TIM_Period is 0

to get 1ms timer TIM_Period is 999


------------------------------------------------*/
/* Enable Timer2 for every 1s
* This will blink green led*/

TIM_TimeBaseStructure.TIM_Period = 23999;
TIM_TimeBaseStructure.TIM_Prescaler = 999;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);

/*Enable Auto reload */
TIM_ARRPreloadConfig(TIM2, ENABLE);

TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Regular);

/* TIM IT Enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

/* TIM2 Enable counter */
TIM_Cmd(TIM2, ENABLE);

/*Enable Timer 3 for every 500ms
* This will blink blue led */
TIM_TimeBaseStructure.TIM_Period = 11999;
TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);

/*Enable Auto reload */
TIM_ARRPreloadConfig(TIM3, ENABLE);

TIM_UpdateRequestConfig(TIM3, TIM_UpdateSource_Regular);

/* TIM IT Enable */
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

/* TIM3 Enable counter */
TIM_Cmd(TIM3, ENABLE);

}

/**
**===========================================================================
**
** Abstract: main program
**
**===========================================================================
*/
int main(void)
{
/* TODO - Add your application code here */
setupHardware();
setupTimer();
/* Infinite loop */
while (1)
{

}
}

#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */
while (1)
{
}
}
#endif

/*
* Minimal __assert_func used by the assert() macro
* */
void __assert_func(const char *file, int line, const char *func, const char *failedexpr)
{
while(1)
{}
}

/*
* Minimal __assert() uses __assert__func()
* */
void __assert(const char *file, int line, const char *failedexpr)
{
__assert_func (file, line, NULL, failedexpr);
}



Jangan lupa tambah ini di file stm32f10x_it.c



void TIM2_IRQHandler(void)
{

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
GPIO_WriteBit(GPIOC, GPIO_Pin_9, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_9)));
}
}

void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
GPIO_WriteBit(GPIOC, GPIO_Pin_8, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_8)));
}
}