单片机超声波测距模块原理与源码解析

单片机超声波测距模块原理与源码解析,第1张


一、实验原理


​ 1、根据超声波测距模块提供的数据手册,都会有时序图,模拟出对应时序,在指定时间内读出相应数据,其实计算公式就是s=(1/2)*(340/t),340是超声波在空气中传递的速度,当然可能会有些误差,一般情况下,返回的数据都需要加工(按一定数学关系转化),才能变成真正需要的数据,所以看懂时序图很重要。


​ 2、转化后的数据就可以通过串口发送给对应的显示外设,例如LCD,OLED之类的,这里就先用串口助手显示了。


​ 3、根据返回的数据,可以设定一个阈值,当距离小于一个值或者大于一个值时,让它进行相应的动作。


(我们在这里设置的测量的最远距离以及测量的最近距离,分别为)

需要注意的几点:

​ 1、测量距离的结果有三种状态,距离太近、量程范围内、距离太远,根据三种不同状态的判断,执行不同的功能;具体功能,程序中有体现。


​ 2、晶振要匹配,使用不同晶振时只需要在对应位置程序上修改即可。



二、关键程序

程序的主要流程:

//模块初始化函数

extern void InitUltrasonicDistance(void);

1,初始化定时器0

2,设置一个10ms的定时器溢出值

3,由于每次测距完成之后需要延时>60ms,所以直接我们在计时完成以后直接将计时器的高低位寄存器TH0与 TL0置0即可,这样最后溢出后时间为65535us合计65.535ms,符合要求,并将延时标志位mbDelayOverFlg置1

//获取最近一次的距离

extern unsigned int getDistance(void);

返回测量保存变量miDistance(单位为cm,后面具体说怎么转换)

//获取最近一次的测距状态

extern unsigned int getDistanceState(void);

返回状态保存变量mcDistanceErr(定义的三个值,0是正常,1是太近,2是太远)

//发送声波

void StartModule()

将超声波模块的TX引脚口保持高电平22us,us比较短,所以这里直接采用暴力编程调用22个_nop_(); 每个_nop_();用时1us

//距离更新或者说是测量函数

extern unsigned char refreshDistance(void);

最外层是对延时标志位mbDelayOverFlg进行判断,mbDelayOverFlg为1那么表明延时完成,可以进行本次测量;反之如果为0,则要等待延时结束才能进行本次测量。


以最远量程对应的计数值(iMAX_LEN)为终值进行计数并结合(!RX==0)进行判断,如果达到iMAX_LEN还没有信号返回,则判定为距离过远。


结合最远量程一起判断这样就避免了(!RX)迟迟不为0的话会陷入死循环的情况

iMAX_LEN内RX=1则表明收到的回波,判断结束,关闭计数器后,将计数器的高低8位进行处理,并复位计时器等待下次使用。


将计数值与事先定义好的最近距离计数值(iMIN_LEN)比较。


如果计数值小于iMIN_LEN,那么需要进行一个10ms的延时复位(10ms足以保证近距离的回波消失,不必延时60ms)并将延时标志位mbDelayOverFlg置0,打开计时器

如果计数值合适则直接将计数值转化为距离即可,后续 *** 作与距离近一样,将延时标志位mbDelayOverFlg以及定时器高低位置0,打开计时器

测量完成后refreshDistance(void)返回1代表测量完成,如果函数返回0那么表示延时标志位为o,即正在延时等待下次测距的开始

然后来解释一下刚刚说的关于换算的问题:

公式**s=(1/2)*(340/t)**中的s单位为m,t单位为s

在我们测量的时间是us,要求的一般以cm为单位输出的距离。


如果系统为12MHz晶振那么经过12分频后计数值等于单位时间,但是由于我们这里系统是11.0592MHz的晶振,所以计数值不等于时间。


11.0592MHz经过12分频以后,频率为(11.0592/12)代表每单位时间(us)的计数数,周期为(12/11.0592)代表每计数1次所用的时间。


这里的测量值便是计数值,所以求周期就需要用周期去乘。


以及之前提到的定时10ms,也要将时间与计数值进行转换

得到转换公式:(计数值 * 1.0851 * 0.17 / 10) => 计数值* 0.01844670 (单位:cm)

源码:

头文件定义的就是上述的几个函数,方便调用

(注释紊乱是编码的问题,复制到Keil5里选择ANSI编码就没问题了)

#include 		
#include 
#include "UltrasonicDistanceDriver.h"

sbit RX =P1^1; //Echo»Ø²¨Òý½Å
sbit TX =P1^2; //Trig´¥·¢ÐźſØÖƶË	

#define uchar unsigned char
/*1mËùÐèÖÜÆÚ:1000mm/(1΢ÃëµÄÉù²¨¾àÀëmm * 1ÖÜÆÚµÄusʱ¼ä) => 1000/(0.17*1.0851);
 *4m = 1000/(0.17*1.0851) * 4 =	21684*/    //ÒÔ11.0592MhzΪ¾§ÕñƵÂÊ£¬¼ÆÊýÒªÉÙÓÚÒÔ12MHzΪ¾§ÕñƵÂÊ£¬ËùÒÔ1.0851³ËÔÚ·Öĸ

