原创 超声波摸组

2007-8-11 20:19 1589 1 1 分类: 软件与OS

#include "SPCE061A.h"
#include "ultrasonic_App.h"


//========================================================================
// 语法格式: int main(void)
// 实现功能: 主程序
// 参数:  无
// 返回值: int 无意义
//========================================================================
void F_Key_Scan_Initial(void);
void F_Key_Scan_ServiceLoop(void);
unsigned int SP_GetCh(void);


void Speech_Resource(unsigned int iSpeechIndex);
void Speech_Result(unsigned int uiResult);
int main(void)
{
 unsigned int uiKey;
 unsigned int Back_data;
 
 F_Key_Scan_Initial();
 Initial_ult();
 while(1)
 {
  uiKey = SP_GetCh();
  switch(uiKey)
  {
   case 0: break;
   case 1:
    Back_data = measure_Times(0);
    if(Back_data==0)
     Speech_Resource(12);  //结果为0时表示测量出错,播放"咚"
    else
     Speech_Result(Back_data);
    break;
   case 2:
    break;
   case 3: break;
   default: break;
  }
  F_Key_Scan_ServiceLoop();
  *P_Watchdog_Clear = 0x0001;
 }   
}


/========================================================================
// 文件名称: 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;             //IOB9  111 ;  IO8 001
}
//========================================================================
// 语法格式: 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中的值怎么是一样的我想通了
 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 = uiTemp_buf[i-1];
     uiTemp_buf[i-1] = uiTemp;
    }
    else
    {
     uiTemp_buf = 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;
}

文章评论0条评论)

登录后参与讨论
我要评论
0
1
关闭 站长推荐上一条 /2 下一条