?? ultrasonic_app.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 + -