#define iMAX_LEN 21684
#define iMIN_LEN 109
 
unsigned int miDistance=0; 			    //²â¾àµÄ¾àÀëÖµ
uchar mcDistanceErr=0; 					//²â¾à״̬±ê¼Ç(0:Õý³£ / 1:¾àÀëÌ«½ü /2:³¬Á¿³Ì)
bit mbDelayOverFlg = 1;					//ÑÓ³Ù³ÌÐòµÄ¿ØÖƱê¼Ç(ĬÈÏΪÑÓ³Ù½áÊø·ñÔòÎÞ·¨½øÈërefreshDistance()º¯Êý)
uchar mbDelay10H, mbDelay10L; 	        //²â¾àµÄСµ¥Î»Ê±¼äÑÓ³Ù
/*-------------------------------------------------------
 *³¬Éù²¨²â¾àÄ£¿é³õʼ»¯º¯Êý
 *@return void
 *-------------------------------------------------------*/
void InitUltrasonicDistance(void)
{
	unsigned int iTmp;
 
    TMOD |=0x01; //ÉèT0Ϊ·½Ê½1£¬GATE=1£»
	
	TH0=0; //¸ßλÖÃ0
	TL0=0; //µÍλÖÃ0
	TR0=0; //¿ªÊ¼Ç°ÏȹرռÆÊýÆ÷
	ET0=1; //ÔÊÐíT0ÖжÏ
	EA=1;  //¿ªÆô×ÜÖжÏ
 
	iTmp = (unsigned int)(65536-(10000/(12/11.0592))); //10msµÄÑÓ³ÙÌáÇ°¼ÆËã(ÒÔ12MHz¼ÆÊýµÄËÙ¶ÈΪ»ù×¼£¬ºÜÏÔÈ»11.0592MHzÔÚÏàͬʱ¼äϼÆÊýÒªÉÙ)
	mbDelay10H = iTmp >> 8; //¸ß8λֵ
	mbDelay10L = iTmp &0x0F; //µÍ8λֵ
}
 
/**-------------------------------------------------------
 * ¶¨Ê±Æ÷º¯Êý£¬T0¼ÆÊýÆ÷ʹÓÃ1ºÅÖжÏ
 * ×÷ÓãºÓÃÓÚÑÓ³Ù³ö·¢²â¾à£¬Ã¿´Î²â¾àÍê³Éºó£¬ÐèÒªÑÓ³Ù>60ms
 * Òò´Ëµ±¼ÆÊýÆ÷Òç³öʱ£¬time=65.535ms,mbDelayCtlFlg=1
 * ------------------------------------------------------- 
*/
void tim0_()interrupt 1 
{	
	TR0 = 0; 			//T0¹Ø±Õ¼ÆÊýÆ÷
	mbDelayOverFlg = 1; //É趨ÑÓ³Ù½áÊø
}
 
/*-------------------------------------------------------
 *Æô¶¯³¬Éù²¨²â¾àÄ£¿é£¬TX±£³Ö22usµÄ¸ßµçƽ
 *-------------------------------------------------------*/
void StartModule()
{
	TX = 1; //¿ØÖƶËÖÃ1
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	TX=0; //¿ØÖƶËÖÃ0£¬µÈ´ý½ÓÊջز¨
}
 
/*-------------------------------------------------------
 *»ñÈ¡×î½üÒ»´Î²âµÃµÄ¾àÀë
 *×¢Òâ:ÿ´Î³É¹¦²â¾à£¬ÐèÒªºÄʱ100ms-150ms×óÓÒʱ¼ä
 *-------------------------------------------------------*/
unsigned int getDistance(void)
{
	return miDistance;
}
 
/*-------------------------------------------------------
 *»ñÈ¡×î½üÒ»´ÎµÄ²â¾à״̬
 *@return unsigned int 0:Õý³£ / 1:(err)¾àÀëÌ«½ü /2:(err)³¬Á¿³Ì
 *-------------------------------------------------------*/
unsigned int getDistanceState(void)
{
	return mcDistanceErr;
}
 
