2014年1月1日 星期三

[STM32] 使用STM32F103CB TIMx 實做 us_delay

圖一

要使用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設定後,再來就是TIMx的設定(以下使用TIM4做介紹),使用TIMx有2個小觀念要先建立,
  1. 決定1個Clock從High到Low的時間多久 ( TIMx_CNT)
  2. 決定幾個Clock之後要發出interrupt ( TIMx_ARR )
  3. TIMx_PSC 計算公式 : Counter Clock Frequency = fCK_PSC / (PSC[15:0] + 1)
搞清楚後,撰寫部分就簡單了,可參考以下us_delay的實做,

// 製作 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);
}

Reference:
[1] STM32通用定时器(TIM2-5)基本用法
[2] STM32F1

沒有留言:

張貼留言