標(biāo)題: STM8L的TIM2捕獲之超聲波測距 [打印本頁]

作者: 51hei小林    時間: 2016-10-10 00:00
標(biāo)題: STM8L的TIM2捕獲之超聲波測距
應(yīng)本訂閱號一位讀者要求,發(fā)布一個超聲波的例程.本來打算用STM8L-DISCOVERY板子上的LCD液晶屏顯示測量到的距離的.昨天寫程序時發(fā)現(xiàn),LCD顯示的一個IO口和檢測超聲波回波的捕獲IO都是PB0,而且TIM2的這捕獲IO還不能復(fù)用到其他引腳,只有PB0這一個IO.所以不能使用LCD顯示了.今天我發(fā)現(xiàn),IAR功能還是很強(qiáng)大的,VIEW菜單下有一個LIVE  WATCH功能,故名思議,就是一個實(shí)時顯示變量數(shù)據(jù)的功能,用起來太爽了,比用屏幕顯示還給力.第一次發(fā)現(xiàn)IAR的這個功能^_^

本例程,主要是通過TIM2的捕獲功能,測量超聲波發(fā)出后,出現(xiàn)的一個高電平時間,根據(jù)高電平的時間和聲速340m/s來計(jì)算距離.
這里要說的是,第一次發(fā)現(xiàn)這個吃灰好久的超聲波模塊,竟然還有這么一個奇怪,我以前沒發(fā)現(xiàn),很方便的功能.就是超聲波模塊收到回波后,ECHO引腳會產(chǎn)生一個高電平,這個高電平的時間,就是超聲波從發(fā)射到返回的時間,只要測量這個高電平的時間,然后除2,就可以得到超聲波從發(fā)射處到目標(biāo)處的時間了.
如下圖,要想讓發(fā)射一次超聲波,只需給TRIG引腳一個大于10us的高電平,由于這個模塊是自帶了4M的晶振,所以可以自動發(fā)送8個40KHz的脈沖(這個模塊的自動化程度很高啊!),模塊接收到超聲波回波后,會在ECHO引腳輸出一個高電平,這個高電平的時間,就是超聲波從發(fā)射到接收的時間,用起來很方便.以前學(xué)習(xí)51時,用過一個把超聲波做在板子上的開發(fā)板,不是外接的模塊,還要自己寫程序發(fā)送8個40KHz的脈沖,還要自己判斷開始計(jì)時時間……用起來很麻煩.這個超聲波模塊的信號是HC-SR04.

下圖是本例程的實(shí)測波形,首先讓PC7產(chǎn)生一個45us的高電平,讓超聲波模塊發(fā)射超聲波,然后會在PB0引腳產(chǎn)生一個高電平,如下圖是實(shí)測的一個超聲波發(fā)射和接收波形,此時高電平的時間是9.6ms,所以超聲波從超聲波模塊到目標(biāo)位置的時間為9.6ms/2=4.8ms.有了時間,還有速度340m/s,根據(jù)公式,就可以求出距離34000/1000(cm/ms)*4.8ms=163cm.

看下圖,右側(cè)部分的tmp值就是計(jì)算后的距離,這個值此刻顯示的為162cm.通過IAR的這個Live Watch功能,可以很方便的查看此時的距離,我用手中的平板,在模塊上方移動,能夠看到距離數(shù)據(jù)會隨之改變.


TIM2的捕獲功能配置,和下圖是一樣的,IC1即捕獲通道1配置為在脈沖的上升沿發(fā)生發(fā)生捕獲,將TIM2的計(jì)數(shù)值復(fù)制到TIM2_CCR1寄存器中,同時計(jì)數(shù)器的值復(fù)位,從0重新開始計(jì)數(shù),在脈沖的下降沿捕獲通道2發(fā)生捕獲,將此時計(jì)數(shù)器的值復(fù)制到TIM2_CCR2寄存器,此值為高電平脈沖時間.



/*硬件連接*/
//PC7 ---->TRIG
// PB0<----ECHO
/****************************************************************************************
*開發(fā)環(huán)境:IAR for stm8 v6.5.3
*硬件平臺:STM8L-DISCOVERY
*功能說明:本例程,
*作    者:茗風(fēng)
****************************************************************************************/
#include"iostm8l152c6.h"
#include"stdint.h"
#include"stdbool.h"

