比賽終于結束了,好幾天沒有更新了,今天重新開始!進入深入學習TIM!
定時器,中斷這兩樣東西是學習一個MCU必須掌握的,也是非常有用的!
STM32的TIM一般有高級定時器TIM1,(TIM8只有在互聯性產品有),普通定時器TIM2,TIM3,TIM4,(TIM5,TIM6,TIM7有點設備中沒有);今天就只介紹普通定時器,因為高級定時器我還不會!每一個普通定時器都有4路通道!

我們先看看這個邏輯圖吧!我們今天先討論討論定時器的問題!我用紅色筆標過的路線就是定時器的工作路線,時鐘有內部時鐘產生,到PSC哪里進行分頻處理,然后CNT進行計數,上面還有一個自動重裝載寄存器APP。

這個是分頻器的工作原理,我們可以看,分頻器設定之前分頻系數為1[1],后面的[2][3][4]分頻系數為2,分頻系數改變后,計數周期也跟著改變了;同時預分頻設置生效時,他還會產生一個中斷信號,這個中斷信號不要管他,一個系統時鐘周期后會自動消失,跟I2C的差不多!

這個是計數過程,上面說過了,計數跟分頻后的周期有關;當計數達到裝載的數值之后,系統會產生一個三個信號,其中溢出信號和更新事件一個時鐘周期后會自動消失,而這時候觸發了更新中斷標志位UIF,我們可以用這個UPDATE來做定時器的中斷標志信號!
TIM_ITConfig(TIM2, TIM_IT_UPDATE, ENABLE);
另外還有4個中斷,我們知道PWM的產生把,他就跟PWM的產生有著血緣關系!

如果我們在OC模式選擇的時候,TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;選擇了Timing那么我們就可以做定時器了。
有時候我們會發現當UPdate中斷信號產生時,其他四個中斷信號也產生,什么原因呢?因為我們在設置tim.TIM_Period = period;時,period時間太短,就錯覺的以為他們是一群產生中斷信號的!來我們分析下:
假設分頻因子為71,即72分頻,PCLK為72M,我們設置的周期為1000;那么我們產生定時器的Upddate信號頻率為1000Hz,周期為1ms,假設我們這里設置的CCR1 = 100;CCR2 = 500;CCR3 = 600;CCR4 = 900;
那么update信號產生后0.1ms產生CCR1的中斷信號,0.5ms后產生CCR2的中斷信號,0.6ms后產生CCR3的中斷信號,這些中斷標志位是:
~~~
#define TIM_FLAG_Update ? ? ? ? ? ? ? ? ? ?((uint16_t)0x0001)
#define TIM_FLAG_CC1 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0002)
#define TIM_FLAG_CC2 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0004)
#define TIM_FLAG_CC3 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0008)
#define TIM_FLAG_CC4 ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0010)
#define TIM_FLAG_COM ? ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0020)
#define TIM_FLAG_Trigger ? ? ? ? ? ? ? ? ? ((uint16_t)0x0040)
#define TIM_FLAG_Break ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0080)
#define TIM_FLAG_CC1OF ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0200)
#define TIM_FLAG_CC2OF ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0400)
#define TIM_FLAG_CC3OF ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x0800)
#define TIM_FLAG_CC4OF ? ? ? ? ? ? ? ? ? ? ((uint16_t)0x1000)
~~~
[OF為溢出]后面做研究!
對于這些CCR1在定時方面的應用我還沒有想出什么好的點子,但是他確實存在,如果想驗證的話,我們可以把周期設置長一點,比如設置為1s,然后通過設置CCR的值,來看看效果,呵呵,不過這是不容易實現的,因為CCRx 最大為0xffff = 65535跟72M比比,還能說什么?好吧,誰有什么好辦法,可以跟我說下!
~~~
void tim_init(u32 period,u32 psc)
{
TIM_TimeBaseInitTypeDef tim;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
tim.TIM_Period = period;
tim.TIM_Prescaler = psc;
tim.TIM_ClockDivision = 0;
tim.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &tim);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 1*period/4;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Pulse = 2*period/4;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Pulse = 3*period/4;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4, ENABLE);
TIM_Cmd(TIM2,ENABLE);
/* Enable the TIM2 global 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);
}
~~~
~~~
void TIM2_IRQHandler(void)
{
static u32 cc2 = 0,cc3 = 0,cc4 = 0,cc5 = 0;
static u8 flag2 = 0,flag3 = 0,flag4 = 0,flag5 = 0;
u32 capture;
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC2) == SET)
{
cc2 ++;
if(cc2 > 1000)
{
flag2 = ~flag2;
if(flag2) led_on(4);
else led_off(4);
cc2 = 0;
}
TIM_ClearFlag(TIM2,TIM_FLAG_CC2);
capture = TIM_GetCapture2(TIM2);
TIM_SetCompare2(TIM2, capture + 255);
}
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC3) == SET)
{
cc3 ++;
if(cc3 > 1000)
{
flag3 = ~flag3;
if(flag3) led_on(5);
else led_off(5);
cc3 = 0;
}
TIM_ClearFlag(TIM2,TIM_FLAG_CC3);
capture = TIM_GetCapture3(TIM2);
TIM_SetCompare3(TIM2, capture + 500);
}
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC4) == SET)
{
cc4 ++;
if(cc4 > 1000)
{
flag4 = ~flag4;
if(flag4) led_on(6);
else led_off(6);
cc4 = 0;
}
TIM_ClearFlag(TIM2,TIM_FLAG_CC4);
capture = TIM_GetCapture4(TIM2);
TIM_SetCompare4(TIM2, capture + 725);
}
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) == SET)
{
cc5 ++;
if(cc5 > 1000)
{
flag5 = ~flag5;
if(flag5) led_on(7);
else led_off(7);
cc5 = 0;
}
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
}
}
~~~
藍橋杯-嵌入式交流群?147520657
- 前言
- 【菜鳥入門】stm32的第一個程序--LED
- 【菜鳥入門】stm32 之 掃描按鍵
- 【菜鳥入門】stm32 之 中斷按鍵
- 【菜鳥入門】stm32 之 USART
- 【菜鳥入門】stm32 之 iic
- 【菜鳥入門】stm32 之 eeprom
- 【菜鳥入門】stm32 之 pwm
- 【菜鳥入門】stm32 之 ADC 模數轉換
- 【菜鳥入門】stm32 之 實時時鐘
- 【菜鳥入門】stm32 之 DMA
- 【菜鳥入門】stm32 之 DAC
- 【STM庫應用】stm32 之 USART
- 中斷源去抖辦法
- stm32 啟動代碼應用技巧
- 【STM庫應用】stm32 之 IIC應用
- 【STM庫應用】stm32 之 中斷按鍵初始化(注意事項)
- 關于結構體初始化
- 【STM庫應用】stm32 之 TIM (詳解一 通用定時器)
- 【STM庫應用】stm32 之 TIM (詳解二 脈沖寬度、周期測量)
- 【stm32庫應用】SD驅動移植(基于SDIO外設)
- SD卡fat文件系統移植
- stm32 DMA初始化選項研究
- stm32 靈活靜態存儲控制器(FSMC)(NORFLASH\PSRAM)
- 【stm32+uC/OS-II】ucosii移植簡單詳細步驟
- STM32 加入調試信息來調試代碼
- NRF24L01 無線通信模塊使用