本实验是基于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

  也欢迎进球球裙技术交流

  点击链接加入群聊【嵌入式单片机Linux C交流群②】https://jq.qq.com/?_wv=1027&k=FW2qSMZ4

C语言单片机项目实战超声波雷达测距的更多相关文章

  1. 基于Linux下的C语言项目实战--本地账号管理系统

    C语言开发项目实战: C语言是一门通用计算机编程语言,广泛应用于底层开发.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.尽 ...

  2. 树莓派控制HC-SR04超声波模块测距(新手向+C语言向)

    因为作业要求使用c语言代码,这里先附上一段摘自网上的代码 感谢KalaerSun的c语言代码,摘自https://blog.csdn.net/qq_25247589/article/details/6 ...

  3. 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...

  4. 手把手和你一起实现一个Web框架实战——EzWeb框架(三)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(三)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo3 这一篇文章 ...

  5. 手把手和你一起实现一个Web框架实战——EzWeb框架(四)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(四)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 这一篇文章主要实现路由组功能.实现路由 ...

  6. 手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(五)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo5 中间件实现 ...

  7. 彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-项目入口与路由EP01

    书接上回,我们已经安装好Iris框架,并且构建好了Iris项目,同时配置了fresh自动监控项目的实时编译,万事俱备,只欠东风,彩虹女神蓄势待发.现在我们来看看Iris的基础功能,如何编写项目入口文件 ...

  8. 给缺少Python项目实战经验的人

    我们在学习过程中最容易犯的一个错误就是:看的多动手的少,特别是对于一些项目的开发学习就更少了! 没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用 ...

  9. Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. 使用ImageMagick操作gif图

    上篇文章我们已经学习了 GraphicsMagick 中的许多函数,也说过 GraphicsMagick 是 ImageMagick 的一个分支,所以他们很多的函数都是一样的使用方式和效果,相似的内容 ...

  2. supermvc介绍

    马上要开始写毕设了,需要一个合适的框架.想想自己用过的几个框框speedphp tp啊 还有公司的 dagger啊 ,大同小易.每一种都有自己喜欢的地方.然后想到了二八理论,我们常用的功能可能不到框架 ...

  3. localStorage util

    // localStorage util var db ={ set : function(key, obj){ localStorage.setItem(key, JSON.stringify(ob ...

  4. Qt中的ui文件转换为py文件

    将pyuic5 -o demo.py demo.ui写入ui-py.bat文件(自定义文件),将ui文件与ui-py.bat文件放在同一文件夹,双击.bat文件即可生成.py文件

  5. str.strip(chars)

    strip会去除给定字符串的指定字符,指定字符可以是一个或多个,去除从左右分别进行,没有则忽略,如果需要去除某个中间的字符,必须先去除外围的字符 看几个例子,以s为例,故意设置为非对称结构, s = ...

  6. selenium--多窗口

    多窗口/句柄 有些页面的链接打开后,会重新打开一个窗口,对于这种情况,想在新页面上操作,就得先切换窗口了.获取窗口的唯一标识用句柄表示,所以只需要切换句柄,我们就能在多个页面上灵活自如的操作了. 1. ...

  7. MyBatis封装对象内的List出现的问题

    本篇文章问题1:wife的复数形式是wives,不是wifes,英语不好请见谅. 对象举例: class User { private String username; private List< ...

  8. C语言数组的创建和使用

    C语言数组的创建和使用 数组是一组相同类型元素的集合. 一维数组的创建及初始化 //创建int类型的数组 //直接创建:不对数组进行初始化 int arr1[10]; //最常用.好用的创建方式 in ...

  9. HCNP Routing&Switching之路由引入导致的问题及解决方案

    前文我们了解了路由引入相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15359902.html:今天我们来讨论下由于路由引入所导致的问题以及怎么避免此 ...

  10. ElasticJob 3.0.0:打造面向互联网生态和海量任务的分布式调度解决方案

    ElasticJob 于 2020 年 5 月 28 日重启并成为 Apache ShardingSphere 子项目.新版本借鉴了 ShardingSphere 可拔插架构的设计理念,对内核进行了大 ...