⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ultrasonic_app.c

📁 凌阳单片机之超声波测距模组
💻 C
字号:
//========================================================================
//	文件名称:	ultrasonic_App.c
//	功能描述:	超声波测距模组V2.0的功能接口函数
//	维护记录:	2006-02-21	V2.0
//========================================================================
#include "SPCE061A.h"
#define LONG_SEND_TIMER		1000		//中距测距时的40KHz信号发射时长
#define LONG_SEND_TIMER2	3000		//中距测距的补充测距时的40KHz信号发射时长
#define LONG_WAIT_DELAY		600			//中距测距的防余波干扰延时时长
#define LONG_WAIT_DELAY2	1500		//中距测距的补充测距时的防余波干扰延时时长
#define LONG_RES_ADD		0x00B0		//中距测距的结果补偿值
#define LONG_RES_ADD2		0x0220		//中距测距的补充测距时的结果补偿值

#define LOW_SEND_TIMER		250			//短距测距时的40KHz信号发射时长
#define LOW_SEND_TIMER2		1000		//短距测距的补充测距时的40KHz信号发射时长
#define LOW_WAIT_DELAY		180			//短距测距的防余波干扰延时时长
#define LOW_WAIT_DELAY2		400			//短距测距的补充测距时的防余波干扰延时时长
#define LOW_RES_ADD			0x0034		//短距测距的结果补偿值
#define LOW_RES_ADD2		0x00B0		//短距测距的补充测距时的结果补偿值

