㈠ 51单片机编写不同距离发出不同信号的程序
程序?
你会超声波测距程序嘛?
会就行啦!
还有,你说的震动的信号,那你得搭一个小马达才行啊,用手机的小马达就可以了。
至于闪光信号,接个LED搞定。
㈡ 求个51单片机超声波测距(距离+报警)的c程序
//晶振=8M
//MCU=STC10F04XE
//P0.0-P0.6共阳数码管引脚
//Trig = P1^0
//Echo = P3^2
#include <reg52.h> //包括一个52标准内核的头文件
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
//***********************************************
sfr CLK_DIV = 0x97; //为STC单片机定义,系统时钟分频
//为STC单片机的IO口设置地址定义
sfr P0M1 = 0X93;
sfr P0M0 = 0X94;
sfr P1M1 = 0X91;
sfr P1M0 = 0X92;
sfr P2M1 = 0X95;
sfr P2M0 = 0X96;
//***********************************************
sbit Trig = P1^0; //产生脉冲引脚
sbit Echo = P3^2; //回波引脚
sbit test = P1^1; //测试用引脚
uchar codeSEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9
uint distance[4]; //测距接收缓冲区
uchar ge,shi,,temp,flag,outcomeH,outcomeL,i; //自定义寄存器
bit succeed_flag; //测量成功标志
//********函数声明
void conversion(uint temp_data);
void delay_20us();
//void pai_xu();
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
CLK_DIV=0X03; //系统时钟为1/8晶振(pdf-45页)
P0M1 = 0; //将io口设置为推挽输出
P1M1 = 0;
P2M1 = 0;
P0M0 = 0XFF;
P1M0 = 0XFF;
P2M0 = 0XFF;
i=0;
flag=0;
test=0;
Trig=0; //首先拉低脉冲输入引脚
TMOD=0x11; //定时器0,定时器1,16位工作方式
TR0=1; //启动定时器0
IT0=0; //由高电平变低电平,触发外部中断
ET0=1; //打开定时器0中断
//ET1=1; //打开定时器1中断
EX0=0; //关闭外部中断
EA=1; //打开总中断0
while(1) //程序循环
{
EA=0;
Trig=1;
delay_20us();
Trig=0; //产生一个20us的脉冲,在Trig引脚
while(Echo==0); //等待Echo回波引脚变高电平
succeed_flag=0; //清测量成功标志
EX0=1; //打开外部中断
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //
TR1=1; //启动定时器1
EA=1;
while(TH1 < 30);//等待测量的结果,周期65.535毫秒(可用中断实现)
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH; //测量结果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
distance_data*=12; //因为定时器默认为12分频
distance_data/=58; //微秒的单位除以58等于厘米
} //为什么除以58等于厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //没有回波则清零
test= !test; //测试灯变化
}
/// distance[i]=distance_data; //将测量结果的数据放入缓冲区
/// i++;
/// if(i==3)
/// {
/// distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
/// pai_xu();
/// distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
/// i=0;
/// }
}
}
//***************************************************************
//外部中断0,用做判断回波电平
INTO_() interrupt 0 // 外部中断是0号
{
outcomeH =TH1; //取出定时器的值
outcomeL =TL1; //取出定时器的值
succeed_flag=1; //至成功测量的标志
EX0=0; //关闭外部中断
}
//****************************************************************
//定时器0中断,用做显示
timer0() interrupt 1 // 定时器0中断是1号
{
TH0=0xfd; //写入定时器0初始值
TL0=0x77;
switch(flag)
{case 0x00:P0=ge; P2=0xfd;flag++;break;
case 0x01:P0=shi;P2=0xfe;flag++;break;
case 0x02:P0=;P2=0xfb;flag=0;break;
}
}
//*****************************************************************
/*
//定时器1中断,用做超声波测距计时
timer1() interrupt 3 // 定时器0中断是1号
{
TH1=0;
TL1=0;
}
*/
//******************************************************************
//显示数据转换程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,_data ;
_data=temp_data/100 ;
temp_data=temp_data%100; //取余运算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余运算
ge_data=temp_data;
_data=SEG7[_data];
shi_data=SEG7[shi_data];
ge_data =SEG7[ge_data];
EA=0;
= _data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ ucharbt ;
for(bt=0;bt<100;bt++);
}
/*
void pai_xu()
{ uint t;
if(distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;} /*交换值
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;} /*交换值
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;} /*交换值
}
*/
㈢ 急求基于凌阳61系列单片机 超声波测距的C语言程序或者汇编程序!!
#include "SPCE061A.h"
#include "ultrasonic_App.h"
//========================================================================
// 语法格式: int main(void)
// 实现功能: 主程序
// 参数: 无
// 返回值: int 无意义
//========================================================================
void F_Key_Scan_Initial(void);
void F_Key_Scan_ServiceLoop(void);
unsigned int SP_GetCh(void);
void Speech_Resource(unsigned int iSpeechIndex);
void Speech_Result(unsigned int uiResult);
int main(void)
{
unsigned int uiKey;
unsigned int Back_data;
F_Key_Scan_Initial();
Initial_ult();
while(1)
{
uiKey = SP_GetCh();
switch(uiKey)
{
case 0: break;
case 1:
Back_data = measure_Times(1);
if(Back_data==0)
Speech_Resource(12); //结果为0时表示测量出错,播放"咚"
else
Speech_Result(Back_data);
break;
case 2:
break;
case 3: break;
default: break;
}
F_Key_Scan_ServiceLoop();
*P_Watchdog_Clear = 0x0001;
}
}
//========================================================================
// 文件名称: IRQ.c
// 功能描述: IRQ中断服务程序
// 维护记录: 2006-04-13 V2.0
//========================================================================
#include "SPCE061A.h"
#include "ultrasonic_App.h"
void IRQ3(void)__attribute__((ISR));
void IRQ3(void)
{
*P_INT_Clear = 0x0100; //
EXT1_IRQ_ult(); //调用超声波测距的外部中断服务程序
}
//========================================================================
// 文件名称: 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;
}
㈣ 基于51单片机,用霍尔传感器测算智能小车行走的距离!谁有汇编程序,贴上来我学习学习。
ORG 0000H
SJMP MAIN
MAIN:
MOV TMOD,#05H
MOV TH0,#0
MOV TL0,#0
SETB EA
MOV P0,#0FFH
SETB TR0
ST:
MOV A,TL0
MOV 30H,A
LCALL BTOD
LCALL DISP
SJMP ST
BTOD:
MOV A,30H
MOV B,#100
DIV AB
MOV 20H,A
MOV A,B
MOV B,#10
DIV AB
MOV 21H,A
MOV 22H,B
RET
DISP:
MOV DPTR,#SEG7
MOV A,21H
MOVC A,@A+DPTR
MOV P0,A
CLR P3.0
LCALL DELAY
SETB P3.0
MOV A,22H
MOVC A,@A+DPTR
MOV P0,A
CLR P3.1
LCALL DELAY
SETB P3.1
RET
DELAY:MOV R7,#20
D00:MOV R6,#100
D11:DJNZ R6,D11
DJNZ R7,D00
RET
SEG7: DB 0C0H,0F9H,0A4H,0B0H
DB 99H,92H,82H,0F8H
DB 80H,90H,88H,83H
DB 0C6H,0A1H,86H,8EH
END
用单片机的p3.4口 数码管显示p0口 共阳极数码管动态显示p3.0和p3.1接com端,我这个程序你得修改一下 根据你的轮子的大小 计算每圈走的距离就可以算出小车行走的距离 祝你成功!
㈤ 用51单片机做测量物体的距离和方位角的程序,想用matlab读取RS232的串行数据来做数据处理
看你用什么单片机吧,matlab有直接可以生成单片机c语言的功能,不过我只看过avr,其他的单片机就不知道了
㈥ 基于单片机超声波测距c语言程序求解释
//上面这段什么意思?
//上下面这段什么意思? 没有code为什么也可以存16进制?
uchar dis_smg[8] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
有code和没有code的区别在于 dis_smg变量的存储的存储方式上
我记得有code的适合 dis_smg的数组元素不能改变的吧 记得不清楚了
你可以网络去
//下面是不是数码管引脚和单片机引脚对应?
//数码管位选定义
sbit smg_we1 = P3^4; //数码管位选定义
答案: 是
㈦ 单片机汇编语言程序解读(超声波测距)越详细越好
这是几个子程序被 堆砌到一起了 ,没有主程序不能实现功能
㈧ 单片机超声波雷达测距的C语言程序设计,具体要求看问题补充
你到网络文库中找找,会找到很多的。你也可到淘宝网上找一下:“单片机超声波测距模块电子设计制作C程序”这是一款比较好的程序,附的资料比较多,有Protel格式原理图、PCB图,有源程序、设计论文报告、元件清单等,制作非常容易,只要按图焊接好元件,基本不需要调试,最远可测量到6.99米,报警距离还可调节。 这里还有制作调试好的实物,你找找看。
㈨ 如何用单片机写一个光电开关距离按键调节程序
,又被叫做U型光电开关,是一款红外线感应光电产品,由红外线发射管和红外线接收管组合而成,而槽宽则就决定了感应接收型号的强弱与接收信号的距离,以光为媒介,由发光体与受光体间的红外光进行接收与转换,检测物体的位置。槽型光电开关于接近开关同样是无接触式的,受检测体的制约少,且检测距离长,可进行长距离的检测(几十米)检测精度高能检测小物体。应用非常的广泛。
槽型光电开关主要特点
1.检测距离长
与接近开关等比较,光电开关的检测距离非常长,且是无接触式的,所以不会损伤检测物体,也不受检测物体的影响。几乎不受检测物体的制约由于是采用对检测对象的表面进行反射及光透过方式,不像接近开关只能对金属,还能对玻璃、塑料、木制物体、液体等各种物质进行检测。
2.响应速度快
与接近开关同样,由于无机械运动,所以能对高速运动的物体进行检测。镜头容易受有机尘土等的影响镜头免受污染后,光会散射或被遮光,所以在有活水蒸汽、尘土等较多的环境下使用的场合,需施加适当的保护装置。受环境强光的影响几乎不受一般照明光的影响,但像太阳光那样的强光直接照射受光体时,会造成误动作或损坏。
NPN槽型光电开关工作原理分析
在不同的应用电路中。可根据需要把其工作输出状态设计成高电平或低电平脉冲输出,见左图、右图。
需要说明的是,有些购买来的成品槽型光电开关的引出脚已焊接了四芯线和插头的。四根线的颜色分别是棕、黑、红、橙。这四根线并不像平常的红色线接电源,黑色线接地。经实际测试。分别是棕色A.黑色C,红色K,橙色E。
单片机与光电开关接法
三线光电开关三线一般为 电源+ 、 电源- 、信号输出端,根据信号输出端输出形式,根据不同形式再添加相应电路(如上拉电阻等),再连到单片机某个IO口即可。
㈩ 51单片机控制的超声波测距仪程序
希望对你有帮助
//超声波模块显示程序
#include <reg52.h> //包括一个52标准内核的头文件
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
sbit Tx = P3^3; //产生脉冲引脚
sbit Rx = P3^2; //回波引脚
uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9
uint distance[4]; //测距接收缓冲区
uchar ge,shi,,temp,flag,outcomeH,outcomeL,i; //自定义寄存器
bit succeed_flag; //测量成功标志
//********函数声明
void conversion(uint temp_data);
void delay_20us();
void pai_xu();
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
i=0;
flag=0;
Tx=0; //首先拉低脉冲输入引脚
TMOD=0x11; //定时器0,定时器1,16位工作方式
TR0=1; //启动定时器0
IT0=0; //由高电平变低电平,触发外部中断
ET0=1; //打开定时器0中断
EX0=0; //关闭外部中断
EA=1; //打开总中断0
while(1) //程序循环
{
EA=0;
Tx=1;
delay_20us();
Tx=0; //产生一个20us的脉冲,在Tx引脚
while(Rx==0); //等待Rx回波引脚变高电平
succeed_flag=0; //清测量成功标志
EX0=1; //打开外部中断
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //
TR1=1; //启动定时器1
EA=1;
while(TH1 < 30);//等待测量的结果,周期65.535毫秒(可用中断实现)
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH; //测量结果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
distance_data*=12; //因为定时器默认为12分频
distance_data/=58; //微秒的单位除以58等于厘米
} //为什么除以58等于厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //没有回波则清零
}
distance[i]=distance_data; //将测量结果的数据放入缓冲区
i++;
if(i==3)
{
distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
pai_xu();
distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
}
}
//***************************************************************
//外部中断0,用做判断回波电平
INTO_() interrupt 0 // 外部中断是0号
{
outcomeH =TH1; //取出定时器的值
outcomeL =TL1; //取出定时器的值
succeed_flag=1; //至成功测量的标志
EX0=0; //关闭外部中断
}
//****************************************************************
//定时器0中断,用做显示
timer0() interrupt 1 // 定时器0中断是1号
{
TH0=0xfd; //写入定时器0初始值
TL0=0x77;
switch(flag)
{case 0x00:P0=ge; P2=0x7f;flag++;break;
case 0x01:P0=shi;P2=0xbf;flag++;break;
case 0x02:P0=;P2=0xdf;flag=0;break;
}
}
//显示数据转换程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,_data ;
_data=temp_data/100 ;
temp_data=temp_data%100; //取余运算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余运算
ge_data=temp_data;
_data=SEG7[_data];
shi_data=SEG7[shi_data]&0x7f;
ge_data =SEG7[ge_data];
EA=0;
= _data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ uchar bt ;
for(bt=0;bt<60;bt++);
}
void pai_xu()
{ uint t;
if (distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;}
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;}
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;}
}