圖一 |
要使用STM32的Timer功能,首要條件,須要先搞清楚目前自己的RCC配置(圖一紅色框框),筆者的RCC設定為(system_stm32f10x.c)如下:
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; // APB
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; // ABP1
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; // APB2
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; // APB
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; // ABP1
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; // APB2
清楚RCC設定後,再來就是TIMx的設定(以下使用TIM4做介紹),使用TIMx有2個小觀念要先建立,
- 決定1個Clock從High到Low的時間多久 ( TIMx_CNT)
- 決定幾個Clock之後要發出interrupt ( TIMx_ARR )
- TIMx_PSC 計算公式 : Counter Clock Frequency = fCK_PSC / (PSC[15:0] + 1)
// 製作 us_delay :
// 1. 產生 6MHz的Counter Clock Frequency,即表示1Clock = 1/6 us
// 2. 1 us = 6 clock一個interrupt
// 3. Counter Clock Frequency = fCK_PSC / (PSC + 1)
// 6M = 72M / ( PSC + 1 ) => PSC = 72M/6M -1
// 因為 APB1不為1(RCC設定得知),所以fCK_PSC = 36M * 2= 72M
static __IO uint32_t TimingDelay;
static void RCC_Configuration()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
}
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 處理 interrupt
void Delay_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4 , TIM_FLAG_Update);
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
}
void delay_us(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void DelayInit()
{
u16 PrescalerValue = 0;
u32 CounterClock = 6000000; // 6M
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_Configuration();
NVIC_Configuration();
PrescalerValue = (uint16_t) (SystemCoreClock / CounterClock) - 1;
TIM_TimeBaseStructure.TIM_Period = 6; // TIMx_ARR
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; //TIMx_PSC
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_Cmd(TIM4, ENABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
// 1. 產生 6MHz的Counter Clock Frequency,即表示1Clock = 1/6 us
// 2. 1 us = 6 clock一個interrupt
// 3. Counter Clock Frequency = fCK_PSC / (PSC + 1)
// 6M = 72M / ( PSC + 1 ) => PSC = 72M/6M -1
// 因為 APB1不為1(RCC設定得知),所以fCK_PSC = 36M * 2= 72M
static __IO uint32_t TimingDelay;
static void RCC_Configuration()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
}
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 處理 interrupt
void Delay_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4 , TIM_FLAG_Update);
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
}
void delay_us(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void DelayInit()
{
u16 PrescalerValue = 0;
u32 CounterClock = 6000000; // 6M
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_Configuration();
NVIC_Configuration();
PrescalerValue = (uint16_t) (SystemCoreClock / CounterClock) - 1;
TIM_TimeBaseStructure.TIM_Period = 6; // TIMx_ARR
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; //TIMx_PSC
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_Cmd(TIM4, ENABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
Reference:
[1] STM32通用定时器(TIM2-5)基本用法
[2] STM32F1
沒有留言:
張貼留言