STM32F1 的通用定時(shí)器是一個(gè)通過可編程預(yù)分頻器(PSC,16位,1~65535)驅(qū)動的 16 位自動裝載計(jì)數(shù)器(CNT)構(gòu)成。STM32 的通用定時(shí)器可以被用于:測量輸入信號的脈沖長度(輸入捕獲)或者產(chǎn)生輸出波形(輸出比較和 PWM)等。 使用定時(shí)器預(yù)分頻器和 RCC 時(shí)鐘控制器預(yù)分頻器,脈沖長度和波形周期可以在幾個(gè)微秒到幾個(gè)毫秒間調(diào)整。定時(shí)器相關(guān)的庫函數(shù)主要集中在固件庫文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件中。
(1)使能定時(shí)器時(shí)鐘(以定時(shí)器3為例)
void TIM3_Int_Init(u16 arr,u16 psc) //初始化函數(shù)保留重加載值arr和與分頻系數(shù)psc兩個(gè)入口參數(shù)
{
}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時(shí)鐘使能
其中APB1和APB2中的定義如下:
/** @defgroup APB1_peripheral
* @{
*/
#define RCC_APB1Periph_TIM2 ((uint32_t)0x00000001)
#define RCC_APB1Periph_TIM3 ((uint32_t)0x00000002)
#define RCC_APB1Periph_TIM4 ((uint32_t)0x00000004)
#define RCC_APB1Periph_TIM5 ((uint32_t)0x00000008)
#define RCC_APB1Periph_TIM6 ((uint32_t)0x00000010)
#define RCC_APB1Periph_TIM7 ((uint32_t)0x00000020)
#define RCC_APB1Periph_TIM12 ((uint32_t)0x00000040)
#define RCC_APB1Periph_TIM13 ((uint32_t)0x00000080)
#define RCC_APB1Periph_TIM14 ((uint32_t)0x00000100)
#define RCC_APB1Periph_WWDG ((uint32_t)0x00000800)
#define RCC_APB1Periph_SPI2 ((uint32_t)0x00004000)
#define RCC_APB1Periph_SPI3 ((uint32_t)0x00008000)
#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000)
#define RCC_APB1Periph_USART3 ((uint32_t)0x00040000)
#define RCC_APB1Periph_UART4 ((uint32_t)0x00080000)
#define RCC_APB1Periph_UART5 ((uint32_t)0x00100000)
#define RCC_APB1Periph_I2C1 ((uint32_t)0x00200000)
#define RCC_APB1Periph_I2C2 ((uint32_t)0x00400000)
#define RCC_APB1Periph_USB ((uint32_t)0x00800000)
#define RCC_APB1Periph_CAN1 ((uint32_t)0x02000000)
#define RCC_APB1Periph_CAN2 ((uint32_t)0x04000000)
#define RCC_APB1Periph_BKP ((uint32_t)0x08000000)
#define RCC_APB1Periph_PWR ((uint32_t)0x10000000)
#define RCC_APB1Periph_DAC ((uint32_t)0x20000000)
#define RCC_APB1Periph_CEC ((uint32_t)0x40000000)
#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0x81013600) == 0x00) && ((PERIPH) != 0x00))
/**
* @}
*/
/** @defgroup APB2_peripheral
* @{
*/
#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2 ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1 ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3 ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15 ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16 ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17 ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9 ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10 ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11 ((uint32_t)0x00200000)
#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))
/**
* @}
*/
(2)初始化定時(shí)器,配置ARR,PSC
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim,參數(shù)有TIM_CKD_DIV1,TIM_CKD_DIV2,TIM_CKD_DIV4
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式,向下計(jì)數(shù)為TIM_CounterMode_Down
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
關(guān)于中斷時(shí)間的計(jì)算:
Tout(溢出時(shí)間)=(ARR+1)(PSC+1) / fclk
其中,ARR為重裝載值,PSC為預(yù)分配系數(shù),fclk為系統(tǒng)時(shí)鐘頻率。 fclk / (PSC+1)其實(shí)得到的是分頻后的頻率,倒數(shù)后變成周期。
系統(tǒng)初始化的時(shí)候在默認(rèn)的系統(tǒng)初始化函數(shù) SystemInit 函數(shù)里面已經(jīng)初始化 APB1 的時(shí)鐘為 2 分頻,所以 APB1 的時(shí)鐘為 36M,而從 STM32 的內(nèi)部時(shí)鐘樹圖得知:當(dāng) APB1 的時(shí)鐘分頻數(shù)為 1 的時(shí)候,TIM2~7 的時(shí)鐘為 APB1 的時(shí)鐘,而如果 APB1 的時(shí)鐘分頻數(shù)不為 1,那么 TIM2~7 的時(shí)鐘頻率將為 APB1 時(shí)鐘的兩倍。
TIM_CounterMode 的作用:
http://blog.sina.com.cn/s/blog_76c545390100ovfj.html
(3)開啟定時(shí)器中斷,配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //在主函數(shù)main()中設(shè)置分組,設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
NVIC_InitTypeDef NVIC_InitStructure;
//中斷優(yōu)先級NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能指定的TIM3中斷,允許更新中斷
中斷配置函數(shù) TIM_ITConfig的說明:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
//其中第二個(gè)參數(shù)很重要,定義如下
#define TIM_IT_Update ((uint16_t)0x0001)//最常用,更新中斷,計(jì)數(shù)器向上溢出/向下溢出,計(jì)數(shù)器初始化(通過軟件或者內(nèi)部/外部觸發(fā))
#define TIM_IT_CC1 ((uint16_t)0x0002)
#define TIM_IT_CC2 ((uint16_t)0x0004)
#define TIM_IT_CC3 ((uint16_t)0x0008)
#define TIM_IT_CC4 ((uint16_t)0x0010)//都是捕獲/比較中斷,貌似都是平等的,即輸入捕獲,輸出比較
#define TIM_IT_COM ((uint16_t)0x0020)
#define TIM_IT_Trigger ((uint16_t)0x0040)//觸發(fā)事件(計(jì)數(shù)器啟動、停止、初始化或者由內(nèi)部/外部觸發(fā)計(jì)數(shù))
#define TIM_IT_Break ((uint16_t)0x0080)
(4)使能定時(shí)器
TIM_Cmd(TIM3, ENABLE); //使能TIM3
至此,初始化完成。
(5)編寫中斷服務(wù)函數(shù)
void TIM3_IRQHandler(void) //TIM3中斷
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查TIM3更新中斷發(fā)生與否
{
//各種中斷服務(wù)函數(shù)內(nèi)容
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIM3更新中斷標(biāo)志
}
}