基于蓝桥杯的单片机模块练习——超声波测距
功能概述
利用超声波模块测量距离并显示在数码管的后三位,单位是cm。如果距离超出量程,就在第一位显示‘F’
#include "stc15f2k60s2.h"
/*
Debug 总结:
*/
sbit TX = P1^0; // 发射引脚
sbit RX = P1^1; // 接收引脚
unsigned char code SMG_duanma[] = {0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,
0xbf,0x7f
};
unsigned char Segbuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned int distance = 0;
bit flag = 0;
void SelectHC573(unsigned char channel)
{
switch(channel)
{
case 0 : P2 = (P2 & 0X1F) | 0X00;break;
case 4 : P2 = (P2 & 0X1F) | 0X80;break;
case 5 : P2 = (P2 & 0X1F) | 0Xa0;break;
case 6 : P2 = (P2 & 0X1F) | 0Xc0;break;
case 7 : P2 = (P2 & 0X1F) | 0Xe0;break;
}
}
void InitSystem()
{
SelectHC573(5);
P0 = 0x00;
SelectHC573(4);
P0 = 0xFF;
SelectHC573(0);
}
void DispalySMG_Bit(unsigned char pos, unsigned char dat)
{
/**********消隐效果最佳******************/
SelectHC573(7);
P0 = 0xff;//关闭所有段选
SelectHC573(6);
P0 = 0x01 << pos;
SelectHC573(0);
P0 = 0xff;
SelectHC573(7);
P0 = dat;
SelectHC573(0);
/**********消隐效果最佳******************/
}
void Timer1_Init()
{
TMOD = 0X00;
TH1 = (65536 - 1000) / 256;
TL1 = (65536 - 1000) % 256;
EA = 1;
ET1 = 1;
TR1 = 1;
}
void Measure_Distance()
{
unsigned char num = 10;//??个方波信号
unsigned int time = 0;
TMOD &= 0xf0;
//方波信号的频率要在38-40khz,所以用定时器0制造一个周期为26us的占空比为50%的方波信号
TH0 = (65536 - 13) / 256;
TL0 = (65536 - 13) % 256;
TR0 = 1;
TX = 0;
while(num--)//连续发送8个波
{
while(TF0 == 0);
TX = ~TX;
TF0 = 0;
}//花费大约208us
TR0 = 0;//发送完信号立即关闭定时器
TL0 = 0; // 设置定时初值
TH0 = 0; // 设置定时初值
TR0 = 1;
while((RX == 1) && (TF0 == 0)); //等待超声波信号返回或者等到测量超出范围
TR0 = 0; //停止定时器
if(TF0 == 0) //正常测量范围
{
time = TH0;
time = (time << 8) | TL0;
distance = time*0.017;//单位是cm,计算方法是:【(time/1000000)*340】/2*100
}
else //超出测量范围
{
TF0 = 0;
distance = 9999;
}
}
void Display_Distance()
{
if(distance == 9999)
{
Segbuff[0] = SMG_duanma[15]; //超出测量范围标志:F
Segbuff[1] = 0xff;
Segbuff[2] = 0xff;
Segbuff[3] = 0xff;
Segbuff[4] = 0xff;
Segbuff[5] = 0xff;
Segbuff[6] = 0xff;
Segbuff[7] = 0xff;
}
else
{
Segbuff[0] = 0xff;
Segbuff[1] = 0xff;
Segbuff[2] = 0xff;
Segbuff[3] = 0xff;
Segbuff[4] = 0xff;
Segbuff[5] = SMG_duanma[distance / 100];
Segbuff[6] = SMG_duanma[(distance % 100) / 10];
Segbuff[7] = SMG_duanma[distance % 10];
}
}
void main()
{
InitSystem();
Timer1_Init();
while(1)
{
if(flag)//间隔200ms测量一次数据
{
Measure_Distance();
flag = 0;
}
Display_Distance();
}
}
void Timer1_Service() interrupt 3
{
static unsigned char pos = 0;
static unsigned char t_1ms = 0;
t_1ms++;
switch(pos)
{
case 0 : DispalySMG_Bit(pos, Segbuff[0]);pos++;P0 = 0XFF;break;
case 1 : DispalySMG_Bit(pos, Segbuff[1]);pos++;P0 = 0XFF;break;
case 2 : DispalySMG_Bit(pos, Segbuff[2]);pos++;P0 = 0XFF;break;
case 3 : DispalySMG_Bit(pos, Segbuff[3]);pos++;P0 = 0XFF;break;
case 4 : DispalySMG_Bit(pos, Segbuff[4]);pos++;P0 = 0XFF;break;
case 5 : DispalySMG_Bit(pos, Segbuff[5]);pos++;P0 = 0XFF;break;
case 6 : DispalySMG_Bit(pos, Segbuff[6]);pos++;P0 = 0XFF;break;
case 7 : DispalySMG_Bit(pos, Segbuff[7]);pos = 0;P0 = 0XFF;break;
}
if(t_1ms == 200)
{flag = 1;t_1ms = 0;}
}
相关知识点
使用超声波模块之前记得要短接1、3和短接2、4
注意:一定要间隔一段时间再测量距离,本例程中间隔了200ms。如果在while循环里不断地使用测量函数的话,会造成数码管显示在一直跳变。
原因是,上一次的数据刚测量完成,还没来得及显示稳定,有立马执行了Measure_Distance()函数,这样就吧time立即重新定义为了0,由于单片机速度很快,这样就会表现在数码管在000和测量值快速的跳变,你根本看不出结果是多少。