uint16_t tim2_ccr1=0,tim2_ccr2=0;
bool  bFinish_Flag=false;

#define a 0x01
#define b 0x02
#define c 0x04
#define d 0x08
#define e 0x10
#define f 0x20
#define g 0x40
#define m 0x80
/******************************************************************************************************
*  名    稱:void GPIO_Init(void)
*  功    能:初始化PC7為高速推挽輸出
*  入口參數(shù):無
*  出口參數(shù):無
*  說    明:
*  范    例:無
******************************************************************************************************/
void GPIO_Config(void)
{
   PC_CR1_C17  =1;//推挽輸出
   PC_CR2_C27  =1;//高速輸出
   PC_DDR_DDR7 =1;//PC7輸出
   PC_ODR_ODR7 =0;//輸出低電平
}
/******************************************************************************************************
*  名    稱:void delay(void)
*  功    能:延時
*  入口參數(shù):無
*  出口參數(shù):無
*  說    明:系統(tǒng)頻率為3M時,理論計(jì)算延時時間為78ms
*  范    例:無
******************************************************************************************************/
void delay(void)
{
  uint8_t i=255,j;
  while(i--)//255*1.2+255*1.2*255
  {
        for(j=0;j<255;j++);  
  }  
}
/******************************************************************************************************
*  名    稱:void CLOCK_Init(void)
*  功    能:系統(tǒng)時鐘切換為HSE,12M/4=3M
*  入口參數(shù):無
*  出口參數(shù):無
*  說    明:
*  范    例:無
******************************************************************************************************/
void CLOCK_Config(void)
{
   CLK_CKDIVR =0x2;//分頻值為4
   /*000: System clock source/1
     001: System clock source /2
     010: System clock source /4
     011: System clock source /8
     100: System clock source /16
     101: System clock source /32
     110: System clock source /64
     111: System clock source /128*/
         
//自動切換
   CLK_SWCR_SWEN =1;//允許切換時鐘
   CLK_SWR =0x04;//寫入一個八位的值,用于選擇目標(biāo)時鐘源
   while(CLK_SWCR_SWBSY);//等待時鐘切換完成
//手動切換
//   CLK_SWR =0x08;//寫入一個八位的值,用于選擇目標(biāo)時鐘源
//   while(!CLK_ECKR_LSERDY);//等待目標(biāo)時鐘源穩(wěn)定
//   CLK_SWCR_SWEN =1;//允許切換時鐘
  /*
  *0x01:HSI selected as system clock source
  *0x02:LSI selected as system clock source
  *0x04:HSE selected as system clock source
  *0x08:LSE selected as system clock source
  */
}
/******************************************************************************************************
*  名    稱:void TIM2_Config(void)
*  功    能:STM8定時器2捕獲功能初始化
*  入口參數(shù):無
*  出口參數(shù):無
*  說    明:PB0為捕獲輸入引腳,使用通道0
*  范    例:無
******************************************************************************************************/
void TIM2_Config(void)
{
  PB_DDR_DDR0 =0;//輸入
  PB_CR1_C10  =0;//浮空輸入
//  PB_CR1_C10  =1;//上拉輸入
  PB_CR2_C20  =0;//禁止外部中斷功能

  CLK_PCKENR1_PCKEN10=1;//打開定時器2時鐘

//------設(shè)置TIM2時鐘分頻值------
  //我的電路板上,HSE接的是12M,四分頻后為3M
  //正常情況應(yīng)該接16M,這樣分頻后不會出現(xiàn)3M這樣不利于計(jì)算時間的頻率
  TIM2_PSCR_PSC=0;//分頻值  3M/2^0=3M/1=3000000Hz

//-重裝值,TIM2從0計(jì)數(shù)到此值,發(fā)生溢出-
//  TIM2_ARRH=0;
//  TIM2_ARRL=100;

  //----AUTO_RELOAD 預(yù)裝載使能----
  TIM2_CR1_ARPE =0;//不通過預(yù)裝載寄存器

  TIM2_CR1_URS=1;//僅當(dāng)計(jì)數(shù)器溢出時才發(fā)生中斷請求

  TIM2_CR1_UDIS=1;//禁止更新事件//計(jì)數(shù)器溢出屬于更新事件

  TIM2_CR1_DIR=0;//向上計(jì)數(shù)

//  TIM2_CCER1_CC1E=0;//清零使能位,為了配置寄存器
//  TIM2_CCER1_CC2E=0;//清零使能位,為了配置寄存器

  TIM2_CCMR1=0;
//  TIM2_CCMR1=0x00; //IC1F=0000  輸入信號不分頻
  TIM2_CCMR1 |=0x01;//CC1S=01 IC1 is mapped on TI1FP1
  /*00: CC1 channel is configured as output
    01: CC1 channel is configured as input, IC1 is mapped on TI1FP1
    10: CC1 channel is configured as input, IC1 is mapped on TI2FP1
    11: Reserved                                                    */

  TIM2_CCMR2=0;
//  TIM2_CCMR2=0x00;//IC1PSC=0 輸入信號不分頻   
  TIM2_CCMR2 |=0x02;//  TIM2_CCMR2_CC2S=0x2
/*  00: CC2 channel is configured as output
    01: CC2 channel is configured as input, IC2 is mapped on TI2FP2
    10: CC2 channel is configured as input, IC2 is mapped on TI1FP2
    11:CC2 channel is configured as input, IC2 is mapped on TRC    */


  TIM2_CCER1_CC1P=0;//上升沿時發(fā)生捕獲
  TIM2_CCER1_CC2P=1;//下降沿時發(fā)生捕獲

  TIM2_SMCR=0x54;//
//  TIM2_SMCR_TS=0x05;//101 iput 1(TI1FP1) 頭文件有錯誤
//  TIM2_SMCR_SMS=0x04;//復(fù)位觸發(fā)模式

  TIM2_CCER1_CC1E=1;//使能捕獲功能
  TIM2_CCER1_CC2E=1;//使能捕獲功能

  TIM2_IER_CC1IE=1;//開啟捕獲中斷
  TIM2_IER_CC2IE=1;//開啟捕獲中斷
  TIM2_CR1_CEN=1;//開啟計(jì)數(shù)
}
void main(void)
{
  static uint16_t tmp=0;
  uint8_t cnts=0;
  CLOCK_Config();//系統(tǒng)時鐘切換為HSE(12MHz/4=3MHz)
  GPIO_Config();//超生波觸發(fā)引腳
//  LCD_Config();
  TIM2_Config();
  asm("rim");               //enable interrupts
  while(1)
  {
    PC_ODR_ODR7 =1;//保證最短10us的低電平

    for(cnts=15;cnts>0;cnts--);

    PC_ODR_ODR7 =0;

    for(cnts=2;cnts>0;cnts--)
    {
      delay();
    }

    if(bFinish_Flag==true)
    {
      //1000000us/3000000=0.33us
      //340(m/s)=34/1000(cm/us)=0.034cm/us
      tmp=(float)tim2_ccr2*0.3333*0.017;
      bFinish_Flag=false;
    }
//   asm("wfi");
  }
}
#pragma vector=TIM2_CAPCOM_CC1IF_vector
__interrupt void TIM2_CAPCOM_CC1IF_ISR(void)
{
   if(TIM2_SR1_CC1IF==1)
   {
     TIM2_SR1_CC1IF=0;//清除中斷標(biāo)志位
//     tim2_ccr1=TIM2_CCR1H;
//     tim2_ccr1<<=8;
//     tim2_ccr1+=TIM2_CCR1L;
   }
   if(TIM2_SR1_CC2IF==1)
   {
     TIM2_SR1_CC2IF=0;//清除中斷標(biāo)志位
     tim2_ccr2=TIM2_CCR2H;
     tim2_ccr2<<=8;
     tim2_ccr2+=TIM2_CCR2L;
     bFinish_Flag=true;
     //tim2_ccr2得到的時間為高電平持續(xù)時間
   }
}






歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1