0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32基礎(chǔ)知識:定時器的定時計(jì)數(shù)功能

CHANBAEK ? 來源:上下求索電子er ? 作者:上下求索電子er ? 2023-10-24 15:26 ? 次閱讀

定時器定時計(jì)數(shù)功能

1 定時器概述

  • 定時器是對周期固定的脈沖信號進(jìn)行計(jì)數(shù),如MCU內(nèi)部的外設(shè)時鐘(APB)。
  • 計(jì)數(shù)器是對周期不確定的脈沖信號進(jìn)行計(jì)數(shù),如MCU的I/O引腳所引入的外部脈沖信號。
  • 定時器和計(jì)數(shù)器本質(zhì)上都是計(jì)數(shù)器,定時器是計(jì)數(shù)器的一種特例。

2 STM32定時器分類

圖片

對于STM32F103共存在6個外設(shè)定時器:高級定時器TIM1,通用定時器TIM2、TIM3、TIM4。

2.1 內(nèi)核定時器

  • 系統(tǒng)節(jié)拍定時器:Systick定時器是屬于內(nèi)核中的一個外設(shè),內(nèi)嵌在NVIC中。

2.2 外設(shè)定時器

  • 常規(guī)定時器> STM32F103xx增強(qiáng)型產(chǎn)品中,內(nèi)置了多達(dá)3個可同步運(yùn)行的標(biāo)準(zhǔn)定時器(TIM2、TIM3和TIM4)。每個定時器都有一個16位的自動加載遞加/遞減計(jì)數(shù)器、一個16位的預(yù)分頻器和4個獨(dú)立的通道,每個通道都可用于輸入捕獲、輸出比較、PWM和單脈沖模式輸出.
    • 高級定時器:除具備通用定時器的功能外,還具備帶死區(qū)控制的互補(bǔ)信號輸出、緊急剎車關(guān)斷輸入等功能,可用于電機(jī)控制數(shù)字電源設(shè)計(jì)。
    • 基本定時器:幾乎沒有任何輸入/輸出通道,常用作時基,實(shí)現(xiàn)基本的定時/計(jì)數(shù)功能。
    • 通用定時器:具備多路獨(dú)立的捕獲和比較通道,可以完成定時/計(jì)數(shù)、輸入捕獲、輸出比較等功能。
  • 專用定時器

3 定時器的時鐘頻率

圖片

4 定時器的主要功能

4.1 定時計(jì)數(shù)

  • 計(jì)數(shù)內(nèi)部時鐘,即定時器模式
  • 計(jì)數(shù)外部脈沖,即計(jì)數(shù)器模式

4.2 輸出比較

  • PWM輸出
  • 電平翻轉(zhuǎn)
  • 單脈沖輸出
  • 強(qiáng)制輸出

4.3 輸入捕獲

  • 捕獲時保存定時器的當(dāng)前計(jì)數(shù)值
  • 捕獲時,可選擇觸發(fā)捕獲中斷
  • 觸發(fā)捕獲的信號邊沿類型可選擇(上升沿,下降沿,雙邊沿)

5 HAL庫的定時器設(shè)計(jì)

5.1 定時器句柄結(jié)構(gòu)的組成

圖片

5.2 三種外設(shè)編程模型

  • 以后綴區(qū)分編程模型
  • 入口參數(shù)均為外設(shè)句柄的指針
方式函數(shù)
輪詢方式HAL_TIM_Base_Start(TIM_HandleTypeDef *htim );HAL_TIM_Base_Stop TIM_HandleTypeDef *htim );
中斷方式HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
DMA方式HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length);

6 定時器的定時/計(jì)數(shù)功能

6.1 時基單元

圖片圖片

①預(yù)分頻模塊

  • 預(yù)分頻計(jì)數(shù)器:對預(yù)分頻時鐘CK_PSC進(jìn)行分頻
  • 預(yù)分頻寄存器:TIMx_PSC:設(shè)置預(yù)分頻系數(shù)PSC
  • 作用1:擴(kuò)大定時器的定時范圍
  • 作用2:獲取精確的計(jì)數(shù)時鐘

預(yù)分頻模塊工作原理 定時器啟動后,預(yù)分頻計(jì)數(shù)器的初值為0,預(yù)分頻時鐘CK_PSC每來一個時鐘,預(yù)分頻計(jì)數(shù)器的值就加1。當(dāng)計(jì)數(shù)值等于預(yù)分頻寄存器所設(shè)定的預(yù)分頻系數(shù)PSC時,預(yù)分頻計(jì)數(shù)器的值將清零,開始下一輪計(jì)數(shù)。

