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
也欢迎进球球裙技术交流
点击链接加入群聊【嵌入式单片机Linux C交流群②】https://jq.qq.com/?_wv=1027&k=FW2qSMZ4
C语言单片机项目实战超声波雷达测距的更多相关文章
- 基于Linux下的C语言项目实战--本地账号管理系统
C语言开发项目实战: C语言是一门通用计算机编程语言,广泛应用于底层开发.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.尽 ...
- 树莓派控制HC-SR04超声波模块测距(新手向+C语言向)
因为作业要求使用c语言代码,这里先附上一段摘自网上的代码 感谢KalaerSun的c语言代码,摘自https://blog.csdn.net/qq_25247589/article/details/6 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(三)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(三)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo3 这一篇文章 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(四)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(四)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 这一篇文章主要实现路由组功能.实现路由 ...
- 手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战
手把手和你一起实现一个Web框架实战--EzWeb框架(五)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 本篇代码,请选择demo5 中间件实现 ...
- 彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-项目入口与路由EP01
书接上回,我们已经安装好Iris框架,并且构建好了Iris项目,同时配置了fresh自动监控项目的实时编译,万事俱备,只欠东风,彩虹女神蓄势待发.现在我们来看看Iris的基础功能,如何编写项目入口文件 ...
- 给缺少Python项目实战经验的人
我们在学习过程中最容易犯的一个错误就是:看的多动手的少,特别是对于一些项目的开发学习就更少了! 没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用 ...
- Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
随机推荐
- 面试HashMap你都扛不住,还想拿到offer?
当我们面试Java开发岗位时,面试官问的频率出现最多的问题,就是这个HashMap,不管是传统型公司还是互联公司,HashMap是必问的,所以作者爆肝整理了HashMap的23个问题以及答案,请查收! ...
- MongoDB索引的简单理解
目录 MongoDB索引 1.语法准备 2.数据准备: 3.索引 3.1 唯一索引 3.2 单键索引 3.3 多键索引 3.4 复合索引 3.5 交叉索引 3.6 部分索引 3.7覆盖索引 3.8 全 ...
- git实战-linux定时监控github更新状态(二)
系列文章 git介绍-常用操作(一)✓ git实战-linux定时监控github更新状态(二)✓ 本文主要内容 如何查看github的本地仓库和远程仓库的同步情况 linux服务器定时监控githu ...
- Hyper-V + WSL2与 VirtualBox 共存
Hyper-V + WSL2与 VirtualBox 共存 这样的教程网上有很多,我先简单复述一下.真正麻烦的是我遇到的问题--开启 Hyper-V 后我的电脑会多出几个删不掉的虚拟显示器来,会在文章 ...
- PHP中环境变量的操作
在 PHP 中,我们可以通过 phpinfo() 查看到当前系统中的环境变量信息(Environment).在代码中,我们也可以通过两个函数,查看和修改相应的环境变量信息. getenv() 获取环境 ...
- Java面向对象系列(6)- 封装详解
封装 该露的露,该藏得藏 我们程序设计要追求"高内聚,低耦合".高内聚就是类得内部数据操作细节自己完成,不允许外部干涉:低耦合:仅暴露少量得方法给外部使用 封装(数据得隐藏) 通常 ...
- python列表底层实现原理
Python 列表的数据结构是怎么样的? 书上说的是:列表实现可以是数组和链表.顺序表是怎么回事?顺序表一般是数组. 列表是一个线性的集合,它允许用户在任何位置插入.删除.访问和替换元素.列表实现是基 ...
- P4180-[BJWC2010]严格次小生成树【Kruskal,倍增】
正题 题目链接:https://www.luogu.com.cn/problem/P4180 题目大意 \(n\)个点\(m\)条边的一张无向图,求它的严格次小生成树. \(1\leq n\leq 1 ...
- Erase-Remove 惯用法
看到<Effective STL>条款 9 的时候想到了我以前复习的"如何正确使用迭代器删除元素",我面试时使用的也是里面的方法,看面试官的反应好像也没有什么问题,还问 ...
- 现代 C++ 对多线程/并发的支持(上) -- 节选自 C++ 之父的 《A Tour of C++》
本文翻译自 C++ 之父 Bjarne Stroustrup 的 C++ 之旅(A Tour of C++)一书的第 13 章 Concurrency.用短短数十页,带你一窥现代 C++ 对并发/多线 ...