用c51单片机如何实现超声波测距控制程序(40khz)
2个回答
展开全部
//超声波模块程序
//Trig = P2^0
//Echo = P3^2
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
//
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//
void delay_20us()
{
uchar a ;
for(a=0;a<100;a++);
}
//***************************************************************
//显示数据转换程序
void display(uint temp)
{
uchar ge,shi,bai;
bai=temp/100;
shi=(temp%100)/10;
ge=temp%10;
wela=1;
P0=0xf7;
wela=0;
dula=1;
P0=table[bai];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
wela=1;
P0=0xef;
wela=0;
dula=1;
P0=table[shi];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
dula=1;
P0=table[ge];
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
}
//***************************************************************
void main()
{
uint distance;
test =0;
Trig=0; //首先拉低脉冲输入引脚
EA=1; //打开总中断0
TMOD=0x10; //定时器1,16位工作方式
while(1)
{
EA=0; //关总中断
Trig=1; //超声波输入端
delay_20us(); //延时20us
Trig=0; //产生一个20us的脉冲
while(Echo==0); //等待Echo回波引脚变高电平
succeed_flag=0; //清测量成功标志
EA=1;
EX0=1; //打开外部中断0
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //计数溢出标志
TR1=1; //启动定时器1
delay(20); //等待测量的结果
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断0
if(succeed_flag==1)
{
time=timeH*256+timeL;
distance=time*0.172; //厘米
display(distance);
}
if(succeed_flag==0)
{
distance=0; //没有回波则清零
test = !test; //测试灯变化
}
}
}
//***************************************************************
//外部中断0,用做判断回波电平
void exter() interrupt 0 // 外部中断0是0号
{
timeH =TH1; //取出定时器的值
timeL =TL1; //取出定时器的值
succeed_flag=1;//至成功测量的标志
EX0=0; //关闭外部中断
}
//****************************************************************
//定时器1中断,用做超声波测距计时
void timer1() interrupt 3 //
{
TH1=0;
TL1=0;
}
转http://blog.sina.com.cn/s/blog_4f8cdc9e0100g3e7.html
其实网上很多的,csdn 程序员都有的,在这里一般都得不到你要的东西,此程序仅供参考,具体的怎么写还得靠自己,网上的只能是借鉴,哪有一摸一样的啊,关键是吸收后在自己写。。。祝你好运,
//Trig = P2^0
//Echo = P3^2
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
//
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//
void delay_20us()
{
uchar a ;
for(a=0;a<100;a++);
}
//***************************************************************
//显示数据转换程序
void display(uint temp)
{
uchar ge,shi,bai;
bai=temp/100;
shi=(temp%100)/10;
ge=temp%10;
wela=1;
P0=0xf7;
wela=0;
dula=1;
P0=table[bai];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
wela=1;
P0=0xef;
wela=0;
dula=1;
P0=table[shi];
dula=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
dula=1;
P0=table[ge];
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay(1);
dula=1;
P0=0x00; //关位码
dula=0;
}
//***************************************************************
void main()
{
uint distance;
test =0;
Trig=0; //首先拉低脉冲输入引脚
EA=1; //打开总中断0
TMOD=0x10; //定时器1,16位工作方式
while(1)
{
EA=0; //关总中断
Trig=1; //超声波输入端
delay_20us(); //延时20us
Trig=0; //产生一个20us的脉冲
while(Echo==0); //等待Echo回波引脚变高电平
succeed_flag=0; //清测量成功标志
EA=1;
EX0=1; //打开外部中断0
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //计数溢出标志
TR1=1; //启动定时器1
delay(20); //等待测量的结果
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断0
if(succeed_flag==1)
{
time=timeH*256+timeL;
distance=time*0.172; //厘米
display(distance);
}
if(succeed_flag==0)
{
distance=0; //没有回波则清零
test = !test; //测试灯变化
}
}
}
//***************************************************************
//外部中断0,用做判断回波电平
void exter() interrupt 0 // 外部中断0是0号
{
timeH =TH1; //取出定时器的值
timeL =TL1; //取出定时器的值
succeed_flag=1;//至成功测量的标志
EX0=0; //关闭外部中断
}
//****************************************************************
//定时器1中断,用做超声波测距计时
void timer1() interrupt 3 //
{
TH1=0;
TL1=0;
}
转http://blog.sina.com.cn/s/blog_4f8cdc9e0100g3e7.html
其实网上很多的,csdn 程序员都有的,在这里一般都得不到你要的东西,此程序仅供参考,具体的怎么写还得靠自己,网上的只能是借鉴,哪有一摸一样的啊,关键是吸收后在自己写。。。祝你好运,
展开全部
/*--------------------------------------
超声测距器单片机程序
MCU AT89C51 XAL 12MHz
2008.2.25
--------------------------------------*/
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
extern void cs_t(void);
extern void delay(uint);
extern void display(uchar*);
data uchar testok;
/*主程序*/
void main(void)
{
data uchar dispram[5];
data uint i;
data ulong time;
P0 = 0xff;
P2 = 0xff;
TMOD = 0x11;
IE = 0x80;
while (1)
{
cs_t();
delay(1);
testok = 0;
EX0 = 1;
ET0 = 1;
while (!testok) display(dispram);
if (1 == testok)
{
time = TH0;
time = (time<<8) | TL0;
time *=172;
time /= 10000;
dispram[0] = (uchar) (time % 10);
time /= 10;
dispram[1] = (uchar) (time % 10);
time /= 10;
dispram[2] = (uchar) (time % 10);
dispram[3] = (uchar) (time / 10);
if (0 == dispram[3]) dispram[3] = 17;
} else
{
dispram[0] = 16;
dispram[1] = 16;
dispram[2] = 16;
dispram[3] = 16;
}
for (i=0; i<300; i++) display(dispram);
}
}
//
/*超声接收程序(外中断0)*/
void cs_r(void) interrupt 0
{
TR0 = 0;
ET0 = 0;
EX0 = 0;
testok = 1;
}
/*超时清除程序(内中断T0)*/
void overtime(void) interrupt 1
{
EX0 = 0;
TR0 = 0;
ET0 = 0;
testok = 2;
}
;-------------------------------------
;超声发生子程序(12M晶振38.5Hz)
;-------------------------------------
NAME CS_T
?PR?CS_T?CS_T SEGMENT CODE
PUBLIC CS_T
RSEG ?PR?CS_T?CS_T
CS_T: PUSH ACC
MOV TH0, #00H
MOV TL0, #00H
MOV A, #4D
SETB TR0
CS_T1: CPL P1.0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ ACC, CS_T1
POP ACC
RET
;
END
;-------------------------------------
;延时100机器周期*参数(1~65535)
;-------------------------------------
NAME DELAY
?PR?_DELAY?DELAY SEGMENT CODE
PUBLIC _DELAY
RSEG ?PR?_DELAY?DELAY
_DELAY: PUSH ACC ;2
MOV A, R7 ;1
JZ DELA1 ;2
INC R6 ;1
DELA1: MOV R5, #50D ;2
DJNZ R5, $ ;2
DJNZ R7, DELA1 ;2
DJNZ R6, DELA1 ;2
POP ACC ;2
RET ;2
;
END
;---------------------------------------
; 四位共阳LED动态扫描显示程序
; P0为段码口,P2为位选口(低电平有效)
; 参数为要显示的字符串指针
;---------------------------------------
NAME DISPLAY
?PR?_DISPLAY?DISPLAY SEGMENT CODE
?CO?_DISPLAY?DISPLAY SEGMENT DATA
EXTRN CODE (_DELAY)
PUBLIC _DISPLAY
RSEG ?CO?_DISPLAY?DISPLAY
?_DISPLAY?BYTE:
DISPBIT: DS 1
DISPNUM: DS 1
RSEG ?PR?_DISPLAY?DISPLAY
_DISPLAY: PUSH ACC
PUSH DPH
PUSH DPL
PUSH PSW
INC DISPNUM
MOV A, DISPNUM
CJNE A, #4D, DISP1
DISP1: JC DISP2
MOV DISPNUM, #00H
MOV DISPBIT, #0FEH
DISP2: MOV A, R1
ADD A, DISPNUM
MOV R0, A
MOV A, @R0
MOV DPTR, #DISPTABLE
MOVC A, @A+DPTR
MOV P0, A
MOV A, DISPNUM
CJNE A, #2D, DISP3
CLR P0.7
DISP3: MOV P2, DISPBIT
MOV R6, #00H
MOV R7, #0AH
LCALL _DELAY
MOV P0, #0FFH
MOV P2, #0FFH
MOV A, DISPBIT
RL A
MOV DISPBIT, A
POP PSW
POP DPL
POP DPH
POP ACC
RET
DISPTABLE:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH,0BFH,0FFH
; "0", "1", "2", "3","4", "5","6","7", "8","9","A","B","C", "D", "E","F", "-", " "
END
超声测距器单片机程序
MCU AT89C51 XAL 12MHz
2008.2.25
--------------------------------------*/
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
extern void cs_t(void);
extern void delay(uint);
extern void display(uchar*);
data uchar testok;
/*主程序*/
void main(void)
{
data uchar dispram[5];
data uint i;
data ulong time;
P0 = 0xff;
P2 = 0xff;
TMOD = 0x11;
IE = 0x80;
while (1)
{
cs_t();
delay(1);
testok = 0;
EX0 = 1;
ET0 = 1;
while (!testok) display(dispram);
if (1 == testok)
{
time = TH0;
time = (time<<8) | TL0;
time *=172;
time /= 10000;
dispram[0] = (uchar) (time % 10);
time /= 10;
dispram[1] = (uchar) (time % 10);
time /= 10;
dispram[2] = (uchar) (time % 10);
dispram[3] = (uchar) (time / 10);
if (0 == dispram[3]) dispram[3] = 17;
} else
{
dispram[0] = 16;
dispram[1] = 16;
dispram[2] = 16;
dispram[3] = 16;
}
for (i=0; i<300; i++) display(dispram);
}
}
//
/*超声接收程序(外中断0)*/
void cs_r(void) interrupt 0
{
TR0 = 0;
ET0 = 0;
EX0 = 0;
testok = 1;
}
/*超时清除程序(内中断T0)*/
void overtime(void) interrupt 1
{
EX0 = 0;
TR0 = 0;
ET0 = 0;
testok = 2;
}
;-------------------------------------
;超声发生子程序(12M晶振38.5Hz)
;-------------------------------------
NAME CS_T
?PR?CS_T?CS_T SEGMENT CODE
PUBLIC CS_T
RSEG ?PR?CS_T?CS_T
CS_T: PUSH ACC
MOV TH0, #00H
MOV TL0, #00H
MOV A, #4D
SETB TR0
CS_T1: CPL P1.0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ ACC, CS_T1
POP ACC
RET
;
END
;-------------------------------------
;延时100机器周期*参数(1~65535)
;-------------------------------------
NAME DELAY
?PR?_DELAY?DELAY SEGMENT CODE
PUBLIC _DELAY
RSEG ?PR?_DELAY?DELAY
_DELAY: PUSH ACC ;2
MOV A, R7 ;1
JZ DELA1 ;2
INC R6 ;1
DELA1: MOV R5, #50D ;2
DJNZ R5, $ ;2
DJNZ R7, DELA1 ;2
DJNZ R6, DELA1 ;2
POP ACC ;2
RET ;2
;
END
;---------------------------------------
; 四位共阳LED动态扫描显示程序
; P0为段码口,P2为位选口(低电平有效)
; 参数为要显示的字符串指针
;---------------------------------------
NAME DISPLAY
?PR?_DISPLAY?DISPLAY SEGMENT CODE
?CO?_DISPLAY?DISPLAY SEGMENT DATA
EXTRN CODE (_DELAY)
PUBLIC _DISPLAY
RSEG ?CO?_DISPLAY?DISPLAY
?_DISPLAY?BYTE:
DISPBIT: DS 1
DISPNUM: DS 1
RSEG ?PR?_DISPLAY?DISPLAY
_DISPLAY: PUSH ACC
PUSH DPH
PUSH DPL
PUSH PSW
INC DISPNUM
MOV A, DISPNUM
CJNE A, #4D, DISP1
DISP1: JC DISP2
MOV DISPNUM, #00H
MOV DISPBIT, #0FEH
DISP2: MOV A, R1
ADD A, DISPNUM
MOV R0, A
MOV A, @R0
MOV DPTR, #DISPTABLE
MOVC A, @A+DPTR
MOV P0, A
MOV A, DISPNUM
CJNE A, #2D, DISP3
CLR P0.7
DISP3: MOV P2, DISPBIT
MOV R6, #00H
MOV R7, #0AH
LCALL _DELAY
MOV P0, #0FFH
MOV P2, #0FFH
MOV A, DISPBIT
RL A
MOV DISPBIT, A
POP PSW
POP DPL
POP DPH
POP ACC
RET
DISPTABLE:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH,0BFH,0FFH
; "0", "1", "2", "3","4", "5","6","7", "8","9","A","B","C", "D", "E","F", "-", " "
END
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询