預(yù)分頻時序圖:圖片

假設(shè)預(yù)分頻系數(shù)PSC=3,預(yù)分頻計(jì)數(shù)器從0計(jì)數(shù)到PSC實(shí)際計(jì)數(shù)值為PSC+1,也就是進(jìn)行了四分頻。
image.png

②計(jì)數(shù)模塊

  • 核心計(jì)數(shù)器:對計(jì)數(shù)時鐘CK_CNT進(jìn)行二次計(jì)數(shù)
  • 計(jì)數(shù)器寄存器:TIMx_CNT:存放核心計(jì)數(shù)器運(yùn)行時的當(dāng)前計(jì)數(shù)值

③自動重載模塊

  • 自動重載模塊由自動重載寄存器TIMx_ARR組成
    • 遞增計(jì)數(shù)模式:TIMx_ARR的值作為核心計(jì)數(shù)器的計(jì)數(shù)終值
    • 遞減計(jì)數(shù)模式:TIMx_ARR的值作為核心計(jì)數(shù)器的計(jì)數(shù)初值

④計(jì)數(shù)模式

圖片

計(jì)數(shù)模式計(jì)數(shù)器溢出值計(jì)數(shù)器重載值
遞增計(jì)數(shù)CNT=ARRCNT=0
遞減計(jì)數(shù)CNT=0CNT=ARR
中心對齊計(jì)數(shù)CNT=ARR-1CNT=1CNT=ARRCNT=0

6.2 定時器時序圖

圖片

①定時時間公式

②相關(guān)寄存器

  • 預(yù)分頻寄存器TIMx_PSC: 設(shè)置預(yù)分頻系數(shù),將預(yù)分頻時鐘(CK_PSC)進(jìn)行1~65536之間的任意值分頻,得到計(jì)數(shù)時鐘(CK_CNT)。
  • 計(jì)數(shù)器寄存器TIMx_CNT : 存放核心計(jì)數(shù)器運(yùn)行時的當(dāng)前計(jì)數(shù)值,便于用戶實(shí)時掌握核心計(jì)數(shù)器的當(dāng)前計(jì)數(shù)值。芯片復(fù)位后,默認(rèn)值為0。
  • 自動重載寄存器TIMx_ARR: 為計(jì)數(shù)器設(shè)置計(jì)數(shù)邊界或重載值。比如計(jì)數(shù)器遞增計(jì)數(shù)時,記到多少發(fā)生溢出;遞減計(jì)數(shù)時,從多少開始往下計(jì)數(shù)。

6.3 外部脈沖計(jì)數(shù)

圖片

6.4 數(shù)據(jù)類型和接口函數(shù)

圖片

成員變量:

成員變量ClockDivision的取值范圍:

TIM_CLOCKDIVISION_DIV1對定時器時鐘TIM_CLK進(jìn)行1分頻
TIM_CLOCKDIVISION_DIV2對定時器時鐘TIM_CLK進(jìn)行2分頻
TIM_CLOCKDIVISION_DIV4對定時器時鐘TIM_CLK進(jìn)行4分頻

成員變量CounterMode的取值范圍

TIM_COUNTERMODE_UP遞增計(jì)數(shù)模式
TIM_COUNTERMODE_DOWN遞減計(jì)數(shù)模式
TIM_COUNTERMODE_CENTERALIGNED1中心對齊計(jì)數(shù)模式1
TIM_COUNTERMODE_CENTERALIGNED2中心對齊計(jì)數(shù)模式2
TIM_COUNTERMODE_CENTERALIGNED3中心對齊計(jì)數(shù)模式3

成員變量AutoReloadPreload的取值范圍

TIM_AUTORELOAD_PRELOAD_DISABLE預(yù)裝載功能關(guān)閉
TIM_AUTORELOAD_PRELOAD_ENABLE預(yù)裝載功能開啟
  1. 用于設(shè)置自動重載寄存器TIMx_ARR的預(yù)裝載功能,即自動重裝寄存器的內(nèi)容是更新事件產(chǎn)生時寫入有效,還是立即寫入有效;
  2. 預(yù)裝載功能在多個定時器同時輸出信號時比較有用,可以確保多個定時器的輸出信號在同一個時刻變化,實(shí)現(xiàn)同步輸出;
  3. 單個定時器輸出時,一般不開啟預(yù)裝載功能。

接口函數(shù):

  1. 時基單元初始化函數(shù):HAL_TIM_Base_Init

    函數(shù)原型HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
    功能描述按照定時器句柄中指定的參數(shù)初始化定時器時基單元
    入口參數(shù)htim:定時器句柄的地址
    返回值HAL狀態(tài)值
    注意事項(xiàng)1. 該函數(shù)將調(diào)用MCU底層初始化函數(shù)HAL_TIM_Base_MspInit完成引腳、時鐘和中斷的設(shè)置2. 該函數(shù)由CubeMX自動生成
  2. 輪詢模式啟動函數(shù):HAL_TIM_Base_Start

    函數(shù)原型HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
    功能描述在輪詢方式下啟動定時器運(yùn)行
    入口參數(shù)htim:定時器句柄的地址
    返回值HAL狀態(tài)值
    注意事項(xiàng)1. 該函數(shù)在定時器初始化完成之后調(diào)用2. 函數(shù)需要由用戶調(diào)用,用于輪詢方式下啟動定時器運(yùn)行
  3. 中斷模式啟動函數(shù):HAL_TIM_Base_Start_IT

    函數(shù)原型HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
    功能描述使能定時器的更新中斷,并啟動定時器運(yùn)行
    入口參數(shù)htim:定時器句柄的地址
    返回值HAL狀態(tài)值
    注意事項(xiàng)1. 該函數(shù)在定時器初始化完成之后調(diào)用2. 函數(shù)需要由用戶調(diào)用,用于使能定時器的更新中斷,并啟動定時器運(yùn)行3. 啟動前需要調(diào)用宏函數(shù) __HAL_TIM_CLEAR_IT 來清除更新中斷標(biāo)志
  4. 定時器中斷通用處理函數(shù)HAL_TIM_IRQHandler

    函數(shù)原型void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
    功能描述作為所有定時器中斷發(fā)生后的通用處理函數(shù)
    入口參數(shù)htim:定時器句柄的地址
    返回值
    注意事項(xiàng)1. 函數(shù)內(nèi)部先判斷中斷類型,并清除對應(yīng)的中斷標(biāo)志,最后調(diào)用回調(diào)函數(shù)完成中斷處理2. 該函數(shù)由CubeMX自動生成
  5. 定時器更新中斷回調(diào)函數(shù)HAL_TIM_PeriodElapsedCallback

    函數(shù)原型void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    功能描述回調(diào)函數(shù),用于處理所有定時器的更新中斷,用戶在該函數(shù)內(nèi)編寫實(shí)際的任務(wù)處理程序
    入口參數(shù)htim:定時器句柄的地址
    返回值
    注意事項(xiàng)1.該函數(shù)由定時器中斷通用處理函數(shù)HAL_TIM_IRQHandler調(diào)用,完成所有定時器的更新中斷的任務(wù)處理2.函數(shù)內(nèi)部需要根據(jù)定時器句柄的實(shí)例來判斷是哪一個定時器產(chǎn)生的本次更新中斷3.函數(shù)由用戶根據(jù)具體的處理任務(wù)編寫
  6. 計(jì)數(shù)值讀取函數(shù)__HAL_TIM_GET_COUNTER

    #define __HAL_TIM_GET_COUNTER(__HANDLE__) ((__HANDLE__)- >Instance- >CNT)
    

    __HANDLE__:定時器句柄的地址

    該函數(shù)通過直接訪問計(jì)數(shù)器寄存器TIMx_CNT來獲取計(jì)數(shù)器的當(dāng)前計(jì)數(shù)值。

  7. 定時器中斷標(biāo)志清除函數(shù)__HAL_TIM_CLEAR_IT

    #define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)- >Instance- >SR = ~(__INTERRUPT__))
    

    __HANDLE__:定時器句柄的地址

    __INTERRUPT__:定時器中斷標(biāo)志

    圖片

任務(wù)實(shí)踐1

基于STM32F103C8T6,開發(fā)板原理圖

圖片

利用開發(fā)板上的按鍵KEY2來觸發(fā)外部脈沖,按鍵每按下一次,就利用PA1引腳發(fā)送一個周期2ms左右的脈沖,送到定時器2的外部觸發(fā)引腳ETR(PA0)進(jìn)行計(jì)數(shù),并將計(jì)數(shù)結(jié)果通過串口發(fā)送到PC上顯示。

