凌阳超声波测距
/=/ 文件名称: 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_buf6,uiTemp; unsigned int uiSystem_Clock; for(;uiMeasure_Index<6;uiMeasure_Index+) /循环进行四次测量 uiTemp = measure_ult(type); /进行一次测量,测量类型由type决定 if(uiMeasure_Index=0) /如果为本次测量的第一次测距,则直接保存在缓冲区第一个单元 uiTemp_buf0 = uiTemp; else /否,则对结果进行比较,进行排序,从大到小排 i = uiMeasure_Index; while(i) /以下为排序的代码 if(uiTemp>uiTemp_bufi-1) uiTemp_bufi = uiTemp_bufi-1; uiTemp_bufi-1 = uiTemp; else uiTemp_bufi = 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_buf5=0) /如果缓冲区中的最小的测距值为0,则采用中间4个数据进行平均 uiResoult = uiTemp_buf1+uiTemp_buf2+uiTemp_buf3+uiTemp_buf4; uiResoult = uiResoult/4; else /否则就取后5个数据进行平均 uiResoult = uiTemp_buf1+uiTemp_buf2+uiTemp_buf3+uiTemp_buf4+uiTemp_buf5; uiResoult = uiResoult/5; return uiResoult;