STM32之輸入捕獲以及小小應用(庫)

      五一之際,先祝你們五一快樂、其實快樂很簡單,工做的人有假放,學習的人也有假放,像我,有假放纔有更多的時間學本身想學的東西、51假期學51,惋惜沒有32假期呀、好了、、言歸正傳,你們聽過吸星大法吧、、在這裏、智商和情商比我高的人估計又知道我要說什麼了、、沒錯了、、今天咱們來了解「葵花寶典」第STM32篇之輸入捕獲,也就是上文所講的「吸星大法」,函數

      那輸入捕獲能夠用來幹嗎呢??這個問題問的好,輸入捕獲能夠用來測量脈衝寬度或者測量頻率,假如要捕獲一個脈衝的高電平脈寬,咱們要怎麼作呢??別急哈、、接下來咱們從頭慢慢的分析到腳、、學習

      據老夫所知:STM32的輸入捕獲,就是經過檢測通道上的邊沿信號,在邊沿信號發生跳變(好比說忽然來個上升沿或者降低沿),計數器就把此刻的計數值存放到對應通道的捕獲比較寄存器,就這樣、、就捕捉到了「美女」、話是這麼說、、可操做起來不只僅是幾句話、由於初始化和對捕獲的處理是不同的、因此,爲了作好迎接捕獲的準備,咱們來介紹下幾個比較陌生的位:ui

       對於定時器的一些寄存器,在以前的博客都有涉及到,如spa

      TIMx_CR1,code

     捕獲/比較模式寄存器1(TIMx_CCMR1),blog

     捕獲/比較使能寄存器(TIMx_CCER),事件

     計數器(TIMx_CNT)ip

     預分頻器(TIMx_PSC)ci

    自動重裝載寄存器(TIMx_ARR)input

    捕獲/比較寄存器1(TIMx_CCR1)

   咱們再來看看捕獲/比較模式寄存器1(TIMx_CCMR1),因爲咱們是用TIM5_CH1,因此該寄存器中

   CC1S[1:0]:捕獲/比較1選擇 (Capture/Compare 1 selection)咱們選擇01:CC1通道被配置爲輸入,IC1映射在TI1上;這個知道爲啥是TI1嗎??請看我那銷魂美麗的塗鴉:

    這裏咱們檢測高電平的寬度,因此咱們檢測的時候只要遇到上升沿就觸發捕獲一次,可是咱們要怎麼設置呢,請看這幾位:

   IC1PSC[1:0]:輸入/捕獲1預分頻器 (Input capture 1 prescaler)00:無預分頻器,捕獲輸入口上檢測到的每個邊沿都觸發一次捕獲;

  神奇吧,好了,IC1F[3:0]:輸入捕獲1濾波器 (Input capture 1 filter)(這個就是上圖中的輸入濾波器,在這裏咱們不作濾波處理,爲何,請看如下解釋)

               在這裏解釋下:數字濾波器由一個事件計數器組成,它記錄到N個事件後會產生一個輸出的跳變:這個N能夠取值具體參考中文手冊,意思是說:我採樣高電平,只有連續採樣到N個電平是高電平的話我才認爲是有效的高電平,低於N個我就認爲是無效的、在這篇博客裏,咱們只要是採樣到高電平就行,因此這裏就不採用數字濾波。

   咱們來看看這個寄存器     捕獲/比較使能寄存器(TIMx_CCER),要使捕獲使能,咱們就須要設置使能位

     CC1E:輸入/捕獲1輸出使能 (Capture/Compare 1 output enable)爲0;

   對於咱們輸入捕獲後要處理的咱們交給咱們的中斷,因此在這裏咱們要開啓中斷使能位  

    DMA/中斷使能寄存器(TIMx_DIER)   CC1IE:容許捕獲/比較1中斷 (Capture/Compare 1 interrupt enable)爲1;

   介紹了以上幾位大神,接下來,咱們要怎麼個思路呢??==當咱們捕獲到上升沿時,咱們把此時的CNT中的值讀出來,而後等待降低沿的到來,這時候要分爲兩種狀況:

  第一:降低沿來了,咱們就記錄此刻CNT的值,(捕獲值)而後重複以上動做

 第二:降低沿沒來,但是這時候定時器的計數值已經到了,也就是要溢出了,這時候要特殊處理下,也就是直接把計數值返回

(注:在這裏,要注意捕獲值跟計數值的差異,他們是不同的、)至於爲何不同,你們能夠思考思考、、

 因此咱們將兩次捕獲的值相減,(降低沿的值減去上升沿的值)就能夠獲得高電平的脈寬了、、而這些事,咱們都在中斷服務函數裏處理(中斷喔、、想起沒??要作什麼知道吧、、注意,這時候有兩個中斷觸發:更新中斷和捕獲中斷,更新中斷用來處理定時器計數溢出,捕獲中斷用來處理捕獲事件)

   接下來,咱們看看咱們具體的實現步驟

     1:開啓掛載在ABP1的TIM5時鐘,開啓掛載在ABP2的GPIOA的時鐘,並初始化TIM5和GPIOA,因爲這兩個初始化前幾篇博客有涉及到,故直接貼出代碼:

 1           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 2           RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
 3           
 4           KEY_Init(); //IO我已在按鍵的函數裏初始化了
 5           
 6           TIM_TimeBaseStructure.TIM_Period = arr;              
 7           TIM_TimeBaseStructure.TIM_Prescaler = psc;
 8           TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
 9           TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
