1. 程式人生 > >stm32之定時器運用———呼吸燈

stm32之定時器運用———呼吸燈

呼吸燈原理

1.在類比電路中,呼吸燈的實現可以通過一個呈現正弦的電壓控制,這個電壓是連續變化的,所以肉眼看上去就是逐漸變暗,逐漸變亮。

2.而在數位電路中如何實現這種效果呢?就需要通過pwm,也就是脈衝寬度調製,將模擬量轉換為數字量。只要能夠用連續電壓控制的東西都是可以通過pwm方式來驅動,效果是一樣的。

3.

這裡寫圖片描述

上面一塊區域的面積等於對應下來的矩形的面積,當然,取得塊的間隔越小(即pwm的週期越小),效果越好。這時,如果週期定了,就可以通過改變佔空比來實現面積的改變,從而模擬出上面那張圖的電壓的連續變化。

注意:pwm波的高度是一定的,所以只能通過改變寬度(佔空比)來實現面積的改變

4.說明:觀察這張圖,會發現下面的pwm波是中心與上面的對齊(即pwm中心為高電平),然後左右擴充套件,每個波的週期還是一樣。當然這時可以的。但更多的是運用左對齊(起始為高電平),然後向右擴充套件直到面積到達要求。

5.stm32實現pwm輸出的原理:設點一個值為a,然後在設定一個重灌值b,b>a.開始計數,當計數值小於a時,輸出高電平,當計數值大於a時,輸出低電平,直到計數到b,到b後又重複來一遍。所以改變這個a就可以改變佔空比、

6.PWM 的輸出其實就是對外輸出脈寬可調(即佔空比調節)的方波訊號,訊號頻率是由自動重灌暫存器 ARR 的值決定,佔空比由比較暫存器 CCR 的值決定。其示意圖如圖 19.1.2 所示:

這裡寫圖片描述

從圖 19.1.2 中可以看到,PWM 輸出頻率是不變的,改變的是 CCR 暫存器內的值,此值的改變將導致 PWM 輸出訊號佔空比的改變。佔空比其實就是一個週期內高電平時間與週期的比值。PWM 輸出比較模式總共有 8 種,具體由暫存器 CCMRx 的位 OCxM[2:0]配置。我們這裡只講解最常用的兩種 PWM 輸出模式:PWM1 和 PWM2,PWM1 和 PWM2 這兩種模式用法差不多,區別之處就是輸出電平的極性不同。如圖 19.1.3 所示:

這裡寫圖片描述

pwm輸出配置步驟

其實 PWM 輸出和上一章一樣也是通用定時器的一個功能,因此還是要用到定時器的相關配置函式

1.因為pwm是由定時器輸出的,既然用到定時器,就先要使能定時器的時鐘:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//我們用的為tim14定時器

2.因為用到io作為輸出,所以要開啟io口的時鐘:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//注意:io口的外設均是掛在AHB1總線上的

3.通過看手冊,TIM14 的 CH1 通道對應的管腳是 PF9,而pf9有很多複用功能,所以要選擇pf9的輸出模式:通過函式:

void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource,
uint8_t GPIO_AF);//前兩個引數不說了。第三個引數為複用為哪種功能,這裡我們使用的是 TIM14 功能,所以引數為 GPIO_AF_TIM14

所以函式為:GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);//AF就是複用的意思

4.配置io口,同之前led時一樣,只不過引數有些變化:

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;//PF9 管腳模式配置為複用輸出
      GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度不變
      GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推完輸出不變
      GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上啦輸出不變
      GPIO_Init(GPIOF,&GPIO_InitStructure);

5.初始化定時器引數,包含自動重灌值,分頻係數,計數方式等.同前面使用定時器中斷

      TIM_TimeBaseInitStructure.TIM_Period = pre;//預裝值,這裡依然通過引數傳遞進來
      TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//預分頻係數
      TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//固定不變
      TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上計數
      TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStructure);

6.定時器基本的引數配置完了,但是還沒設定它為pwm輸出模式:
用到的函式為:

void TIM_OCxInit(TIM_TypeDef* TIMx,TIM_OCInitTypeDef* TIM_OCInitStruct);//

