Google Code Prettify

2019年2月19日 星期二

[STM32]使用Timer中斷

前一個實驗,使用IO來控制LED,並且運用Delay的副程式來讓LED一秒切換一次狀態,但是這樣的作法實際上並不理想,大多數Delay的副程式是使用while迴圈來讓程式空轉,達到延時或計時的效果,這意味著在這空轉的期間,系統的主程式沒辦法做讓何事情。

為了使程式在使用上更有效率,大部分類似的功能都是使用Timer來實現。

以下是Timer的設定步驟

選擇完晶片後,首先是設定外部震盪,如果要使用內部震盪可直接略過

選擇外部震盪

再來是選擇Clock source

選擇internal clock

再來跳到Clock configuration,設定頻率,這邊我是使用外部震盪,石英晶體的頻率為8M,最後APB1與APB2的頻率為24M。

Clock configuration
接下來是要設定Timer的中斷間隔,我使用的是Timer1來做示範,可以查看資料手冊中,Timer的Clock source 是APB2



接下來要計算Timer的中斷時間,以0.5s為範例,我時脈是24M,Prescaler應該要設定
24M/(2-1),但是Prescaler數值範圍只有16bit也就是0~65535所以我們要用一些變通的方法來做,Prescaler設定23999,也就是24K-1,然後把Period設定成500,也就是說計數器每秒可以計數1000次,在計數到第500次的時候發生中斷,執行中斷的內容。

Prescaler與Period的設定值


Main程式中新增
HAL_TIM_Base_Start_IT(&htim1);

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start_IT(&htim1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
 

在TIM1_UP_TIM16_IRQHandler中加入IO狀態切換的副程式


void TIM1_UP_TIM16_IRQHandler(void)

{

  /* USER CODE BEGIN TIM1_UP_TIM16_IRQn 0 */

 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);

  /* USER CODE END TIM1_UP_TIM16_IRQn 0 */

  HAL_TIM_IRQHandler(&htim1);

  /* USER CODE BEGIN TIM1_UP_TIM16_IRQn 1 */



  /* USER CODE END TIM1_UP_TIM16_IRQn 1 */

}



[STM32]使用Timer中斷

前一個實驗,使用IO來控制LED,並且運用Delay的副程式來讓LED一秒切換一次狀態,但是這樣的作法實際上並不理想,大多數Delay的副程式是使用while迴圈來讓程式空轉,達到延時或計時的效果,這意味著在這空轉的期間,系統的主程式沒辦法做讓何事情。 為了使程式在使用上更有...