10           TIM_TimeBaseInit(TIM5, & TIM_TimeBaseStructure);         

      二、設置TIM_CH1的輸入捕獲功能,打開「stm3210x.tim.h」咱們能夠看到

 1 typedef struct
 2 {
 3 
 4   uint16_t TIM_Channel;      /*!< Specifies the TIM channel.設置通道
 5                                   This parameter can be a value of @ref TIM_Channel */
 6 
 7   uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.設置輸入信號的有效捕獲極性
 8                                   This parameter can be a value of @ref TIM_Input_Capture_Polarity */
 9 
10   uint16_t TIM_ICSelection;  /*!< Specifies the input. 設置映射關係
11                                   This parameter can be a value of @ref TIM_Input_Capture_Selection */
12 
13   uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler. 設置捕獲的分配係數
14                                   This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
15 
16   uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter. 設置數字濾波器的長度
17                                   This parameter can be a number between 0x0 and 0xF */
18 } TIM_ICInitTypeDef;

根據咱們以上的瞭解,咱們設置,請看如下代碼:

1                 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;     //通道1
2                 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;   //上升沿捕獲
3                 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //映射到TI1
4                 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //不分頻
5                 TIM_ICInitStructure.TIM_ICFilter = 0x0;                //不濾波
6                 TIM_ICInit(TIM5, &TIM_ICInitStructure);

     三、設置中斷優先級、在這裏比較簡單,直接看代碼:

1         NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;                               
2         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
3         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
4         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
5         NVIC_Init(&NVIC_InitStructure);         

    4.使能中斷並開啓定時器

1  
2     TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE );      
3             
4      TIM_Cmd(TIM5, ENABLE);

   五、編寫中斷服務函數    

 1 u8 TM5_CH1_CAPTURE_STA = 0;//8位0x00~0x80
 2  u16 TM5_CH1_CAPTURE_VAL;  //捕獲高電平後定時器溢出的次數
 3 
 4 void TIM5_IRQHandler(void)
 5 {
 6    if((TM5_CH1_CAPTURE_STA & 0x80) == 0 )  //未成功捕獲,0x80捕獲完成
 7      {
 8       if(TIM_GetITStatus(TIM5, TIM_IT_Update) == SET)  //數據更新中斷產生
 9             {
10            if(TM5_CH1_CAPTURE_STA & 0x40)     //已經捕獲到高電平
11                      {
12                          if((TM5_CH1_CAPTURE_STA & 0x3f)==0x3f)   //­溢出
13                          {
14                           TM5_CH1_CAPTURE_STA |= 0x80;  //強制捕獲成功
15                           TM5_CH1_CAPTURE_VAL = 0xffff;  //此時的計數值
16                          }
17                          else
18                          {
19                            TM5_CH1_CAPTURE_STA++; 
20                          }
21                          
22                       }
23              }
24             if(TIM_GetITStatus(TIM5, TIM_IT_CC1) == SET)//發生捕獲
25             {
26         if(TM5_CH1_CAPTURE_STA & 0x40)  //成功捕獲到一次降低沿,但不是第一次捕獲
27                 {
28                      TM5_CH1_CAPTURE_STA |= 0x80;  //捕獲成功
29                       TM5_CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);//獲取捕獲值
30                       TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);//要設置爲上升沿,等待降低沿的來臨 31         }
32                 else  //第一次捕獲
33                 {
34                     TM5_CH1_CAPTURE_STA = 0;
35                     TM5_CH1_CAPTURE_VAL = 0;
36                     TIM_SetCounter(TIM5, 0);  //還沒等到降低沿來時把全部的都清零
37                     TM5_CH1_CAPTURE_STA |= 0x40;
38                     TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);//要設置成降低沿,等到上升沿的來臨 39                  }
40                 
41       }
42    }
43       TIM_ClearITPendingBit(TIM5, TIM_IT_CC1 | TIM_IT_Update);
44 
45 }

      六、注意紅色標註部分,好好理解剛開始說的計數值和捕獲值的區別、還有

TIM_SetCounter(TIM5, 0); //設置計數器寄存器值
TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);//設置通道1輸入捕獲極性
這兩個函數是庫函數爲咱們提升的能夠單獨對通道進行操做的函數,很是方便

      七、到這裏,咱們須要在主函數裏稍微寫下:

1  if(TM5_CH1_CAPTURE_STA & 0x80)
2          {
3                temp =  (TM5_CH1_CAPTURE_VAL & 0x3f);
4                temp *= 65536; //計數器爲0~65535,也就是65536一次 5                temp +=  TM5_CH1_CAPTURE_VAL;
6                printf("HIGH is %d\r\n",temp);
7                TM5_CH1_CAPTURE_STA = 0;//這裏由於咱們在以前的捕獲時,若捕獲成功則爲1,並無清0,因此要進行下一次捕獲的話,要在這裏進行清零 8      }

      八、好了,至於我標題說的小應用,也就是把咱們上次PWM的輸出給此次的輸入捕獲,你們經過串口就能夠看到高電平的脈寬了。固然,在這篇博客的程序裏也須要保留上次PWM輸出的程序方可、、

      九、你們肚子餓了吧、、吃飯去吧、、

     

      今天五一,仍是宅在宿舍學32,也很開心,由於學到了東西、、有假放開心、、有學到知識也開心,即便在學的過程當中可能會被煩惱到、、其實快樂也很簡單、只是看你怎麼把握、、五月的開始、、將繼續學stm3二、、還有英語六級、、加油、、在這裏、有錯的地方但願能指教、、我也虛心的向您學習、、

相關文章
相關標籤/搜索