#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define Open_Ultrasound() DDRD |= BIT(PD7) //开启超声波发射
#define Close_Ultrasound() DDRD &= ~BIT(PD7) //关闭超声波发射
//清零定时器 复位预分频器 开启计数器 允许输入捕获中断 8M 晶振下 8分频 获得 1us 时基
#define Start_T1() TCNT1=0;SFIOR |= BIT(PSR10);TCCR1B |= BIT(CS11);TIFR |= BIT(OCF1A)|BIT(ICF1);TIMSK |= BIT(TICIE1)
//关闭T1 关闭输入捕获中断
#define Stop_T1() TCCR1B &= ~BIT(CS11);TIMSK &= ~BIT(TICIE1)
unsigned char Flag_TimeoUt; //超声波接收超时
unsigned char Flag_RecevOk; //超声波接受正常
void Ultrasound_Init(void)
{
TCCR1B |= BIT(WGM12); //设置T1工作模式 为比较匹配
OCR1A = 65535; //设置为 65ms 超时 最大测量距离约为10M 一般不会超过这个
TIMSK |= BIT(OCIE1A); //溢出(超时) 中断
TCCR2 = BIT(COM20)|BIT(WGM21)|BIT(CS20); //T2 使用 CTC模式 不预分频
OCR2 = 99; //PWM 输出 40000Hz
//OCR2=104; //PWM 输出 38000Hz
}
unsigned char GetDistant(unsigned int *Distance) //距离计算函数
{
Flag_TimeoUt = 0;
Flag_RecevOk = 0;
//启动超声波发射
Open_Ultrasound();
delay_250us(); //放出约10个周期的超声波 周期 t = 1/40000 ~ 25us 所以在250us这个时间内 超声波约走了 d = 346.5*250/10000(25 摄氏度) = 8.7cm 的路程
//关闭超声波发射
Close_Ultrasound();
delay_50us();
delay_50us();
delay_50us(); //还要继续延时约300us 走路程为两个超声波头间距离的时间 我设计的电路板 连个超声波头间距为8cm 那么最好延时 250us 以上
//总体上 超声波盲区 (测量出错区) 约为 (250 + 150)/10000*344 cm = 13.76cm(大概减少发送超声波的周期数可以缩短盲区 不过这样会减少测量的最大距离 这里只是我个人的实验结果,如有错误,请指正)
//开启定时器
Start_T1();
//等待超声波返回 或者 超时
while((!Flag_TimeoUt) && (!Flag_RecevOk));
if(Flag_TimeoUt)
{
return 0;
}
else
{
//计算距离
*Distance = (unsigned int)(((ICR1 + 400 + 2)/2)*3.44)/10; //ICR1 + 前面延时的时间 + 指令执行的时间
}
return 1;
}
#pragma interrupt_handler TIMER1_CAPT:6
void TIMER1_CAPT(void) //超声波接收中断
{
Stop_T1(); //关闭计数器
Close_Ultrasound();
Flag_RecevOk = 1;
}
#pragma interrupt_handler TIMER1_COMPA:7
void TIMER1_COMPA(void) //超声波接收超时中断
{
Stop_T1(); //关闭计数器
Close_Ultrasound();
Flag_TimeoUt = 1;
}