顯示具有 STM32F411xC 基礎教學 標籤的文章。 顯示所有文章
顯示具有 STM32F411xC 基礎教學 標籤的文章。 顯示所有文章

2016年7月24日 星期日

STM32F411xC 基礎教學 :Timer使用方式

STM32F411xC/E Timer可分為以下三組:
1. Advanced-control timer(TIM1)
2.General-purpose timers(TIM2 to TIM5)
3.General-purpose timers(TIM9 to TIM11)

ps. TIM8 在STM32F411xC/E中是不能用的。

這三組有各自相對應的block diagram,根據使用不同的AHB/APB2或AHB/APB1,也會對時間計算有不同的結果,細節可自行參考RM0383 Reference manual

STM32 Timer 每次進入中斷時間間隔計算方式:
((1+TIM_Prescaler) / 系統頻率)*(1+TIM_Period) =
((1+9599)/96Mhz) * (1+9999) = 1 sec。

main function:
int main(void)
{
  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);

  debug_io_init();
  TIM2_Init();

  /* Infinite loop */
  while (1)

}


Debug GPIO(PC15) init:
void debug_io_init( void )
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOC, ENABLE );
 
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_ResetBits(GPIOC, GPIO_Pin_15);
    GPIO_SetBits(GPIOC, GPIO_Pin_15);
}


TIM2 init:
void TIM2_Init(void)
{
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

   NVIC_InitTypeDef NVIC_InitStructure;

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

   /* 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);

   /* Time base configuration */
   TIM_TimeBaseStructure.TIM_Period            = 10000-1;
   TIM_TimeBaseStructure.TIM_Prescaler         = 9600-1;
   TIM_TimeBaseStructure.TIM_ClockDivision     = 0;
   TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

   TIM_ClearFlag(TIM2, TIM_FLAG_Update);
   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
   TIM_Cmd(TIM2, ENABLE);
}


TIM2 IRQHandler:
void TIM2_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
  {
    GPIO_ResetBits(GPIOC, GPIO_Pin_15);
    GPIO_SetBits(GPIOC, GPIO_Pin_15);
 
    GPIO_ToggleBits(GPIOC, GPIO_Pin_0);
 
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  }
}


驗證:
    下圖為邏輯分析儀測量的結果,由圖中可看出PC15每一秒鐘會觸發一次,符合我們所預期的時間。


2016年7月21日 星期四

STM32F411xC 基礎教學 :SysTick使用方式

本篇基於STM32F411xC平台,紀錄SysTick的使用方式。

實驗說明:
    使用GPIO(PC15)來觀察程式進入SysTick_Handler,到下一次進入SysTick_Handler的時間。

Main function:
int main(void)
{

  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);

  SysTick_Config(960000+1);//10ms中斷一次

  while ( 1 ) {
    if (flag_10ms_period){
      flag_10ms_period = 0;
      //每10ms要執行的function
    }
  }
}


SysTick_Handler function:
extern volatile uint8_t flag_10ms_period;
void SysTick_Handler(void)
{
  GPIO_SetBits(GPIOC, GPIO_Pin_15);

  flag_10ms_period = 1;

  GPIO_ResetBits(GPIOC, GPIO_Pin_15);
}


    SysTick會依照你使用MCU的系統頻率來計算中斷次數,下圖為STM32F411xC的SysClk,這次範例要計算每10ms中斷一次,計算方式為96000MHz(實體頻率) * 10,並在main.c中加入SysTick_Config(96000*10)

STM32F411xC Sysclk
使用邏輯分析儀觀察GPIO:
    由下圖觀察到,由於我們在SysTick_Handler中有做將GPIO拉high->low的動作,因此觀察GPIO high的間格時間,即可知道SysTick是否依我們的設計每10m觸發一次。



2016年7月20日 星期三

STM32F411xC 基礎教學 : Button與 LED使用方式

本篇基於STM32F411xC平台,記錄板端Button與Led的使用方式。

實驗說明:
按下Button1(PD2)點亮Led2(PC0),Button2(PC12)點亮Led5(PC1)。

Button 初始化:

//button1:PD2
//button2:PC12

void Btn_Init(void) {

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD, ENABLE );

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_Init( GPIOD, &GPIO_InitStructure );

  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOC, ENABLE );

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_Init( GPIOC, &GPIO_InitStructure );
}

LED 初始化:

//LED2:PC0
//LED5:PC1
//LED3:PC2
//LED4:PC3

void gpio_led_config( void )
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOC, ENABLE );

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init( GPIOC, &GPIO_InitStructure );
}


Main function:

int main(void)
{

  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);

  Btn_Init();
  gpio_led_config();

  while ( 1 ) {

   //Sw1
   if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2) == 0){
   //turn on PC0:LED2
   GPIO_SetBits(GPIOC, GPIO_Pin_0);
   }else{
   //turn off PC0:LED2
   GPIO_ResetBits(GPIOC, GPIO_Pin_0);
   }

   //Sw2
   if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_12) == 0){
   GPIO_SetBits(GPIOC, GPIO_Pin_1);
   }else{
   GPIO_ResetBits(GPIOC, GPIO_Pin_1);
   }
  }

}