本实验是基于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. 【第六篇】- Maven 仓库之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 仓库 在 Maven 的术语中,仓库是一个位置(place). Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库. 在 Maven 中,任何一个依赖.插件或者项目构建的输出 ...

  2. Map集和

    目录 Map 特点 继承树 常用方法 entrySet 方法 HashMap 特点 HashMap 的重要常量 存储结构 jdk1.8 总结 面试题 HashMap存储自定义类型键值 LinkedHa ...

  3. go相关

    mac 上build go  如果想要在centos上面执行 必须使用下面的方式 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o hello ...

  4. 机器学习——Adaboost

    1 Adaboost 的提出 1990年,Schapire最先构造出一种多项式级的算法,即最初的Boost算法; 1993年,Drunker和Schapire第一次将神经网络作为弱学习器,应用Boos ...

  5. Java面向对象系列(8)- Super详解

    场景一 场景二 场景三 场景四 注意:调用父类的构造器,super()必须在子类构造器的第一行 场景五 场景六 super注意点 super调用父类得构造方法(即构造器),必须在构造方法得第一个 su ...

  6. Oracle基本入门

    一.数据的存储 1.java 程序中的对象:数组.集合保存.当运行的程序结束的时候,里面的数据就消亡. 2.文件存储系统: 存在的缺陷: 2.1)没有明确的数据类型划分. 2.2)没有用户身份验证机制 ...

  7. python二级 第9套

    1. prInt.默认输出空格 2. 我的这种想法也行不通啊 format() 一次只能有一个未知量 2. 分割的结果就是列表 3. 对比"大学"    上一套的split('&q ...

  8. P4542-[ZJOI2011]营救皮卡丘【费用流,Floyd】

    正题 题目链接:https://www.luogu.com.cn/problem/P4542 题目大意 给出\(n+1\)个点\(m\)条边的无向图,\(k\)个人开始在\(0\)号点,一个人进入\( ...

  9. Javascript 常见的高阶函数

    高阶函数,英文叫 Higher Order function.一个函数可以接收另外一个函数作为参数,这种函数就叫做高阶函数. 示例: function add(x, y, f) { return f( ...

  10. Mysql explain中key_len的作用及计算规则

    key_len表示索引使用的字节数,根据这个值可以判断索引的使用情况,特别是在组合索引的时候,判断该索引有多少部分被使用到非常重要. 在计算key_len时,下面是一些需要考虑的点: 索引字段的附加信 ...