注:本任務(wù)例程使用的開發(fā)板,KEY2與PA5相連接。KEY2原理圖如下:

圖片

使用按鍵時,需要設(shè)置PA5為輸入上拉模式,這樣在KEY2沒有按下時,PA5可以讀取到高電平,KEY2按下時PA5可以讀取到低電平。

  1. 配置PA1為GPIO_Output(User Label:PULSE),PA5為GPIO_Input(User Label:KEY2),上拉模式。
    圖片
    圖片
    上述操作在stm32f1xx_hal_gpio.c中生成GPIO引腳初始化函數(shù)MX_GPIO_Init,并在main.c中調(diào)用

    void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : PA1 */
      GPIO_InitStruct.Pin = GPIO_PIN_1;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PA5 */
      GPIO_InitStruct.Pin = GPIO_PIN_5;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
  2. 配置定時器2時鐘源為外部觸發(fā)引腳ETR2,自動重載寄存器ARR配置為一個相對較大的計(jì)數(shù),防止溢出。外部脈沖信號采用默認(rèn)配置:不使用濾波,不進(jìn)行脈沖信號反相,不進(jìn)行脈沖信號分頻。
    圖片
    圖片
    上述操作在tim.c生成引腳初始化函數(shù):

    void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(tim_baseHandle- >Instance==TIM2)
      {
      /* USER CODE BEGIN TIM2_MspInit 0 */
    
      /* USER CODE END TIM2_MspInit 0 */
        /* TIM2 clock enable */
        __HAL_RCC_TIM2_CLK_ENABLE();
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /**TIM2 GPIO Configuration
        PA0-WKUP     ------ > TIM2_ETR
        */
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /* USER CODE BEGIN TIM2_MspInit 1 */
    
      /* USER CODE END TIM2_MspInit 1 */
      }
    }
    
    void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
    {
    
      if(tim_baseHandle- >Instance==TIM2)
      {
      /* USER CODE BEGIN TIM2_MspDeInit 0 */
    
      /* USER CODE END TIM2_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_TIM2_CLK_DISABLE();
    
        /**TIM2 GPIO Configuration
        PA0-WKUP     ------ > TIM2_ETR
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
    
      /* USER CODE BEGIN TIM2_MspDeInit 1 */
    
      /* USER CODE END TIM2_MspDeInit 1 */
      }
    }
    

    上述操作在tim.c生成如下代碼完成初始化定時器,并在main.c中調(diào)用

    /* TIM2 init function */
    void MX_TIM2_Init(void)
    {
    
      /* USER CODE BEGIN TIM2_Init 0 */
    
      /* USER CODE END TIM2_Init 0 */
    
      TIM_ClockConfigTypeDef sClockSourceConfig = {0};
      TIM_MasterConfigTypeDef sMasterConfig = {0};
    
      /* USER CODE BEGIN TIM2_Init 1 */
    
      /* USER CODE END TIM2_Init 1 */
      htim2.Instance = TIM2;
      htim2.Init.Prescaler = 0;
      htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim2.Init.Period = 65535;
      htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
      if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
      sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
      sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
      sClockSourceConfig.ClockFilter = 0;
      if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
      {
        Error_Handler();
      }
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM2_Init 2 */
    
      /* USER CODE END TIM2_Init 2 */
    
    }
    

    其中調(diào)用的HAL_TIM_Base_Init函數(shù)將調(diào)用HAL_TIM_Base_MspInit完成引腳初始化。

  3. 配置串口外設(shè)USART1,選擇異步模式,無硬件流控。
    圖片
    上述操作在usart.c中生成串口配置相關(guān)函數(shù),并在main.c中調(diào)用。usart的封裝邏輯與tim相同,不再贅述。

    void MX_USART1_UART_Init(void)
    {
    
      /* USER CODE BEGIN USART1_Init 0 */
    
      /* USER CODE END USART1_Init 0 */
    
      /* USER CODE BEGIN USART1_Init 1 */
    
      /* USER CODE END USART1_Init 1 */
      huart1.Instance = USART1;
      huart1.Init.BaudRate = 115200;
      huart1.Init.WordLength = UART_WORDLENGTH_8B;
      huart1.Init.StopBits = UART_STOPBITS_1;
      huart1.Init.Parity = UART_PARITY_NONE;
      huart1.Init.Mode = UART_MODE_TX_RX;
      huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart1.Init.OverSampling = UART_OVERSAMPLING_16;
      if (HAL_UART_Init(&huart1) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN USART1_Init 2 */
    
      /* USER CODE END USART1_Init 2 */
    
    }
    
    void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(uartHandle- >Instance==USART1)
      {
      /* USER CODE BEGIN USART1_MspInit 0 */
    
      /* USER CODE END USART1_MspInit 0 */
        /* USART1 clock enable */
        __HAL_RCC_USART1_CLK_ENABLE();
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /**USART1 GPIO Configuration
        PA9     ------ > USART1_TX
        PA10     ------ > USART1_RX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /* USER CODE BEGIN USART1_MspInit 1 */
    
      /* USER CODE END USART1_MspInit 1 */
      }
    }
    
    void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
    {
    
      if(uartHandle- >Instance==USART1)
      {
      /* USER CODE BEGIN USART1_MspDeInit 0 */
    
      /* USER CODE END USART1_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_USART1_CLK_DISABLE();
    
        /**USART1 GPIO Configuration
        PA9     ------ > USART1_TX
        PA10     ------ > USART1_RX
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
    
      /* USER CODE BEGIN USART1_MspDeInit 1 */
    
      /* USER CODE END USART1_MspDeInit 1 */
      }
    }
    
  4. 程序編寫
    使用串口輸出,需要在Keil的Options中勾選Use MicroLIB.
    圖片
    在main.c中重定義printfscanf函數(shù)

    /* USER CODE BEGIN Includes */
    #include < stdio.h >
    /* USER CODE END Includes */
    
    /* USER CODE BEGIN 4 */
    int fputc (int ch, FILE *f)
    {
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
        return ch;
    }
    int fgetc(FILE *f)
    {
        uint8_t ch = 0;
        HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
        return ch;
    }
    /* USER CODE END 4 */
    

    用戶變量定義代碼

    /* USER CODE BEGIN PV */
    uint8_t Result = 0;
    /* USER CODE END PV */
    

    用戶變量初始化代碼

    /* USER CODE BEGIN 2 */
      HAL_TIM_Base_Start_IT(&htim2);
      printf("Timer count function test: n");
      /* USER CODE END 2 */
    

    用戶應(yīng)用代碼

    /* USER CODE BEGIN 3 */
        if (HAL_GPIO_ReadPin(GPIOA, KEY2_Pin) == GPIO_PIN_RESET)
        {
          HAL_Delay(10);
          if (HAL_GPIO_ReadPin(GPIOA, KEY2_Pin) == GPIO_PIN_RESET)
          {
            HAL_GPIO_WritePin(GPIOA, PULSE_Pin, GPIO_PIN_SET);
            HAL_Delay(1);
            HAL_GPIO_WritePin(GPIOA, PULSE_Pin, GPIO_PIN_RESET);
            HAL_Delay(1);
            Result = __HAL_TIM_GET_COUNTER(&htim2);
            printf("Count = %d", Result);
          }
          while (HAL_GPIO_ReadPin(GPIOA, KEY2_Pin) == GPIO_PIN_RESET);
        }
      }
      /* USER CODE END 3 */
    

    實(shí)驗(yàn)現(xiàn)象

    圖片

