找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3443|回復(fù): 0
收起左側(cè)

STM8L的TIM2捕獲之超聲波測(cè)距

[復(fù)制鏈接]
ID:140343 發(fā)表于 2016-10-10 00:00 | 顯示全部樓層 |閱讀模式
應(yīng)本訂閱號(hào)一位讀者要求,發(fā)布一個(gè)超聲波的例程.本來(lái)打算用STM8L-DISCOVERY板子上的LCD液晶屏顯示測(cè)量到的距離的.昨天寫(xiě)程序時(shí)發(fā)現(xiàn),LCD顯示的一個(gè)IO口和檢測(cè)超聲波回波的捕獲IO都是PB0,而且TIM2的這捕獲IO還不能復(fù)用到其他引腳,只有PB0這一個(gè)IO.所以不能使用LCD顯示了.今天我發(fā)現(xiàn),IAR功能還是很強(qiáng)大的,VIEW菜單下有一個(gè)LIVE  WATCH功能,故名思議,就是一個(gè)實(shí)時(shí)顯示變量數(shù)據(jù)的功能,用起來(lái)太爽了,比用屏幕顯示還給力.第一次發(fā)現(xiàn)IAR的這個(gè)功能^_^

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

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

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


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



/*硬件連接*/
//PC7 ---->TRIG
// PB0<----ECHO
/****************************************************************************************
*開(kāi)發(fā)環(huán)境:IAR for stm8 v6.5.3
*硬件平臺(tái):STM8L-DISCOVERY
*功能說(shuō)明:本例程,
*作    者:茗風(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
/******************************************************************************************************
*  名    稱(chēng):void GPIO_Init(void)
*  功    能:初始化PC7為高速推挽輸出
*  入口參數(shù):無(wú)
*  出口參數(shù):無(wú)
*  說(shuō)    明:
*  范    例:無(wú)
******************************************************************************************************/
void GPIO_Config(void)
{
   PC_CR1_C17  =1;//推挽輸出
   PC_CR2_C27  =1;//高速輸出
   PC_DDR_DDR7 =1;//PC7輸出
   PC_ODR_ODR7 =0;//輸出低電平
}
/******************************************************************************************************
*  名    稱(chēng):void delay(void)
*  功    能:延時(shí)
*  入口參數(shù):無(wú)
*  出口參數(shù):無(wú)
*  說(shuō)    明:系統(tǒng)頻率為3M時(shí),理論計(jì)算延時(shí)時(shí)間為78ms
*  范    例:無(wú)
******************************************************************************************************/
void delay(void)
{
  uint8_t i=255,j;
  while(i--)//255*1.2+255*1.2*255
  {
        for(j=0;j<255;j++);  
  }  
}
/******************************************************************************************************
*  名    稱(chēng):void CLOCK_Init(void)
*  功    能:系統(tǒng)時(shí)鐘切換為HSE,12M/4=3M
*  入口參數(shù):無(wú)
*  出口參數(shù):無(wú)
*  說(shuō)    明:
*  范    例:無(wú)
******************************************************************************************************/
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*/
         
//自動(dòng)切換
   CLK_SWCR_SWEN =1;//允許切換時(shí)鐘
   CLK_SWR =0x04;//寫(xiě)入一個(gè)八位的值,用于選擇目標(biāo)時(shí)鐘源
   while(CLK_SWCR_SWBSY);//等待時(shí)鐘切換完成
//手動(dòng)切換
//   CLK_SWR =0x08;//寫(xiě)入一個(gè)八位的值,用于選擇目標(biāo)時(shí)鐘源
//   while(!CLK_ECKR_LSERDY);//等待目標(biāo)時(shí)鐘源穩(wěn)定
//   CLK_SWCR_SWEN =1;//允許切換時(shí)鐘
  /*
  *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
  */
}
/******************************************************************************************************
*  名    稱(chēng):void TIM2_Config(void)
*  功    能:STM8定時(shí)器2捕獲功能初始化
*  入口參數(shù):無(wú)
*  出口參數(shù):無(wú)
*  說(shuō)    明:PB0為捕獲輸入引腳,使用通道0
*  范    例:無(wú)
******************************************************************************************************/
void TIM2_Config(void)
{
  PB_DDR_DDR0 =0;//輸入
  PB_CR1_C10  =0;//浮空輸入
//  PB_CR1_C10  =1;//上拉輸入
  PB_CR2_C20  =0;//禁止外部中斷功能

  CLK_PCKENR1_PCKEN10=1;//打開(kāi)定時(shí)器2時(shí)鐘

//------設(shè)置TIM2時(shí)鐘分頻值------
  //我的電路板上,HSE接的是12M,四分頻后為3M
  //正常情況應(yīng)該接16M,這樣分頻后不會(huì)出現(xiàn)3M這樣不利于計(jì)算時(shí)間的頻率
  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;//不通過(guò)預(yù)裝載寄存器

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

  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  輸入信號(hào)不分頻
  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 輸入信號(hào)不分頻   
  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;//上升沿時(shí)發(fā)生捕獲
  TIM2_CCER1_CC2P=1;//下降沿時(shí)發(fā)生捕獲

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

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

  TIM2_IER_CC1IE=1;//開(kāi)啟捕獲中斷
  TIM2_IER_CC2IE=1;//開(kāi)啟捕獲中斷
  TIM2_CR1_CEN=1;//開(kāi)啟計(jì)數(shù)
}
void main(void)
{
  static uint16_t tmp=0;
  uint8_t cnts=0;
  CLOCK_Config();//系統(tǒng)時(shí)鐘切換為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得到的時(shí)間為高電平持續(xù)時(shí)間
   }
}

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表