注意:我們知道每個通用定時器有多達 4 路 PWM 輸出通道(對於 TIM9-TIM14 最多有 2 路),所以TIM_OCxInit 函式名中的 x 值可以為 1/2/3/4。函式的第一個引數相信大家一看就清楚,是用來選擇定時器的。第二個引數是一個結構體指標變數:

typedef struct
{
uint16_t TIM_OCMode; //比較輸出模式
uint16_t TIM_OutputState; //比較輸出使能
uint16_t TIM_OutputNState; //比較互補輸出使能
uint32_t TIM_Pulse; //脈衝寬度
uint16_t TIM_OCPolarity; //輸出極性
uint16_t TIM_OCNPolarity; //互補比較輸出極性
uint16_t TIM_OCIdleState; //空閒狀態下比較輸出狀態
uint16_t TIM_OCNIdleState; //空閒狀態下比較輸出狀態
}

這裡我們比較常用的 PWM 模式所需的成員變數:
TIM_OCMode:比較輸出模式選擇,總共有 8 種,最常用的是 PWM1 和 PWM2。
TIM_OutputState:比較輸出使能,用來使能 PWM 輸出到 IO 口。
TIM_OCPolarity:輸出極性,用來設定輸出通道電平的極性,是高電平還是低電平。
結 構 體 內 其 他 的 成 員 變 量 TIM_OutputNState , TIM_OCNPolarity ,
TIM_OCIdleState 和 TIM_OCNIdleState 是高階定時器才用到的。

所以配置完為:

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;     
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM14,&TIM_OCInitStructure);

7.開啟定時器

TIM_Cmd(TIM14,ENABLE);

8.修改 TIMx_CCRx 的值控制佔空比(這一步寫在主函式中,因為要實時去改變佔空比).

其實經過前面幾個步驟的配置,PWM 已經開始輸出了,只是佔空比和頻率是固定的,例如本章要實現呼吸燈效果,那麼就需要調節 TIM14 通道 1 的佔空比,通過修改 TIM14_CCR1 值控制。調節佔空比函式是:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);//對 於 其 他 通 道 , 分 別 有 對 應 的 函 數 名 , 函 數 格 式 是 TIM_SetComparex(x=1/2/3/4)。

分析:第一個引數不說了,第二個引數是計數值。。注意:這個計數值一定要小於前面設定定時器時總的預裝載值(TIM_TimeBaseInitStructure.TIM_Period = pre);

程式碼:

pwm.c

#include "pwm.h"

void TIM14_PWM_Init(u16 pre,u16 psc)
{
      GPIO_InitTypeDef GPIO_InitStructure;
      TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      TIM_OCInitTypeDef TIM_OCInitStructure;


      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//´ٍ؟ھ¶¨ت±ئ÷µؤت±ضس
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//زٍخھسأµ½¶ث؟ع£¬ثùزشزھت¹ؤـ¶ث؟عت¼ت±ضس£¬ءيحâioµؤحâة趼تا¹ز½سشعAHB1×ـدكةدµؤ

          GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
          GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//ثظ¶ب
      GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//حئحئحىتن³ِ
      GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//ةدہ­
      GPIO_Init(GPIOF,&GPIO_InitStructure);//شع³ُت¼»¯ز»دآ

          TIM_TimeBaseInitStructure.TIM_Period = pre;//ةèضأ¶¨ت±ئ÷µؤضـئع£¬ز²¾حت£×¢زâ£؛صâہïخھ´«µؤ²خت‎
      TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//¶¨ت±ئ÷ش¤·ضئµدµت‎
          TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//ح¨³£²»ذق¸ؤثû£¬¹ج¶¨µؤ£¬ز»°مآج²¨µؤت±؛ٍسأ
      TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//دٍةد¼ئت‎£¬´سءم؟ھت¼¼ئت‎£¬¼ئت‎µ½ضط×°ضµ
      TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStructure);//³ُت¼»¯ز»دآ

          TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
          TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
        TIM_OC1Init(TIM14,&TIM_OCInitStructure);

        TIM_Cmd(TIM14,ENABLE);

}

mian.c