unsigned int Counter_buf;				//超声波测距当中,用于保存TimerB计数的变量,相当于时长
unsigned int EXT1_IRQ_flag=0;			//外部中断标志变量,用于EXT1的IRQ中断程序和测距程序同步
//========================================================================
//	语法格式:	void Initial_ult(void)
//	实现功能:	超声波测距模组的初始化子程序
//	参数:		无
//	返回值:	无
//========================================================================
void Initial_ult(void)
{
	unsigned int uiTemp;
	//									初始化端口主要是IOB8和IOB9
	uiTemp = *P_IOB_Dir;
	uiTemp = uiTemp|0x0200;
	uiTemp = uiTemp&0xfeff;
	*P_IOB_Dir = uiTemp;
	uiTemp = *P_IOB_Attrib;
	uiTemp = uiTemp|0x0200;
	uiTemp = uiTemp&0xfeff;
	*P_IOB_Attrib = uiTemp;
	uiTemp = *P_IOB_Buffer;
	uiTemp = uiTemp|0x0300;
	*P_IOB_Data = uiTemp;
}
//========================================================================
//	语法格式:	void Delay_ult(unsigned int timers)
//	实现功能:	超声波测距模组的延时子程序
//	参数:		unsigned int timers    延时的时长(仅是一个相对量)
//	返回值:	无
//========================================================================
void Delay_ult(unsigned int timers)
{
	unsigned int i;
	for(i=0;i<timers;i++)
	{
		__asm("nop");
	}
}
//========================================================================
//	语法格式:	unsigned int Resoult_ult(unsigned int Counter)
//	实现功能:	超声波测距模组的测距数据处理程序,将TimerB的计数值换算为距离
//	参数:		Counter	需要换算的计数值
//	返回值:	计算后的距离,厘米为单位
//========================================================================
unsigned int Resoult_ult(unsigned int Counter)
{
	unsigned int uiTemp;
	unsigned long ulTemp;
	ulTemp = (unsigned long)Counter*33500;
	ulTemp = ulTemp/196608;
    ulTemp = ulTemp>>1;					//除二
	uiTemp = (unsigned int)ulTemp;
	return uiTemp;
}
//========================================================================
//	语法格式:	unsigned int measure_ult(unsigned int type)
//	实现功能:	超声波测距模组的测距程序,完成一次测距
//	参数:		type	选择测距类型,
//				type=1		中距测距
//				type=0		短距测距
//	返回值:	所测得的距离,以厘米为单位
//========================================================================
unsigned int measure2_ult(unsigned int type);
unsigned int measure_ult(unsigned int type)
{
	unsigned int Exit_flag = 1;
	unsigned int uiTemp;
	unsigned int uiResoult;
	unsigned int uiSend_Timer,uiWait_Timer,uiRes_Add;
	unsigned int uiSystem_Clock;
	uiSystem_Clock = *P_SystemClock;	//将当前的系统时钟设置暂时保存起来
	*P_SystemClock = 0x0088;			//将系统时钟设置为49MHz,分频比为1,强振模式
	if(type)							//根据type即测距类型,选择不同的测距参数
	{
		uiSend_Timer = LONG_SEND_TIMER;
		uiWait_Timer = LONG_WAIT_DELAY;
		uiRes_Add = LONG_RES_ADD;
	}
	else
	{
		uiSend_Timer = LOW_SEND_TIMER;
		uiWait_Timer = LOW_WAIT_DELAY;
		uiRes_Add = LOW_RES_ADD;
	}
	*P_TimerB_Data = 0xfed2;
	*P_TimerB_Ctrl = 0x03c0;			//enable 40KHz out
	Delay_ult(uiSend_Timer);			//delay for send the signal
	*P_TimerB_Ctrl = 0x0006;			//stop 40KHz out
	*P_TimerB_Data = 0x0000;
	*P_TimerB_Ctrl = 0x0001;			//TimerB work as a counter at 192KHz
	while(*P_TimerB_Data<uiWait_Timer)	//等待一定时间后再打开TimerA的计数(来源于EXT1)
	{									//以避开余波的干扰
		*P_Watchdog_Clear = 0x0001;
	}
	*P_INT_Clear = 0x0100;					//开中断前先清中断
	*P_INT_Ctrl = *P_INT_Ctrl_New|0x0100;
	*P_INT_Clear = 0xffff;				//清除中断发生标志
	__asm("IRQ ON");					//打开总中断使能
	EXT1_IRQ_flag = 0;					//TimerA的溢出中断的标志变量置0
	while(Exit_flag)
	{
		if(EXT1_IRQ_flag==1)			//当该变量在timerA的FIQ中断中被置1时表示接收到了回波
		{
			Exit_flag = 0;				//exit
			Counter_buf = Counter_buf+uiRes_Add;//计数值加上一定的调整数据
			uiResoult = Resoult_ult(Counter_buf);//对计数值进行处理,得出距离值
		}
		if(*P_TimerB_Data>10000)		//如计数值大于10000,表示超时
		{
			Exit_flag = 0;				//exit
			uiResoult = measure2_ult(type);//再进行一次补充的测距,将会加长40KHz信号发射的量
			*P_TimerB_Ctrl = 0x0006;	//stop timerB
		}
		uiTemp = *P_TimerB_Data;
		*P_Watchdog_Clear = 0x0001;
	}
	*P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100);	//关掉外部中断
	__asm("IRQ OFF");					//关掉总中断
	
	*P_SystemClock = uiSystem_Clock;	//恢复系统时钟的设置
	return uiResoult;
}
//========================================================================
//	语法格式:	void EXT1_IRQ_ult(void)
//	实现功能:	超声波测距模组的测距程序的EXT1中断服务程序,在EXT1的IRQ中断
//				中调用
//	参数:		无
//	返回值:	无
//========================================================================
void EXT1_IRQ_ult(void)
{
	Counter_buf = *P_TimerB_Data;		//save the timerB counter
	*P_TimerB_Ctrl = 0x0006;			//stop timerB
	*P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100);	//关掉外部中断
	*P_INT_Clear = 0xffff;				//清除中断发生标志
	EXT1_IRQ_flag = 1;					//通知测距程序,外部中断已发生
}
//========================================================================
//	语法格式:	unsigned int measure2_ult(void)
//	实现功能:	补充进行一次远距的测量,以保证能够获取测量结果
//	参数:		type	选择测距类型,
//				type=1		中距测距
//				type=0		短距测距
//	返回值:	所测得的距离,以厘米为单位
//========================================================================
unsigned int measure2_ult(unsigned int type)
{
	unsigned int Exit_flag = 1;
	unsigned int uiResoult;
	unsigned int uiSend_Timer,uiWait_Timer,uiRes_Add;
	*P_TimerA_Ctrl = 0x0006;			//stop TimerA

	*P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100);	//关掉外部中断
	__asm("IRQ OFF");					//关掉总中断
	*P_INT_Clear = 0xffff;				//清除掉中断发生标志
	
	if(type)							//根据type即测距类型,选择不同的测距参数
	{
		uiSend_Timer = LONG_SEND_TIMER2;
		uiWait_Timer = LONG_WAIT_DELAY2;
		uiRes_Add = LONG_RES_ADD2;
	}
	else
	{
		uiSend_Timer = LOW_SEND_TIMER2;
		uiWait_Timer = LOW_WAIT_DELAY2;
		uiRes_Add = LOW_RES_ADD2;
	}
	*P_TimerB_Data = 0xfed2;
	*P_TimerB_Ctrl = 0x03c0;			//enable 40KHz out
	Delay_ult(uiSend_Timer);			//delay for send the signal
	*P_TimerB_Ctrl = 0x0006;			//stop 40KHz out
	*P_TimerB_Data = 0x0000;
	*P_TimerB_Ctrl = 0x0001;			//TimerB work as a counter at 192KHz
	while(*P_TimerB_Data<uiWait_Timer)	//等待一定时间,以避开余波的干扰
	{
		*P_Watchdog_Clear = 0x0001;
	}

	*P_INT_Ctrl = *P_INT_Ctrl_New|0x0100;//打开外部中断
	*P_INT_Clear = 0xffff;				//清除中断发生标志
	__asm("IRQ ON");					//打开总中断使能
	
	EXT1_IRQ_flag = 0;					//TimerA的溢出中断的标志变量置0
	while(Exit_flag)
	{
		if(EXT1_IRQ_flag==1)			//当该变量在timerA的FIQ中断中被置1时表示接收到了回波
		{
			Exit_flag = 0;				//exit
			Counter_buf = Counter_buf+uiRes_Add;//计数值加上一定的调整数据
			uiResoult = Resoult_ult(Counter_buf);//对计数值进行处理,得出距离值
		}
		if(*P_TimerB_Data>10000)		//如计数值大于10000,表示超时
		{
			Exit_flag = 0;				//exit
			uiResoult = 0;				//error return data 0
			*P_TimerB_Ctrl = 0x0006;	//stop timerB
		}
	}
	return uiResoult;
}
//========================================================================
//	语法格式:	unsigned int measure_Times(unsigned int type)
//	实现功能:	组合进行共6次的测距程序,包括对6次测量结果的取平均值处理
//	参数:		type	选择测距类型,
//				type=1		中距测距
//				type=0		短距测距
//	返回值:	所测得的距离,以厘米为单位
//========================================================================
unsigned int measure_Times(unsigned int type)
{
	unsigned int uiResoult=0,uiMeasure_Index=0,i;
	unsigned int uiTemp_buf[6],uiTemp;
	unsigned int uiSystem_Clock;
	
	for(;uiMeasure_Index<6;uiMeasure_Index++)
	{											//循环进行四次测量
		uiTemp = measure_ult(type);				//进行一次测量,测量类型由type决定
		if(uiMeasure_Index==0)					//如果为本次测量的第一次测距,则直接保存在缓冲区第一个单元
			uiTemp_buf[0] = uiTemp;		
		else
		{										//否,则对结果进行比较,进行排序,从大到小排
			i = uiMeasure_Index;
			while(i)							//以下为排序的代码
			{
				if(uiTemp>uiTemp_buf[i-1])
				{
					uiTemp_buf[i] = uiTemp_buf[i-1];
					uiTemp_buf[i-1] = uiTemp;
				}
				else
				{
					uiTemp_buf[i] = uiTemp;
					break;						//退出排序
				}
				i--;
			}
		}
		//两次测量之间的延时等待,利用以下代码软仿真时的cycles数结合设置的CPUCLK进行计算,大概72ms
		uiSystem_Clock = *P_SystemClock;		//将之前的系统时钟的设置用变量保存
		*P_SystemClock = 0x000b;				//设置为FSYS=24.576MHz  分频比为8
		for(i=0;i<5;i++)
		{
			Delay_ult(1000);						//调用延时程序
			*P_Watchdog_Clear = 0x0001;
		}
		*P_SystemClock = uiSystem_Clock;		//恢复系统时钟设置
		//此处延时结束
	}
	//对6次测距的结果进行处理
	if(uiTemp_buf[5]==0)
	{											//如果缓冲区中的最小的测距值为0,则采用中间4个数据进行平均
		uiResoult = uiTemp_buf[1]+uiTemp_buf[2]+uiTemp_buf[3]+uiTemp_buf[4];
		uiResoult = uiResoult/4;
	}
	else
	{											//否则就取后5个数据进行平均
		uiResoult = uiTemp_buf[1]+uiTemp_buf[2]+uiTemp_buf[3]+uiTemp_buf[4]+uiTemp_buf[5];
		uiResoult = uiResoult/5;
	}
	return uiResoult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -