版权声明:让结局不留遗憾,让过程更加完美。 https://blog.csdn.net/Xiaomo_haa/article/details/88081708
关于超声波这一部分,在省赛阶段是不会考的,在国赛可能会考。
关于超声波这一块,具体原理就是,使用单片机发送8个40KHz的脉冲,然后开启定时器计时,计算从发送到接收的时间,然后当接受管脚接收到回波之后就会被拉低,这时候关闭定时器,就可以算出距离。
所以我们在超声波这一块,还涉及定时器。
但是定时器的程序很简单。
下面是发送脉冲的程序
#define sonic_nop {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();};
void SendSonic(void)
{
unsigned char i = 8;
while(i --)
{
TX = 1;
sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
TX = 0;
sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
}
}
然后检测是否接收到的程序
#include "sys.h"
bit flag_125ms = 0;
void main(void)
{
uint t, distance = 0;
All_Init();
Time0_Init();
Timer1Init();
EA = 1;
while(1)
{
if(flag_125ms)
{
flag_125ms = 0;
SendSonic(); //发送50KHz的超声波
TR1 = 1; //开启定时器1计时
while((RX == 1) && (TF1 == 0)); //如果接收到回波或者定时器1溢出
TR1 = 0; //关闭定时器1
if(TF1 == 1)
{
TF1 = 0;
distance = 999; //距离999
}
else
{
t = TH1;
t <<= 8;
t |= TL1;
distance = (uint)(t * 0.017);
}
Deal_distance(distance);
TH1 = 0;
TL1 = 0;
}
}
}
定时器程序
#include "sys.h"
//关闭所有外设
void All_Init(void)
{
P2 = (P2 & 0x1f) | 0x80; //打开Y4C(LED)
P0 = 0xff; //关闭LED
P2 = (P2 & 0x1f) | 0xe0; //打开Y7C(数码管)
P0 = 0xff; //关闭数码管
P2 = (P2 & 0x1f) | 0xa0; //打开Y5C
P0 = 0x00; //关闭蜂鸣器、继电器
P2 = P2 & 0x1f;
}
//定时器0初始化
void Time0_Init(void)
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xcd; //设置定时初值1ms
TH0 = 0xd4; //设置定时初值1ms
TF0 = 0; //清除TF0标志
ET0 = 1; //允许定时器0中断
TR0 = 1; //定时器0开始计时
}
//定时器0中断程序
void Time0(void) interrupt 1
{
static uint t0 = 0;
static uchar index = 0;
t0 ++;
if(t0 == 125)
{
t0 = 0;
flag_125ms = 1;
Led_illume(0xfe << index);
index ++;
index &= 0x07;
}
Nixie_Show();
Nixie_Scan();
}
void Timer1Init(void) //0微秒@11.0592MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0; //设置定时初值
TH1 = 0; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0;
}
在这里说一下我刚刚调试程序时遇到的问题,我在定义定时器1时是这样写的
void Timer1Init(void) //0微秒@11.0592MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0; //设置定时初值
TH1 = 0; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0;
ET1 = 1;
}
在这里我允许了定时器1中断,但是我并没有写定时器1中断服务程序,然后在正常接收到回波时正常,一旦定时器1溢出,程序就会卡死,后来就发现不需要允许定时器1中断,即如下面这样写就可以了。。
void Timer1Init(void) //0微秒@11.0592MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0; //设置定时初值
TH1 = 0; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0;
}
坑爹啊坑爹!