int main()
{
    u8 fx = 0;
    u32 i = 0;//ำรภดภผำ
    RCC_HSE_Config(8,336,2,7);
    Beep_Init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SysTick_Init(168);
    key_init();
    LED_Init();
    TIM14_PWM_Init(500-1,84-1);//2000hz,ึฦฺถจมห,0.5MS

    //while(1)
    //{
        //  if(fx==0)
            //{
                //  i++;
                //  if(i==300)
                //  {
                    //      fx=1;
                //  }
            //}

            //else
            //{
            //      i--;
                //if(i==0)
            //  {
                //      fx=0;
                //}
            //}
         // TIM_SetCompare1(TIM14,i);
            //delay_ms(10);
    //}


    /********the second code*****/
        while(1)
        {
           while(i<=300)
           {
              TIM_SetCompare1(TIM14,i);
              delay_ms(10);
              i++;
           }

           while(i!=0)
           {
              TIM_SetCompare1(TIM14,i);
              delay_ms(10);
              i--;
           }
      }
}

補充:
1.主函式中註釋程式碼是官方的程式碼,下面是我自己原創的程式碼。官方程式碼是引用了一個變數來判斷方向。

2.觀察主函式的程式碼,我們設定的定時器為0.5ms,意思就是pwm波的週期為0.5ms,而每次執行完TIM_SetCompare1(TIM14,i);波形(佔空比)就會改變,而後面寫的delay_ms(10);是為了維持這一個波形一段時間,反映在模擬訊號上就是電壓變化的很平緩,很慢,自然亮度的變化也就很緩慢自然。自然,這個延遲時間知道要大於你定時時間好幾倍吧-.-

擴充套件

試試用pwm輸出來控制板子上的蜂鳴器來實現控制他的聲音大小

提示:看電路圖發現beep連在pf9上,而pf9本來就是tim13的複用口。所以只需在這個程式碼基礎上修改定時器的標號為tim13即可

相關推薦

stm32定時運用———呼吸

呼吸燈原理 1.在類比電路中,呼吸燈的實現可以通過一個呈現正弦的電壓控制,這個電壓是連續變化的,所以肉眼看上去就是逐漸變暗,逐漸變亮。 2.而在數位電路中如何實現這種效果呢?就需要通過pwm,也就是脈衝寬度調製,將模擬量轉換為數字量。只要能夠用連續電壓控制的

STM32定時中斷控制LED閃爍

上篇部落格我們是用延時函式實現了LED的閃爍,今天我們使用STM32的定時器來使LED閃爍。 關於32的定時器的種類,今天我在這先不做過多的說明,有時間我會再另寫一篇部落格來專門介紹32的定時器。今天我們使用32的定時器3來產生中斷,以實現LED的閃爍。 今

STM32-自學筆記(9.SysTick定時控制LED閃爍,程式用到的庫函式介紹)

1.SysTick_CLKSourceConfig 函式原型:viod SysTick_CLKSourceConfig (u32 SysTick_CLKSource) 功能:選擇SysTick的時鐘源 引數:SysTick_CLKSource:SysTick時鐘源 引數:S

STM32-自學筆記(8.使用STM32的SysTick定時控制LED閃爍)

SysTick定時器,被稱為“系統節拍時鐘”。SysTick屬於ARM  Cortex-M3核心的一個內設,STM32也帶有SysTick定時器。 SysTick定時器的基本結構 SysTick工作原理: SysTick從時鐘源介面獲得時鐘驅動 從重灌暫存器將

STM32通用定時的基本定時功能實現閃爍

/*MAIN.C*/ /* Includes ------------------------------------------------------------------*/#inclu

STM32實戰3.定時控制LED閃爍(定時1)

#include "sys.h" #include "led.h" #include "delay.h" #include "TIM1.h" int main(void) { NVIC_Configuration(); LED_Init(); delay_init

定時/計數器0定時

.com 函數調用 wid 延時 mod main images .cn cnblogs /* 效果說明: 定時器中斷:通過單片機計數使程序執行 一秒中斷一次,中斷發生時高四位亮一秒,中斷發生後又回到主程序 */ #include <

STM32--TIM定時時鐘分割(疑難)