任務(wù)實(shí)踐2

設(shè)計(jì)電子時鐘,從00:00:00開始計(jì)時,并將計(jì)時信息通過串口UART1發(fā)送到PC進(jìn)行顯示。

  1. 配置定時器1產(chǎn)生1s的更新中斷。計(jì)算PSC和ARR的值,將T=1s,TIM_CLK=8000000Hz帶入公式
    得可取值PSC=1999,ARR=3999.
    在CubeMX中使能TIM1,采用內(nèi)部時鐘 (8MHz) ,設(shè)置PSC和ARR值,并在嵌套向量中斷控制器NVIC設(shè)置中使能TIM1的更新中斷。
    圖片
    圖片
    上述操作在tim.c中生成TIM1初始化函數(shù),并在main.c中調(diào)用

  2. 配置USART1串口輸出,生成代碼后應(yīng)在工程中重定向printfscanf函數(shù),方法同任務(wù)實(shí)踐1,這部分不再贅述。

  3. 編寫代碼
    main.c中進(jìn)行用戶數(shù)據(jù)類型定義

    /* USER CODE BEGIN PTD */
    typedef struct
    {
      uint8_t hour;
      uint8_t minutes;
      uint8_t second;
    }CLOCK_Typedef;
    /* USER CODE END PTD */
    

    用戶變量定義

    /* USER CODE BEGIN PV */
    CLOCK_Typedef clock = {0};
    /* USER CODE END PV */
    

    用戶初始化代碼

    /* USER CODE BEGIN 2 */
     // 清除更新中斷標(biāo)志,避免定時器一啟動就進(jìn)入中斷
      __HAL_TIM_CLEAR_IT(&htim1, TIM_IT_UPDATE);
      HAL_TIM_Base_Start_IT(&htim1);
      /* USER CODE END 2 */
    

    用戶應(yīng)用代碼

    /* USER CODE BEGIN 3 */
        printf("Time:%02d:%02d:%02d.rn", clock.hour, clock.minutes, clock.second);
        HAL_Delay(1000);
      }
      /* USER CODE END 3 */
    

    編寫定時器更新中斷回調(diào)函數(shù)

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
      if (htim- >Instance == TIM1)  // 判斷時鐘源
      {
        clock.second++;
        if (clock.second == 60)
        {
          clock.second = 0;
          clock.minutes++;
          if (clock.minutes == 60)
          {
            clock.minutes = 0;
            clock.hour++;
            if (clock.hour == 24)
            {
              clock.hour = 0;
            }
          }
        }
      }
    }
    
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    16665

    瀏覽量

    347737
  • STM32
    +關(guān)注

    關(guān)注

    2257

    文章

    10828

    瀏覽量

    352432
  • 計(jì)數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2241

    瀏覽量

    93969
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3218

    瀏覽量

    113665
  • 脈沖信號
    +關(guān)注

    關(guān)注

    6

    文章

    376

    瀏覽量

    36775
