超声波传感器测距实验

  本实验是基于MSP430利用HC-SR04超声波传感器进行测距,测距范围是3-65cm,讲得到的数据显示在LCD 1602液晶屏上。

 超声波传感器测距实验_第1张图片

模块工作原理如下

(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


你可能感兴趣的:(430/51单片机)