1. 程式人生 > 實用技巧 >C語言微控制器專案實戰超聲波雷達測距

C語言微控制器專案實戰超聲波雷達測距

  本實驗是基於MSP430利用HC-SR04超聲波感測器進行測距,測距範圍是3-65cm,講得到的資料顯示在LCD 1602液晶屏上。

  

  模組工作原理如下

  (1)採用 IO 觸發測距,給至少 10us 的高電平訊號;

  (2)模組自動傳送 8 個 40khz 的方波,自動檢測是否有訊號返回;

  (3)有訊號返回,通過 IO 輸出一高電平,高電平持續的時間就是超聲波從發射到返回的時間

  (4計算測試距離測試距離=(高電平時間*聲速(340M/S))/2;

  根據工作原理,我們可以選擇兩種模式驅動

  1. 採用中斷+定時器方式,將ECHO定義為上升沿下降沿都能觸發中斷,trig觸發之後,echo高電平進中斷開啟定時器,echo低電平關閉定時器並統計定時器計數值

  2. 採用普通IO+定時器模式,觸發之後等待echo響應,響應時開啟定時器,直到echo恢復低關閉定時器,獲取時間

  此處我採用的是第一種模式,利用MSP430的timerA 的捕獲比較模式,在程式的中斷中處理得到的資料,並轉化成距離。

  1:此模組不宜帶電連線,如果要帶電連線,則先讓模組的 Gnd 端先連線。否則會影響

  模組工作。

  2:測距時,被測物體的面積不少於0.5平方米且要儘量平整。否則會影響測試結果。在下載程式的時候建議將連線echo的一端斷開,避免出現不必要的問題。

  可以參考這個視訊資料

  超聲波雷達測距

  /**********************************************************下邊是程式碼***************************************************/

 

 //功能說明: 1602顯示 超聲波模組測距 串列埠傳送至上位機

  #include

  #include "Config.h"

  #include "1602.c"

  #include "UART.h"

  int count = 0;

  int flag = 0;

  #define uchar unsigned char

  #define uint unsigned int

  /***************????*******************************/

  #define trig_H P2OUT|=BIT0 //????

  #define
trig_L P2OUT&=~BIT0   #define echo P2IN & BIT1 //????   uint cnt;   unsigned long int tim_data,dista_data,dista_data_all,dista_data_sum;   /***************??*******************************/   void delay(uint n)   {   uchar i;   for(;n>0;n--)   for(i=10;i>0;i--);   }   /********************??,????????***************/   void dista_f(unsigned long int distance_data)   {   dista_data_all=dista_data_all+distance_data;   cnt=cnt+1;   if(cnt==16)   {   cnt=0;   dista_data_sum=dista_data_all>>4;   dista_data_all=0;   LCD1602_write_double(13,1,dista_data_sum); //?1602?????   LCD1602_write_char(14,1,'m');   LCD1602_write_char(15,1,'m');   //Print_float(dista_data_sum, 2);   }   }   /**************???io?********************/   void Init_IO()   {   P2DIR = 0XFD;   P2OUT |= 0XFF;   P2IE |= BIT1; //??P2????   P2IES &=~BIT1; //????????   }   /**************??????******************/   void Init_Timer()   {   TACTL|=TACLR+TASSEL_2+ID_3; //???A???   //TACTL |= TASSEL1 + TACLR + ID0 + ID1 + MC0 + TAIE;   //TACCR0 = 9999;   }   void InitTimerB(){   TBCTL=TBSSEL1+ID1+ID0+MC0+TBCLR;//選擇1/8SMCLK 增計數 清除TAR   TBCCTL0=CCIE;//CCR0中斷允許 比較模式   TBCCR0=10000;//時間間隔10ms   }   /************???**************************/   void main( void )   {   WDTCTL = WDTPW + WDTHOLD; //?????   Clock_Init();   InitTimerB();   Init_IO();   UART_Init();   Start_1602(); //??1602   tim_data=0;cnt=0;dista_data=0;   delay(1000); //????   uchar string[] = "distance:";   LCD1602_write_str(0, 0, string);   _EINT(); //?????   while(1)   {   /*if(flag == 1)   {   Print_float(dista_data_sum, 2);   flag = 0;   }*/   trig_H; //?????   delay(2); //??15us   trig_L; //?????   delay(50); //????   while(echo); //????   delay(1000); //????   }   }   /*****************************P2???*******************/   #pragma vector=PORT2_VECTOR   __interrupt void port_init(void)   {   if(echo) //?????   {   TACTL|=TACLR+TASSEL_2+ID_3;   TACTL|=MC_2; //?????,?????????   P2IES|=BIT1; //??P2??????   }   else //?????   {   TACTL=0; //????,????   TACTL|=TASSEL_2+ID_3;   P2IES&=~BIT1; //??P2??????   tim_data=TAR; //????   dista_data=(tim_data*1000/58); //?????(??=us/58)   //dista_data=(tim_data*17/100);   dista_f(dista_data); //??????   }   P2IFG&=~BIT1; // P2???????   }   #pragma vector=TIMERB0_VECTOR   __interrupt void TimerBINT()   {   count++;   if(count>=300)   {   Print_float(dista_data_sum, 2);   //flag = 1;   count = 0;   }   }

  /*********************************clock.c**********************************/

  //****************************************************

  //*************時鐘源模組

  //****************************************************

  #include

  #include "config.h"

  #include "clock.h"

  /********************系統時鐘初始化****************/

  void init_clk(void) //初始化系統時鐘

  {

  uchar i;

  BCSCTL1 &=~XT2OFF; //開啟XT2振盪器

  BCSCTL2 |=SELM_2+SELS;

  do

  {

  IFG1 &=~OFIFG; //清除錯誤標誌

  for(i=0;i<0xff;i++); //延時等待

  }

  while((IFG1 & OFIFG)!=0);

  IFG1 &=~ OFIFG;

  }

  /*******************************************1602.c***********************************/

  #include

  #include "Config.h"

  #include "clock.h"

  #include "1602.h"

  //*************************************************************************

  // 初始化IO口子程式

  //*************************************************************************

  void LCD1602Port_init()

  {

  P4SEL = 0x00;

  P4DIR = 0xFF; //資料口輸出模式

  P5SEL = 0x00;

  P5DIR|= BIT5 + BIT6 + BIT7; //控制口設定為輸出模式

  }

  //***********************************************************************

  // 顯示屏命令寫入函式

  //***********************************************************************

  void LCD1602_write_com(unsigned char com)

  {

  RS_CLR;

  RW_CLR;

  EN_SET;

  DataPort = com; //命令寫入埠

  delay_ms(5);

  EN_CLR;

  }

  //***********************************************************************

  // 顯示屏資料寫入函式

  //***********************************************************************

  void LCD1602_write_data(unsigned char data)

  {

  RS_SET;

  RW_CLR;

  EN_SET;

  DataPort = data; //資料寫入埠

  delay_ms(5);

  EN_CLR;

  }

  //***********************************************************************

  // 顯示屏清空顯示

  //***********************************************************************

  void LCD1602_clear(void)

  {

  LCD1602_write_com(0x01); //清螢幕顯示

  delay_ms(5);

  }

  //***********************************************************************

  // 顯示屏字串寫入函式

  //***********************************************************************

  void LCD1602_write_str(unsigned char x,unsigned char y,unsigned char *s)

  {

  if (y == 0)

  {

  LCD1602_write_com(0x80 + x); //第一行顯示

  }

  else

  {

  LCD1602_write_com(0xC0 + x); //第二行顯示

  }

  while (*s)

  {

  LCD1602_write_data( *s);

  s ++;

  }

  }

  //***********************************************************************

  // 顯示屏單字元寫入函式

  //***********************************************************************

  void LCD1602_write_char(unsigned char x,unsigned char y,unsigned char data)

  {

  if (y == 0)

  {

  LCD1602_write_com(0x80 + x); //第一行顯示

  }

  else

  {

  LCD1602_write_com(0xC0 + x); //第二行顯示

  }

  LCD1602_write_data( data);

  }

  //***********************************************************************

  // 顯示屏初始化函式

  //***********************************************************************

  void LCD1602_init(void)

  {

  LCD1602_write_com(0x38); //顯示模式設定

  delay_ms(5);

  LCD1602_write_com(0x08); //顯示關閉

  delay_ms(5);

  LCD1602_write_com(0x01); //顯示清屏

  delay_ms(5);

  LCD1602_write_com(0x06); //顯示游標移動設定

  delay_ms(5);

  LCD1602_write_com(0x0C); //顯示開及游標設定

  delay_ms(5);

  }

  void LCD1602_write_double(unsigned char x,unsigned char y,unsigned int data)

  {

  uchar i;

  for(i=0;i<6;i++)

  {

  if(i==2)

  LCD1602_write_char( x--, y, '.');

  else

  {

  LCD1602_write_char( x--, y, 0x30+data%10);

  data=data/10;

  }

  }

  }

  void LCD1602_write_int(unsigned char x,unsigned char y,unsigned int data)

  {

  uchar i;

  for(i=0;i<2;i++)

  {

  LCD1602_write_char( x--, y, 0x30+data%10);

  data=data/10;

  }

  }

  void Start_1602()

  {

  LCD1602Port_init(); //系統初始化,設定IO口屬性

  delay_ms(100); //延時100ms

  LCD1602_init(); //液晶引數初始化設定

  }

  

uart.h

  #ifndef _UART_H_

  #define _UART_H_

  #include "msp430x14x.h"

  void Print_Str(uchar *s);

  //*************************************************************************

  // MSP430?????

  //*************************************************************************

  void UART_Init()

  {

  U0CTL|=SWRST + CHAR; //??SWRST,8?????

  U0TCTL|=SSEL1; //SMCLK?????

  U0BR1=baud_h; //BRCLK=8MHZ,Baud=BRCLK/N

  U0BR0=baud_l; //N=UBR+(UxMCTL)/8

  U0MCTL=0x00; //??????0,???9600bps

  ME1|=UTXE0; //UART0????

  ME1|=URXE0; //UART0????

  U0CTL&=~SWRST;

  IE1|=URXIE0; //???????

  P3SEL|= BIT4 + BIT5; //??IO????????,??UART??

  P3DIR|= BIT4; //??TXD0??????

  }

  //*************************************************************************

  // ??0??????

  //*************************************************************************

  void Send_Byte(uchar data)

  {

  while(!(IFG1&UTXIFG0)); //?????????????

  U0TXBUF=data;

  }

  //***************************************//

  void Print_float(unsigned int t, unsigned char position)//????? position ???????

  {

  unsigned int s_int[5] = {0};

  int i = 0;

  while(t>0)

  {

  s_int[i++] = t%10;

  t=t/10;

  }

  for(i=4;i>=0;i--)

  {

  if(i==position)

  {

  Send_Byte(0x30 + s_int[i]);

  Send_Byte(0x2E);

  }

  else

  {

  Send_Byte(0x30 + s_int[i]);

  }

  }

  //delay_ms(100);

  Send_Byte('m');

  Send_Byte('m');

  Send_Byte(' ');

  delay_ms(100);

  }

  //*************************************************************************

  // ??0??int???

  //*************************************************************************

  void Print_int(unsigned int t)

  {

  unsigned int s_int[5];

  unsigned int i = 1;

  while(t>0)

  {

  s_int[i] = t%10;

  t=t/10;

  i++;

  }

  i--;

  while(i)

  {

  Send_Byte(0x30 + s_int[i]);

  i--;

  }

  }

  //*************************************************************************

  // ??0???????

  //*************************************************************************

  void Print_Str(uchar *s)

  {

  while(*s != '\0')

  {

  Send_Byte(*s++);

  }

  }

  #endif

  也歡迎進球球裙技術交流

  點選連結加入群聊【嵌入式微控制器LinuxC交流群②】https://jq.qq.com/?_wv=1027&k=FW2qSMZ4