疑難 計數器 謝謝 term 比例 是什麽 tab 超過 定時 不太明白 (1) TIM_Perscaler來設置預分頻系數; (2) TIM_ClockDivision來設置時鐘分割(時鐘分頻因子); (3) TIM_Counte

11.按鍵驅動定時防抖(詳解)

pri pos long 超時時間 device queue pen fun cti 本節目標:   通過定時器來防止按鍵抖動,測試程序是使用上節的:阻塞操作的測試程序 1.如下圖所示,在沒有定時器防抖情況下,按鍵沒有穩定之前會多次進入中斷,使得輸出多個相同信息出來

(筆記)Linux內核學習(八)定時和時間管理

全局變量 define 結構 load 統計 object 一個 完成 溢出 一 內核中的時間觀念 內核在硬件的幫助下計算和管理時間。硬件為內核提供一個系統定時器用以計算流逝的時間。系 統定時器以某種頻率自行觸發,產生時鐘中斷,進入內核時鐘中斷處理程序中進行

java學習筆記定時

blog div this rgs date row demo sdf 時間 定時器 1 package pack01_timer; 2 3 import java.io.File; 4 import java.text.ParseException; 5 i

STM32-通用定時基本定時功能

數字 vision 實現 定義 還要 可能 輸出 給定 禁止 1. STM32的Timer簡介 STM32中一共有11個定時器,其中2個高級控制定時器,4個普通定時器和2個基本定時器,以及2個看門狗定時器和1個系統嘀嗒定時器。其中系統嘀嗒定時器是前文中所描述的Sys

Linux驅動定時在按鍵去抖中的應用

arc div 測試 完整 esc arm 是否 reg blog 機械按鍵在按下的過程中會出現抖動的情況,如下圖,這樣就會導致本來按下一次按鍵的過程會出現多次中斷,導致判斷出錯。在按鍵驅動程序中我們可以這麽做: 在按鍵驅動程序中我們可以這麽做來取消按鍵抖動的影響:當出現

[轉]解決STM32開啟定時時立即進入一次中斷程序問題

結果 程序 相關 fig 請求 啟動 其中 邏輯性 ear 整理:MilerShao 在用到STM32定時器的更新中斷時,發現有些情形下只要開啟定時器就立即進入一次中斷。準確說,只要使能更新中斷允許位就立即響應一次更新中斷【當然前提是相關NVIC也已經配置好】。

js定時操作

abs 第一個字符 tin type itl ntb 跑馬燈 get function <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

STM32-(SysTick定時,EXTI外部中斷/事件控制器)

Systick系統定時器 介紹:systick定時器上屬於CM3核心中的一個外設,內嵌在NVIC中。系統定時器是一個24位向下計數的計數器,計數器每一次計數的時間是1/SYSTICK,一般我們設定SYSTICK為72M。當過載數值暫存器的值遞減到0時,系統定時器產生一次中斷,以此迴圈。

遊戲伺服器定時

遊戲伺服器之定時器 1.1 簡單介紹     在遊戲中的關於定時任務的應用很多,在此就不舉例了。所謂定時任務,簡單來說就是t毫秒後執行相應的任務。因為這裡用的例子都是博主工作時用到的遊戲伺服器中的,所以相關程式碼會比較詳盡,如若只是瞭解定時器的大概實現,按照博主所標註的順序,只看重點

STM32cubeMX 基於stm32定時實現定時1秒LED閃爍。

軟體: STM32CubeMX V4.25.0   keil_u5 韌體庫版本: STM32Cube FW_F1 V1.6.1 硬體: OneNet 麒麟座V1.4 在STM32CubeMX中新建專案,選擇正確的MCU型號  

Java多執行緒學習筆記20定時Timer

詳細程式碼見:github程式碼地址   本節內容:     定時器Timer的使用及分析 1) 如何實現指定時間執行任務 2) 如何實現按指定週期執行任務   第五章 定時器Timer 定時/計劃

PHP 程式碼自動執行定時

<?php ignore_user_abort();//關閉瀏覽器仍然執行 set_time_limit(0);//讓程式一直執行下去 $interval=3;//每隔一定時間執行 do{ $msg = date("Y-m-d H:i:s"); file_put_content