程序有2個。。一個是自己搭的,一個是買的模塊。自己搭的測距能到1.6M,模塊能到4M。
模塊程序
void PLL_Init(void) //PLLCLK=2*OSCCLK*(SYNR+1)/(REFDV+1)
{ //PLLCLK=2*16M*(2+1)/(0+1)= 96M
SYNR = 0xC2; //總線頻率爲PLL頻率的一半48M
REFDV = 0xC0;
ECLKCTL &= ~0x80;
while(!(CRGFLG&0x08)); //自循環語句,等待時鐘頻率穩定後允許鎖相環時鐘作爲系統時鐘
CLKSEL=0x80; //選擇鎖相環頻率爲系統時鐘頻率
}
//-------------------------真#定時器初始化---------------------------------------------
void PIT_Init(void)
{
//----------------------定時10uS,控制採樣頻率---------------------------------------
PITMUX_PMUX0=0; //使用微計數器0
PITMTLD0 = 1; //微時鐘0設置爲99
PITLD0 = 239; //time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS.
//溢出時間爲 2 * 240 / 48000000 = 10us
}
uint Time = 0;
char Error_Flag = 0;
void delay(uint t)
{
while(t--);
}
float Ranging(void)
{
float Length = 0; //距離,單位釐米(CM?
int Count = 0;
PORTA_PA0 = 1;
delay(15);
PORTA_PA0 = 0;
while(1)
{
if(PORTA_PA1 == 1) break; //等待
if(PORTA_PA1 == 0) Count++;
if(Count >= 400){Error_Flag = 1;return 0;}
}
Time = 0;
PITCFLMT_PITE=1; //定時器使能
PITCE_PCE0=1; //定時器0使能
PITINTE_PINTE0=1; //定時器中斷0使能
EnableInterrupts //開中斷
while(1)
{
if(PORTA_PA1 == 0) break; //等待
if(Time >= 5000) {Error_Flag = 1;return 0;} //超時
}
DisableInterrupts //關中斷
Length = (float)((17*Time)/100.0); //340m/s * T
delay(0xffff); //延時避免干擾
delay(0xffff); //延時避免幹
delay(0xffff); //延時避免干擾
delay(0xffff); //延時避免干擾
return Length;
}
void main(void)
{
float Length_T = 0;
float Length = 0;
char Count = 3;
PLL_Init();
lcd_init();
PIT_Init();
//Send_Data(test,2,2);
DisableInterrupts //關中斷
DDRB_DDRB7 = 1; //test
DDRA_DDRA0 = 1; //超聲波控制A0
DDRA_DDRA1 = 0; //超聲波接受A1
for(;;)
{
while(Count--)
{
Length = (float)(Ranging()/3.0);
if(Error_Flag == 0) Length_T += Length;
if(Error_Flag == 1) Count += 1;
Error_Flag = 0;
}
Count = 3;
ClearScreen();
Show_Flaot(Length_T,2,2);
Length_T = 0;
}
}
#pragma CODE_SEG NON_BANKED
void interrupt 66 Timer1_IRQ(void) //5MS
{
PITTF_PTF0=1; //清中斷標誌位
Time++; //10us
}
自己搭的程序
uint Time = 0;
char Error_Flag = 0;
void delay(uint t)
{
while(t--);
}
float Ranging(void)
{
float Length = 0; //距離,單位釐米(CM)
Time = 0;
PITCFLMT_PITE=1; //定時器使能
PITCE_PCE0=1; //定時器0使能
PITINTE_PINTE0=1; //定時器中斷0使能
EnableInterrupts //開中斷
PWME_PWME0 = 1; //使能PWM輸出
//發送40KHz調製信號
delay(80);
PWME_PWME0 = 0;
delay(20); //延時避免干擾
while(1)
{
if(PORTA_PA0 == 0) break; //等待
if(Time >= 3000) {Error_Flag = 1;return 0;} //超時
}
DisableInterrupts //關中斷
Length = (0.17 * Time);//340m/s * T
delay(0xffff); //延時避免干擾
delay(0xffff); //延時避免干擾
delay(0xffff); //延時避免干擾
return Length;
}
void PLL_Init(void) //PLLCLK=2*OSCCLK*(SYNR+1)/(REFDV+1)
{ //PLLCLK=2*16M*(2+1)/(0+1)= 96M
SYNR = 0xC2; //總線頻率爲PLL頻率的一半48M
REFDV = 0xC0;
ECLKCTL &= ~0x80;
while(!(CRGFLG&0x08)); //自循環語句,等待時鐘頻率穩定後允許鎖相環時鐘作爲系統時鐘
CLKSEL=0x80; //選擇鎖相環頻率爲系統時鐘頻率
}
void PWM_Init(void)
{
PWMCTL = 0xA0; //PWM 23 級聯(前輪舵機) PWM 67 級聯(搖頭舵機)
//PWM 4 PWM5 做電機控制(正反轉)
PWMCAE = 0x00; //PWM 左對齊輸出
PWMPOL = 0x01; //PWM 極性爲1
PWMCLK = 0x01; //PWM 0 選擇時鐘源 SA
PWMPRCLK = 0x32; //時鐘源 A = 48M/4 = 12M
//時鐘源 B = 48M/8 = 6M
PWMSCLA = 0x01; //時鐘源SA = A/(2*1) = 6M
PWMSCLB = 0x01; //時鐘源SB = B/(2*1) = 3M
//-----------------超聲波驅動--------------
PWMPER0 = 150; //頻率40KHz
PWMDTY0 = 75; //50%
PWME_PWME0 = 0; //禁止PWM輸出
}
//-------------------------真#定時器初始化---------------------------------------------
void PIT_Init(void)
{
//----------------------定時10uS,控制採樣頻率---------------------------------------
PITMUX_PMUX0=0; //使用微計數器0
PITMTLD0 = 1; //微時鐘0設置爲99
PITLD0 = 239; //time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS.
//溢出時間爲 2 * 240 / 48000000 = 10us
}
void main(void)
{
float Length_T = 0;
float Length = 0;
char Count = 3;
PLL_Init();
PWM_Init();
lcd_init();
PIT_Init();
//Send_Data(test,2,2);
DisableInterrupts //關中斷
DDRB_DDRB7 = 1; //test
DDRA_DDRA1 = 0; //超聲波接受
PWME_PWME0 = 1;
for(;;)
{
while(Count--)
{
Length = (Ranging()/10.0);
if(Error_Flag == 0) Length_T += Length;
if(Error_Flag == 1) Count += 1;
Error_Flag = 0;
}
Count = 10;
ClearScreen();
Send_Data((int)Length_T,2,2);
lcd_putsf("CM",25,2);
Length_T = 0;
}
}
#pragma CODE_SEG NON_BANKED
void interrupt 66 Timer1_IRQ(void) //5MS
{
DisableInterrupts //關中斷
PITTF_PTF0=1; //清中斷標誌位
Time++; //10us
EnableInterrupts //開中斷
}
拿去吧,電路圖.....