| 九九的STM32筆記(一)TIM模塊定時(shí)器向上溢出 & 輸出比較 | 回復數:14,點(diǎn)擊數:3558 |
【樓主位】 jjldc 九九![]() 積分:1251 派別: 等級:------ 來(lái)自:寧波-武漢-深圳 | 九九的STM32筆記(一)TIM模塊定時(shí)器向上溢出 & 輸出比較 首先我們必須肯定ST公司的實(shí)力,也承認STM32的確是一款非常不錯的Cortex-M3核單片機,但是,他的手冊實(shí)在是讓人覺(jué)得無(wú)法理解,尤其是其中的TIM模塊,沒(méi)有條理可言,看了兩天幾乎還是不知所云,讓人很是郁悶。同時(shí)配套的固件庫的說(shuō)明也很難和手冊上的寄存器對應起來(lái),研究起來(lái)非常費勁!功能強大倒是真的,但至少也應該配套一個(gè)讓人看的明白的說(shuō)明吧~~ 兩天時(shí)間研究了STM32定時(shí)器的最最基礎的部分,把定時(shí)器最基礎的兩個(gè)功能實(shí)現了,余下的功能有待繼續學(xué)習。 首先有一點(diǎn)需要注意:FWLib固件庫目前的最新版應該是V2.0.x,V1.0.x版本固件庫中,TIM1模塊被獨立出來(lái),調用的函數與其他定時(shí)器不同;在V2.0系列版本中,取消了TIM1.h,所有的TIM模塊統一調用TIM.h即可。網(wǎng)絡(luò )上流傳的各種代碼有許多是基于v1版本的固件庫,在移植到v2版本固件庫時(shí),需要做些修改。本文的所有程序都是基于V2.0固件庫。 以下是定時(shí)器向上溢出示例代碼: C語(yǔ)言: TIM1模塊產(chǎn)生向上溢出事件 //Step1.時(shí)鐘設置:?jiǎn)?dòng)TIM1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //Step2.中斷NVIC設置:允許中斷,設置優(yōu)先級 NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQChannel; //更新事件 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優(yōu)先級0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優(yōu)先級1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //允許中斷 NVIC_Init(&NVIC_InitStructure); //寫(xiě)入設置 //Step3.TIM1模塊設置 void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; //TIM1 使用內部時(shí)鐘 //TIM_InternalClockConfig(TIM1); //TIM1基本設置 //設置預分頻器分頻系數71,即APB2=72M, TIM1_CLK=72/72=1MHz //TIM_Period(TIM1_ARR)=1000,計數器向上計數到1000后產(chǎn)生更新事件,計數值歸零 //向上計數模式 //TIM_RepetitionCounter(TIM1_RCR)=0,每次向上溢出都產(chǎn)生更新事件 TIM_BaseInitStructure.TIM_Period = 1000; TIM_BaseInitStructure.TIM_Prescaler = 71; TIM_BaseInitStructure.TIM_ClockDivision = 0; TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_BaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure); //清中斷,以免一啟用中斷后立即產(chǎn)生中斷 TIM_ClearFlag(TIM1, TIM_FLAG_Update); //使能TIM1中斷源 TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //TIM1總開(kāi)關(guān):開(kāi)啟 TIM_Cmd(TIM1, ENABLE); } //Step4.中斷服務(wù)子程序: void TIM1_UP_IRQHandler(void) { GPIOC->ODR ^= (1<<4); //閃燈 TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update); //清中斷 } 下面是輸出比較功能實(shí)現TIM1_CH1管腳輸出指定頻率的脈沖: C語(yǔ)言: TIM1模塊實(shí)現輸出比較,自動(dòng)翻轉并觸發(fā)中斷 //Step1.啟動(dòng)TIM1,同時(shí)還要注意給相應功能管腳啟動(dòng)時(shí)鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Step2. PA.8口設置為T(mén)IM1的OC1輸出口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //Step3.使能TIM1的輸出比較匹配中斷 NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //Step4. TIM模塊設置 void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; //TIM1基本計數器設置 TIM_BaseInitStructure.TIM_Period = 0xffff; //這里必須是65535 TIM_BaseInitStructure.TIM_Prescaler = 71; //預分頻71,即72分頻,得1M TIM_BaseInitStructure.TIM_ClockDivision = 0; TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_BaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure); //TIM1_OC1模塊設置 TIM_OCStructInit(& TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //管腳輸出模式:翻轉 TIM_OCInitStructure.TIM_Pulse = 2000; //翻轉周期:2000個(gè)脈沖 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能TIM1_CH1通道 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出為正邏輯 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //寫(xiě)入配置 //清中斷 TIM_ClearFlag(TIM1, TIM_FLAG_CC1); //TIM1中斷源設置,開(kāi)啟相應通道的捕捉比較中斷 TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); //TIM1開(kāi)啟 TIM_Cmd(TIM1, ENABLE); //通道輸出使能 TIM_CtrlPWMOutputs(TIM1, ENABLE); } Step5.中斷服務(wù)子程序 void TIM1_CC_IRQHandler(void) { u16 capture; if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET) { TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 ); capture = TIM_GetCapture1(TIM1); TIM_SetCompare1(TIM1, capture + 2000); //這里解釋下: //將TIM1_CCR1的值增加2000,使得下一個(gè)TIM事件也需要2000個(gè)脈沖, //另一種方式是清零脈沖計數器 //TIM_SetCounter(TIM2,0x0000); } } 關(guān)于TIM的操作,要注意的是STM32處理器因為低功耗的需要,各模塊需要分別獨立開(kāi)啟時(shí)鐘,所以,一定不要忘記給用到的模塊和管腳使能時(shí)鐘,因為這個(gè)原因,浪費了我好多時(shí)間阿~~! 下一回,將介紹TIM模塊PWM的功能! 我的博客中本文的地址,內有語(yǔ)法高亮的代碼,方便閱讀 本貼被 jjldc 編輯過(guò),最后修改時(shí)間:2009-02-18,21:52:03. | ||
![]() |
![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【1樓】 lljyes 積分:312 派別: 等級:------ 來(lái)自: | 今天對比了一下,固件庫手冊跟固件庫2.0里面的例子的TIM使用,對寄存器的定義對不上號!對TIM無(wú)從下手呀! 本貼被 lljyes 編輯過(guò),最后修改時(shí)間:2009-03-04,14:02:17. | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【2樓】 hl1200aa 積分:1117 派別: 等級:------ 來(lái)自: | /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler =200; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* Output Compare Toggle Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_Channel = TIM_Channel_1; TIM_OCInitStructure.TIM_Pulse =1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInit(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); 這個(gè)例程里面怎么調整TIM_OCInitStructure.TIM_Pulse都沒(méi)有用,LED閃爍的速度都一樣,郁悶ing,不知道哪位高手能指點(diǎn)下。 本貼被 hl1200aa 編輯過(guò),最后修改時(shí)間:2009-03-15,22:37:51. | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【3樓】 xxpeng 積分:19 派別: 等級:------ 來(lái)自: | 回復2樓,有可能是沒(méi)有開(kāi)啟比較中斷,這樣每次計到65535才產(chǎn)生中斷一次,可以改變65535看地否能改變燈閃的頻率 本貼被 xxpeng 編輯過(guò),最后修改時(shí)間:2009-03-18,07:00:31. | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【4樓】 xaolong 小龍 積分:7 派別: 等級:------ 來(lái)自:北京市 | 2樓的,我的也是這個(gè)情況,弄好了沒(méi)啊,給大家說(shuō)一下啊。 | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
【5樓】 xiaorunyi 蕭潤逸![]() 積分:929 派別: 等級:------ 來(lái)自: | TIM_BaseInitStructure.TIM_Period = 1000; 這個(gè)在計算時(shí)是否要加1,或在設置時(shí)是否要減1? 數值大影響不大,但是數值小了就影響大了 | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【6樓】 lgkuang 積分:2 派別: 等級:------ 來(lái)自: | Step5.中斷服務(wù)子程序 void TIM1_CC_IRQHandler(void) { u16 capture; if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET) { TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 ); capture = TIM_GetCapture1(TIM1); TIM_SetCompare1(TIM1, capture + 2000); //這里解釋下: //將TIM1_CCR1的值增加2000,使得下一個(gè)TIM事件也需要2000個(gè)脈沖, //另一種方式是清零脈沖計數器 //TIM_SetCounter(TIM2,0x0000); } } 在中斷服務(wù)子程序的 TIM_SetCompare1(TIM1, capture + 2000); 要改變相應的數值 才能夠改變中斷的頻率 | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【7樓】 myworkmail 積分:651 派別: 等級:------ 來(lái)自: | MARK | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
【8樓】 zhang_mike2000 ![]() 積分:694 派別: 等級:------ 來(lái)自:電子魯迅 | 【樓主位】 jjldc 九九 各模塊需要分別獨立開(kāi)啟時(shí)鐘,所以,一定不要忘記給用到的模塊和管腳使能時(shí)鐘,因為這個(gè)原因,浪費了我好多時(shí)間阿~~! ----------------------------------------------------------------------- 用下面這個(gè)指令是不是就沒(méi)有這個(gè)麻煩了? RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, ENABLE); | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【9樓】 yaowang_hao 積分:64 派別: 等級:------ 來(lái)自: | 回復【樓主位】jjldc 九九 ----------------------------------------------------------------------- 我按您的程序做試驗,設置:TIM_BaseInitStructure.TIM_Period = 1000; TIM_BaseInitStructure.TIM_Prescaler = 71000;想實(shí)現1S延時(shí),可是發(fā)現不準啊,您能給解釋一下不? | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【10樓】 huangtonggao 積分:34 派別: 等級:------ 來(lái)自: | mark | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【11樓】 linfeng286 積分:1086 派別: 等級:------ 來(lái)自: | MARK | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【12樓】 bingobravo 積分:9 派別: 等級:------ 來(lái)自: | 問(wèn)下樓主:為什么說(shuō) “TIM_BaseInitStructure.TIM_Period = 0xffff;” 這里必須是65535 ??? | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【13樓】 hui3700 積分:38 派別: 等級:------ 來(lái)自: | mark下 | ||
![]() |
![]() ![]() ![]() ![]() | ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
| 【14樓】 bjj9217 積分:866 派別: 等級:------ 來(lái)自: | mark |
聯(lián)系客服