unsigned char refreshDistance(void)
{
	unsigned int i;      //³¬Á¿³Ì¼ì²â±äÁ¿
	unsigned int iCycle; //¼ÆËã×ÜÖÜÆÚ
 
	if (1 == mbDelayOverFlg)//ÅжÏÊÇ·ñÔÚÑÓ³ÙÆÚ
	{	
		i = iMAX_LEN; //ÖÃÈë×î´óÁ¿³Ì
		StartModule(); //·¢ËͲâ¾àÄ£¿éÆô¶¯ÐźÅ
		/**
		 *   ´ËÓï¾äµÄ×÷ÓÃ:
		 *   ûÓÐÊÕµ½»Ø²¨ÇÒÔÚN(iMAX_LEN*N)Ã×ÕÏ°­ÎïÐźŷµ»ØÐèÒªµÄʱ¼äÇ°ÔòµÈ´ý
		 *   (ÎÞÐźż´Ê±·µ»Ø£¬·ÀÖ¹ËÀÑ­»·£¬×è°­ÆäËü³ÌÐòµÄÖ´ÐÐ)
		 */   //RX=0ʱ¼´´ú±íÎÞÐźÅ
		while(!RX && i-->0);
		//Åжϴ¦Àí½á¹û
		if (i>0) //СÓÚNÃ×(ÔÚÕâÀï²»¶Ôi½øÐÐÐ޸ĵÄÇé¿öÏ£¬N=4Ã×)
		{
			TR0=1; //ÊÕµ½»Ø²¨µÄÉϱßÑØ(RX=1)£¬´ò¿ª¼ÆÊýÆ÷
			while(RX);//µ±»Ø²¨RX=0ʱ£¬²â¾à½áÊø
			TR0=0; //¹Ø±Õ¶¨Ê±Æ÷£¨ÐèÒªÒ»¸öʱÖÓÖÜÆÚ£©
			iCycle = (TH0 * 256 + TL0) + 1; //¼ÆËã×ÜÏûºÄµÄÖÜÆÚ

			TH0=0;//¶¨Ê±Æ÷¸ßµÍλ¸´Î»
			TL0=0;
	
				if (iCycle <= iMIN_LEN)
				{
					mcDistanceErr = 1;//¾àÀëÌ«½ü
					/**
					 * ¾àÀ볬½ü£ºÖØÆôÑÓ³Ùʱ¼ä >10ms£¬±£Ö¤ÉÏÒ»¸öÉù²¨»Ø²¨ÒѾ­Ïûʧ
					 *           T0¼ÆÊýÆ÷ÖØ×°ÖµmbDelay10H, mbDelay10L£¬ÔÚInitUltrasonicDistance()³õʼ»¯º¯ÊýÖÐÉú³É
					 *           ÒѾ­ÌáÇ°¼ÆËãºÃÁË10ms
					 */
					mbDelayOverFlg = 0; //¸´Î»ÑÓ³Ù±êÖ¾
					TH0 = mbDelay10H;   //ÖØ×°¼ÆÊýÆ÷¸ß8λ
					TL0 = mbDelay10L;   //ÖØ×°¼ÆÊýÆ÷µÍ8λ
					TR0 = 1; //Æô¶¯ÑÓ³Ù¼ÆÊýÆ÷
				}
						else
						{   
							//(iCycle * 1.0851 * 0.17 / 10) => iCycle * 0.01844670 (ÓÉԭʼµÄ¼ÆË㹫ʽs=340t/2(m),us->sÇÒm->cm,½«Ô­Ê½x10^(-4,
							//Ç°ÃæµÄ¼ÆËãÓÃ(12MHzϵļÆÊý´ÎÊý/11.0592ϵļÆÊý´ÎÊý)=(12MHz/11.0592MHz)£¬¶øÔÚ11.0592ϼÆʱÕýÊÇiCycleµÄ¼ÆÊýÖµ
							miDistance = (unsigned int)(iCycle * 0.01844670);//(µ¥Î»cm)
							mcDistanceErr = 0;//²â¾àÕý³£Öµ
							/**
							 * Ò»´Î²â¾àÍê³ÉÐèÒªÑÓ³Ù>60msµÄʱ¼ä£¬±£Ö¤ÉÏÒ»¸öÉù²¨»Ø²¨ÒѾ­Ïûʧ
							 * Õâ¶ùʹÓÃ16λ¼ÆÊýÆ÷µÄÕû¸ö¿Õ¼ä£¬½«T0¼ÆʱÆ÷µÄ¸ßλÓëµÍλ¶¼ÖÃ0£¬ÕâÑùÒ»¹²¼Æʱ65.535ms>60ms,Âú×ãÒªÇó
							 */
							mbDelayOverFlg = 0; //¸´Î»ÑÓ³Ù±êÖ¾
							TH0 = 0; //T0£¬¸ßλ¹é0¸´Î»
							TL0 = 0; //T0£¬µÍλ¹é0¸´Î»
							TR0=1;//´ò¿ªT0ÑÓ³Ù¼ÆÊýÆ÷£¨´Ëʱ²»²â¾à£¬ËùÒÔ²»Ó°Ïì²â¾àµÄ¼ÆË㣩
						}
		}
		else 
			mcDistanceErr = 2; //³¬Á¿³Ì
 
		return 0; //Íê³É²â¾à²Ù×÷
	}
	else //ÕýÔÚÑӳٵȴýÏ´βâ¾àµÄ¿ªÊ¼
		return 1;
}

啰里啰嗦就说完了,有什么不对的地方欢迎各位大佬指出。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/578070.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存