收藏 人收藏

    評論

    相關(guān)推薦

    電機(jī)控制基礎(chǔ)知識1—定時器基礎(chǔ)知識與PWM輸出原理

    轉(zhuǎn)速等。 本篇先介紹 定時器基礎(chǔ)知識 ,然后對照這些知識介紹一下 定時器輸出PWM的基本原理 ,以及 編程實(shí)現(xiàn)與代碼分析 。 首先來看一下定時器
    的頭像 發(fā)表于 06-17 00:11 ?1.2w次閱讀
    電機(jī)控制<b class='flag-5'>基礎(chǔ)知識</b>1—<b class='flag-5'>定時器</b><b class='flag-5'>基礎(chǔ)知識</b>與PWM輸出原理

    定時器基礎(chǔ)知識

    目錄:一、定時器基礎(chǔ)知識二、基本定時器(TIM6和TIM7)三、通用定時器(TIM2~TIM6)1.功能特點(diǎn)2.時鐘源3.時基單元4.輸入捕
    發(fā)表于 08-09 07:30

    STM32使用定時器計(jì)數(shù)

    32完全可以克服這一困難STM32F103系列可使用的定時器8個,其中通用定時器有TMI1-TIM7高級定時器TIM0 TIM8而在這 我主要使用通用
    發(fā)表于 08-18 07:23

    定時器基礎(chǔ)知識與PWM輸出原理是什么

    轉(zhuǎn)速等。本篇先介紹定時器基礎(chǔ)知識,然后對照這些知識介紹一下定時器輸出PWM的基本原理,以及編程實(shí)現(xiàn)與代碼分析。首先來看一下定時器的基礎(chǔ)介紹
    發(fā)表于 01-25 08:16

    定時計(jì)數(shù)技術(shù)

    單片機(jī)控制系統(tǒng)中常常用到的定時計(jì)數(shù)問題。5.1  定時計(jì)數(shù)概述1、定時的定義:      
    發(fā)表于 12-17 14:39 ?24次下載

    定時器/計(jì)數(shù)器基礎(chǔ)

    15-1.實(shí)現(xiàn)定時的方法15-2.定時器/計(jì)數(shù)器的結(jié)構(gòu)和工作原理 15-3.定時器/計(jì)數(shù)器的控制15-4.
    發(fā)表于 03-23 12:17 ?48次下載

    ASF設(shè)計(jì):定時計(jì)數(shù)器的中斷是如何使用的?

    ASF設(shè)計(jì)2:定時計(jì)數(shù)器的中斷使用
    的頭像 發(fā)表于 07-10 01:05 ?3967次閱讀

    STM32定時器基本計(jì)數(shù)原理解析

    STM32的TIM定時器分為三類:基本定時器、通用定時器和高級定時器。從分類來看就知道STM32
    發(fā)表于 12-27 16:20 ?1.8w次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>定時器</b>基本<b class='flag-5'>計(jì)數(shù)</b>原理解析

    定時器計(jì)數(shù)器基礎(chǔ)知識和使用方法及C程序?qū)崿F(xiàn)1s鐘定時的程序

    本文檔的主要內(nèi)容詳細(xì)介紹的是定時器計(jì)數(shù)器基礎(chǔ)知識和使用方法及C程序?qū)崿F(xiàn)1s鐘定時的程序。
    發(fā)表于 04-18 17:27 ?6次下載
    <b class='flag-5'>定時器</b>與<b class='flag-5'>計(jì)數(shù)器</b>的<b class='flag-5'>基礎(chǔ)知識</b>和使用方法及C程序?qū)崿F(xiàn)1s鐘<b class='flag-5'>定時</b>的程序

    淺談定時器基礎(chǔ)知識與PWM輸出原理

    轉(zhuǎn)速等。 本篇先介紹定時器基礎(chǔ)知識,然后對照這些知識介紹一下定時器輸出PWM的基本原理,以及編程實(shí)現(xiàn)與代碼分析。 首先來看一下定時器的基礎(chǔ)
    的頭像 發(fā)表于 04-05 10:35 ?1.4w次閱讀
    淺談<b class='flag-5'>定時器</b><b class='flag-5'>基礎(chǔ)知識</b>與PWM輸出原理

    STM32定時器-基本定時器

    目錄定時器分類基本定時器功能框圖講解基本定時器功能時鐘源計(jì)數(shù)器時鐘
    發(fā)表于 11-23 18:21 ?31次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>定時器</b>-基本<b class='flag-5'>定時器</b>

    電機(jī)控制基礎(chǔ)——定時器基礎(chǔ)知識與PWM輸出原理

    轉(zhuǎn)速等。本篇先介紹定時器基礎(chǔ)知識,然后對照這些知識介紹一下定時器輸出PWM的基本原理,以及編程實(shí)現(xiàn)與代碼分析。首先來看一下定時器的基礎(chǔ)介紹
    發(fā)表于 11-30 14:21 ?38次下載
    電機(jī)控制基礎(chǔ)——<b class='flag-5'>定時器</b><b class='flag-5'>基礎(chǔ)知識</b>與PWM輸出原理

    stm32中斷源有哪些_【話說定時器系列】之八:STM32定時器計(jì)數(shù)定時基本功能實(shí)驗(yàn)...

    TIMER 的基本應(yīng)用原理、常規(guī)應(yīng)用等?,F(xiàn)在將課程內(nèi)容整理為文章,針對STM32定時器有基本了解的用戶,分享具體的應(yīng)用實(shí)現(xiàn)環(huán)節(jié)及常見問題解決。實(shí)驗(yàn)內(nèi)容:使用STM32定時器的基本
    發(fā)表于 12-05 13:21 ?0次下載
    <b class='flag-5'>stm32</b>中斷源有哪些_【話說<b class='flag-5'>定時器</b>系列】之八:<b class='flag-5'>STM32</b><b class='flag-5'>定時器</b><b class='flag-5'>計(jì)數(shù)</b><b class='flag-5'>定時</b>基本<b class='flag-5'>功能</b>實(shí)驗(yàn)...

    STM32 使用定時器計(jì)數(shù) 寄存版本

    32完全可以克服這一困難STM32F103系列可使用的定時器8個,其中通用定時器有TMI1-TIM7高級定時器TIM0 TIM8而在這 我主要使用通用
    發(fā)表于 12-27 18:27 ?0次下載
    <b class='flag-5'>STM32</b> 使用<b class='flag-5'>定時器</b><b class='flag-5'>計(jì)數(shù)</b> 寄存<b class='flag-5'>器</b>版本

    STM32F03定時器基礎(chǔ)知識基本簡介

    STM32F103微控制定時器分為系統(tǒng)定時器(SysTick)、“看門狗”定時器(WatchDog)、基本
    的頭像 發(fā)表于 07-03 17:08 ?3310次閱讀
    <b class='flag-5'>STM32</b>F03<b class='flag-5'>定時器</b><b class='flag-5'>基礎(chǔ)知識</b>基本簡介