定時(shí)器定時(shí)計(jì)數(shù)功能
1 定時(shí)器概述
- 定時(shí)器是對(duì)周期固定的脈沖信號(hào)進(jìn)行計(jì)數(shù),如MCU內(nèi)部的外設(shè)時(shí)鐘(APB)。
- 計(jì)數(shù)器是對(duì)周期不確定的脈沖信號(hào)進(jìn)行計(jì)數(shù),如MCU的I/O引腳所引入的外部脈沖信號(hào)。
- 定時(shí)器和計(jì)數(shù)器本質(zhì)上都是計(jì)數(shù)器,定時(shí)器是計(jì)數(shù)器的一種特例。
2 STM32定時(shí)器分類
對(duì)于STM32F103共存在6個(gè)外設(shè)定時(shí)器:高級(jí)定時(shí)器TIM1,通用定時(shí)器TIM2、TIM3、TIM4。
2.1 內(nèi)核定時(shí)器
- 系統(tǒng)節(jié)拍定時(shí)器:Systick定時(shí)器是屬于內(nèi)核中的一個(gè)外設(shè),內(nèi)嵌在NVIC中。
2.2 外設(shè)定時(shí)器
- 常規(guī)定時(shí)器> STM32F103xx增強(qiáng)型產(chǎn)品中,內(nèi)置了多達(dá)3個(gè)可同步運(yùn)行的標(biāo)準(zhǔn)定時(shí)器(TIM2、TIM3和TIM4)。每個(gè)定時(shí)器都有一個(gè)16位的自動(dòng)加載遞加/遞減計(jì)數(shù)器、一個(gè)16位的預(yù)分頻器和4個(gè)獨(dú)立的通道,每個(gè)通道都可用于輸入捕獲、輸出比較、PWM和單脈沖模式輸出.
- 專用定時(shí)器
- 看門(mén)狗定時(shí)器
- 實(shí)時(shí)時(shí)鐘
- 低功耗定時(shí)器
3 定時(shí)器的時(shí)鐘頻率
4 定時(shí)器的主要功能
4.1 定時(shí)計(jì)數(shù)
- 計(jì)數(shù)內(nèi)部時(shí)鐘,即定時(shí)器模式
- 計(jì)數(shù)外部脈沖,即計(jì)數(shù)器模式
4.2 輸出比較
- PWM輸出
- 電平翻轉(zhuǎn)
- 單脈沖輸出
- 強(qiáng)制輸出
4.3 輸入捕獲
- 捕獲時(shí)保存定時(shí)器的當(dāng)前計(jì)數(shù)值
- 捕獲時(shí),可選擇觸發(fā)捕獲中斷
- 觸發(fā)捕獲的信號(hào)邊沿類型可選擇(上升沿,下降沿,雙邊沿)
5 HAL庫(kù)的定時(shí)器設(shè)計(jì)
5.1 定時(shí)器句柄結(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 定時(shí)器的定時(shí)/計(jì)數(shù)功能
6.1 時(shí)基單元
①預(yù)分頻模塊
- 預(yù)分頻計(jì)數(shù)器:對(duì)預(yù)分頻時(shí)鐘CK_PSC進(jìn)行分頻
- 預(yù)分頻寄存器:TIMx_PSC:設(shè)置預(yù)分頻系數(shù)PSC
- 作用1:擴(kuò)大定時(shí)器的定時(shí)范圍
- 作用2:獲取精確的計(jì)數(shù)時(shí)鐘
預(yù)分頻模塊工作原理: 定時(shí)器啟動(dòng)后,預(yù)分頻計(jì)數(shù)器的初值為0,預(yù)分頻時(shí)鐘CK_PSC每來(lái)一個(gè)時(shí)鐘,預(yù)分頻計(jì)數(shù)器的值就加1。當(dāng)計(jì)數(shù)值等于預(yù)分頻寄存器所設(shè)定的預(yù)分頻系數(shù)PSC時(shí),預(yù)分頻計(jì)數(shù)器的值將清零,開(kāi)始下一輪計(jì)數(shù)。
預(yù)分頻時(shí)序圖:
假設(shè)預(yù)分頻系數(shù)PSC=3,預(yù)分頻計(jì)數(shù)器從0計(jì)數(shù)到PSC實(shí)際計(jì)數(shù)值為PSC+1,也就是進(jìn)行了四分頻。
②計(jì)數(shù)模塊
- 核心計(jì)數(shù)器:對(duì)計(jì)數(shù)時(shí)鐘CK_CNT進(jìn)行二次計(jì)數(shù)
- 計(jì)數(shù)器寄存器:TIMx_CNT:存放核心計(jì)數(shù)器運(yùn)行時(shí)的當(dāng)前計(jì)數(shù)值
③自動(dòng)重載模塊
- 自動(dòng)重載模塊由自動(dòng)重載寄存器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=ARR | CNT=0 |
遞減計(jì)數(shù) | CNT=0 | CNT=ARR |
中心對(duì)齊計(jì)數(shù) | CNT=ARR-1CNT=1 | CNT=ARRCNT=0 |
6.2 定時(shí)器時(shí)序圖
①定時(shí)時(shí)間公式
②相關(guān)寄存器
- 預(yù)分頻寄存器TIMx_PSC: 設(shè)置預(yù)分頻系數(shù),將預(yù)分頻時(shí)鐘(CK_PSC)進(jìn)行1~65536之間的任意值分頻,得到計(jì)數(shù)時(shí)鐘(CK_CNT)。
- 計(jì)數(shù)器寄存器TIMx_CNT : 存放核心計(jì)數(shù)器運(yùn)行時(shí)的當(dāng)前計(jì)數(shù)值,便于用戶實(shí)時(shí)掌握核心計(jì)數(shù)器的當(dāng)前計(jì)數(shù)值。芯片復(fù)位后,默認(rèn)值為0。
- 自動(dòng)重載寄存器TIMx_ARR: 為計(jì)數(shù)器設(shè)置計(jì)數(shù)邊界或重載值。比如計(jì)數(shù)器遞增計(jì)數(shù)時(shí),記到多少發(fā)生溢出;遞減計(jì)數(shù)時(shí),從多少開(kāi)始往下計(jì)數(shù)。
6.3 外部脈沖計(jì)數(shù)
6.4 數(shù)據(jù)類型和接口函數(shù)
成員變量:
成員變量ClockDivision的取值范圍:
TIM_CLOCKDIVISION_DIV1 | 對(duì)定時(shí)器時(shí)鐘TIM_CLK進(jìn)行1分頻 |
---|---|
TIM_CLOCKDIVISION_DIV2 | 對(duì)定時(shí)器時(shí)鐘TIM_CLK進(jìn)行2分頻 |
TIM_CLOCKDIVISION_DIV4 | 對(duì)定時(shí)器時(shí)鐘TIM_CLK進(jìn)行4分頻 |
成員變量CounterMode的取值范圍
TIM_COUNTERMODE_UP | 遞增計(jì)數(shù)模式 |
---|---|
TIM_COUNTERMODE_DOWN | 遞減計(jì)數(shù)模式 |
TIM_COUNTERMODE_CENTERALIGNED1 | 中心對(duì)齊計(jì)數(shù)模式1 |
TIM_COUNTERMODE_CENTERALIGNED2 | 中心對(duì)齊計(jì)數(shù)模式2 |
TIM_COUNTERMODE_CENTERALIGNED3 | 中心對(duì)齊計(jì)數(shù)模式3 |
成員變量AutoReloadPreload的取值范圍
TIM_AUTORELOAD_PRELOAD_DISABLE | 預(yù)裝載功能關(guān)閉 |
---|---|
TIM_AUTORELOAD_PRELOAD_ENABLE | 預(yù)裝載功能開(kāi)啟 |
- 用于設(shè)置自動(dòng)重載寄存器TIMx_ARR的預(yù)裝載功能,即自動(dòng)重裝寄存器的內(nèi)容是更新事件產(chǎn)生時(shí)寫(xiě)入有效,還是立即寫(xiě)入有效;
- 預(yù)裝載功能在多個(gè)定時(shí)器同時(shí)輸出信號(hào)時(shí)比較有用,可以確保多個(gè)定時(shí)器的輸出信號(hào)在同一個(gè)時(shí)刻變化,實(shí)現(xiàn)同步輸出;
- 單個(gè)定時(shí)器輸出時(shí),一般不開(kāi)啟預(yù)裝載功能。
接口函數(shù):
時(shí)基單元初始化函數(shù):
HAL_TIM_Base_Init
函數(shù)原型 HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) 功能描述 按照定時(shí)器句柄中指定的參數(shù)初始化定時(shí)器時(shí)基單元 入口參數(shù) htim:定時(shí)器句柄的地址 返回值 HAL狀態(tài)值 注意事項(xiàng) 1. 該函數(shù)將調(diào)用MCU底層初始化函數(shù)HAL_TIM_Base_MspInit完成引腳、時(shí)鐘和中斷的設(shè)置2. 該函數(shù)由CubeMX自動(dòng)生成 輪詢模式啟動(dòng)函數(shù):
HAL_TIM_Base_Start
函數(shù)原型 HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim) 功能描述 在輪詢方式下啟動(dòng)定時(shí)器運(yùn)行 入口參數(shù) htim:定時(shí)器句柄的地址 返回值 HAL狀態(tài)值 注意事項(xiàng) 1. 該函數(shù)在定時(shí)器初始化完成之后調(diào)用2. 函數(shù)需要由用戶調(diào)用,用于輪詢方式下啟動(dòng)定時(shí)器運(yùn)行 中斷模式啟動(dòng)函數(shù):
HAL_TIM_Base_Start_IT
函數(shù)原型 HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) 功能描述 使能定時(shí)器的更新中斷,并啟動(dòng)定時(shí)器運(yùn)行 入口參數(shù) htim:定時(shí)器句柄的地址 返回值 HAL狀態(tài)值 注意事項(xiàng) 1. 該函數(shù)在定時(shí)器初始化完成之后調(diào)用2. 函數(shù)需要由用戶調(diào)用,用于使能定時(shí)器的更新中斷,并啟動(dòng)定時(shí)器運(yùn)行3. 啟動(dòng)前需要調(diào)用宏函數(shù) __HAL_TIM_CLEAR_IT 來(lái)清除更新中斷標(biāo)志 定時(shí)器中斷通用處理函數(shù)
HAL_TIM_IRQHandler
函數(shù)原型 void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) 功能描述 作為所有定時(shí)器中斷發(fā)生后的通用處理函數(shù) 入口參數(shù) htim:定時(shí)器句柄的地址 返回值 無(wú) 注意事項(xiàng) 1. 函數(shù)內(nèi)部先判斷中斷類型,并清除對(duì)應(yīng)的中斷標(biāo)志,最后調(diào)用回調(diào)函數(shù)完成中斷處理2. 該函數(shù)由CubeMX自動(dòng)生成 定時(shí)器更新中斷回調(diào)函數(shù)
HAL_TIM_PeriodElapsedCallback
函數(shù)原型 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 功能描述 回調(diào)函數(shù),用于處理所有定時(shí)器的更新中斷,用戶在該函數(shù)內(nèi)編寫(xiě)實(shí)際的任務(wù)處理程序 入口參數(shù) htim:定時(shí)器句柄的地址 返回值 無(wú) 注意事項(xiàng) 1.該函數(shù)由定時(shí)器中斷通用處理函數(shù)HAL_TIM_IRQHandler調(diào)用,完成所有定時(shí)器的更新中斷的任務(wù)處理2.函數(shù)內(nèi)部需要根據(jù)定時(shí)器句柄的實(shí)例來(lái)判斷是哪一個(gè)定時(shí)器產(chǎn)生的本次更新中斷3.函數(shù)由用戶根據(jù)具體的處理任務(wù)編寫(xiě) 計(jì)數(shù)值讀取函數(shù)
__HAL_TIM_GET_COUNTER
#define __HAL_TIM_GET_COUNTER(__HANDLE__) ((__HANDLE__)- >Instance- >CNT)
__HANDLE__
:定時(shí)器句柄的地址該函數(shù)通過(guò)直接訪問(wèn)計(jì)數(shù)器寄存器TIMx_CNT來(lái)獲取計(jì)數(shù)器的當(dāng)前計(jì)數(shù)值。
定時(shí)器中斷標(biāo)志清除函數(shù)
__HAL_TIM_CLEAR_IT
#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)- >Instance- >SR = ~(__INTERRUPT__))
__HANDLE__
:定時(shí)器句柄的地址__INTERRUPT__
:定時(shí)器中斷標(biāo)志
任務(wù)實(shí)踐1
基于STM32F103C8T6,開(kāi)發(fā)板原理圖
利用開(kāi)發(fā)板上的按鍵KEY2來(lái)觸發(fā)外部脈沖,按鍵每按下一次,就利用PA1引腳發(fā)送一個(gè)周期2ms左右的脈沖,送到定時(shí)器2的外部觸發(fā)引腳ETR(PA0)進(jìn)行計(jì)數(shù),并將計(jì)數(shù)結(jié)果通過(guò)串口發(fā)送到PC上顯示。
注:本任務(wù)例程使用的開(kāi)發(fā)板,KEY2與PA5相連接。KEY2原理圖如下:
使用按鍵時(shí),需要設(shè)置PA5為輸入上拉模式,這樣在KEY2沒(méi)有按下時(shí),PA5可以讀取到高電平,KEY2按下時(shí)PA5可以讀取到低電平。
配置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); }
配置定時(shí)器2時(shí)鐘源為外部觸發(fā)引腳ETR2,自動(dòng)重載寄存器ARR配置為一個(gè)相對(duì)較大的計(jì)數(shù),防止溢出。外部脈沖信號(hào)采用默認(rèn)配置:不使用濾波,不進(jìn)行脈沖信號(hào)反相,不進(jìn)行脈沖信號(hào)分頻。
上述操作在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
生成如下代碼完成初始化定時(shí)器,并在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
完成引腳初始化。配置串口外設(shè)USART1,選擇異步模式,無(wú)硬件流控。
上述操作在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 */ } }
程序編寫(xiě)
使用串口輸出,需要在Keil的Options中勾選Use MicroLIB.
在main.c中重定義printf
和scanf
函數(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ì)電子時(shí)鐘,從00:00:00開(kāi)始計(jì)時(shí),并將計(jì)時(shí)信息通過(guò)串口UART1發(fā)送到PC進(jìn)行顯示。
配置定時(shí)器1產(chǎn)生1s的更新中斷。計(jì)算PSC和ARR的值,將T=1s,TIM_CLK=8000000Hz帶入公式
得可取值PSC=1999,ARR=3999.
在CubeMX中使能TIM1,采用內(nèi)部時(shí)鐘 (8MHz) ,設(shè)置PSC和ARR值,并在嵌套向量中斷控制器NVIC設(shè)置中使能TIM1的更新中斷。
上述操作在tim.c
中生成TIM1初始化函數(shù),并在main.c
中調(diào)用配置USART1串口輸出,生成代碼后應(yīng)在工程中重定向
printf
和scanf
函數(shù),方法同任務(wù)實(shí)踐1,這部分不再贅述。編寫(xiě)代碼
在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)志,避免定時(shí)器一啟動(dòng)就進(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 */
編寫(xiě)定時(shí)器更新中斷回調(diào)函數(shù)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim- >Instance == TIM1) // 判斷時(shí)鐘源 { 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; } } } } }
-
mcu
+關(guān)注
關(guān)注
146文章
17149瀏覽量
351213 -
STM32
+關(guān)注
關(guān)注
2270文章
10900瀏覽量
356046 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2256瀏覽量
94575 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3248瀏覽量
114818 -
脈沖信號(hào)
+關(guān)注
關(guān)注
6文章
399瀏覽量
36973
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論