『壹』 跪求一个 用stc12c系列 pca发送40khz 单片机 定时捕捉回波 的超声波测距 c语言程序
超声波的话我用的是X宝上的潮汕波模块,这里我写了一个超声波的头文件 我传给你好了,还有头文件上说明,应该能看懂的
传不来 文件 直接发给你好了。
/*
头文件说明:
本头文件有三个可以调用的函数
1.串口的初始化函数 UESC_UART_Init(uint band)
1)参数是设定的波特率,晶振是12MHz,建议设置为2400.
2)注意初始化后要简短延时。
2. UESC_UART_Putchar(char kkk)
该函数可以向上位机发送一个字节的数据,参数就是要发送的数据。
本函数是用到了中断,这样程序在接收数据的时候可以运行其他程序。
单片机通过串口接收到数据之后将8位的数据放在 date 的外部变量中,所以在主函数里可以直接操作接收来的变量;
接收到数据后同时会将外部变量flag置位,以适应不同的应用场合。
注意: 使用到串口是 定时器1不能使用。
发送单个字符的时候记得加 ‘’ 将字符括起来。
记得将flag置一;
第二次修改的内容:
给初始化函数加了晶振的选择,传递的参数就是晶振的频率 12M的晶振就传递12
注意:该函数在12M 24M 24.576M测试搜通过。 但是11.0592死活不成功,不要问为什么,搞得好像我知道似的!
建议在调用之前建议先测试一下该晶振频率能否通过。
第二次修改的内容:
解决了部分晶振频率串口通信失败的问题,现在所有的晶振均测试通过。
同时加了字符串输出函数:UART_PutString(char *s) 参数就是要显示的字符串,记得用“”。
作者@Jack_kk
完成日期:2014_4_14
第一次修改时间:2014_5_13
第二次修改时间:2014_5_18
第三次修改时间:2014_5_19
*/
#include<reg51.h>
#include<stdio.h>
#include"UART.h"
char get_char;
bit flag;
unsigned char date;
void UESC_UART_Init(uint band,double MHz)
{
TMOD|=0x20;
TH1=256-(double)(MHz*2604)/band;
TL1=TH1;
SM0=0; //和下面的一条语句同时设定串口工作方式
SM1=1;
REN=1; //允许串口接收
EA=1; //总中断
TR1=1; //定时器开始
ES=1; //开串口中断
}
void UESC_UART_Putchar(char kkk)
{
ES=0;
SBUF=kkk;
while(!TI);
TI=0;
ES=1;
}
void UART_PutString(char *s)
{
while(*s)
{
UESC_UART_Putchar(*s++);
}
}
/*
void UESC_UART_Getchar(void) //这个部分注释掉是因为 没有用到中断。
{
ES=0; //发送数据之前把串口关闭
// TI=1; //这里是发送一个字符串printf的用法,先关闭窗口中断,然后TI 好就是这样、
// puts(" Please input a letter");
// TI=0;
while(!RI);
RI=0;
get_char=SBUF;
// TI=1;
// printf("The letter you just input is ");
// TI=0;
SBUF=get_char;
while(!TI);
TI=0;
ES=1;
}
*/
错了,那是串口头文件 sorry
/*
********************头文件说明**********************
本头文件适用于HC-HR04超声波模块
经封装本头文件可以直接调用的函数是:
1.Ultrasound_Init();
初始化定时器0;
2.Get_time();
取得距离函数,返回值是距离,单位厘米,声速是240m/s时的测量结果。
示例:
Ultrasound_Init();
while(1)
{
dis=Get_time();
display(dis);
}
注意:
1.本头文件占用了定时器0,在主函数里面就不要在使用定时器0了;
2.调用本头文件之前记得修改IO口;
3.测量周期建议在60ms以上。
作者@Jack_kk
时间:2014_5_14
*/
#include"Ultrasound.h"
#include<intrins.h>
#include<reg51.h>
sbit Echo=P3^2;
sbit Trig=P1^0;
void Delay15us() //@12.000MHz
{
unsigned char i;
i = 42;
while (--i);
}
void Ultrasound_Init()
{
TMOD|=0x09;
TH0=TL0=0;
ET0=1;
TR0=1;
EA=1;
}
unsigned int Get_dis()
{
int timeout=20000;
Trig=1;
Delay15us();
Trig=0;
while(!Echo&timeout)
timeout--;
timeout=20000;
while(Echo&timeout)
timeout--;
timeout=TH0*256+TL0; //这里偷了一点懒,将变量防死机变量timeout作为了返回值
TH0=TL0=0;
return timeout*0.024;
}
『贰』 谁有超声波探头的程序麻烦发一下
我这是单片机控制超声波探头的汇编源程序,已验证可以
中断入口程序 *
;********************************************
;
ORG 0000H
LJMP START
ORG 0003H
LJMP PINT0
ORG 000BH
LJMP INTT0
ORG 0013H
RETI
ORG 001BH
LJMP INTT1
ORG 0023H
RETI
ORG 002BH
RETI
;
;********************************************
;* 主 程 序 *
;********************************************
;
START: MOV SP,#4FH
MOV R0,#40H
MOV R7,#0BH
CLEARDISP: MOV @R0,#00H
INC R0
DJNZ R7,CLEARDISP
MOV 20H,#00H
MOV TMOD,#21H ;T1为8位自动重装模式,T0为16位定时器
MOV TH0,#00H ;65毫秒初值
MOV TL0,#00H
MOV TH1,#0F2H ;40KHZ初值
MOV TL1,#0F2H
MOV P0,#0FFH
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH
MOV R4,#04H ;超声波肪冲个数控制(为赋值的一半)
SETB PX0
SETB ET0
SETB EA
SETB TR0 ;开启测距定时器
start1: LCALL DISPLAY
JNB 00H,START1 ;收到反射信号时标志位为1
CLR EA
LCALL WORK ;计算距离子程序
SETB EA
CLR 00H
SETB TR0 ;重新开启测距定时器
MOV R2,#64H ;测量间隔控制(约4*100=400MS)
LOOP: LCALL DISPLAY
DJNZ R2,LOOP
SJMP Start1
;
;****************************************************
;* 中断程序* *
;****************************************************
;T0中断,65毫秒中断一次
INTT0: CLR EA
CLR TR0
MOV TH0,#00H
MOV TL0,#00H
SETB ET1
SETB EA
SETB TR0 ;启动计数器T0,用以计算超声来回时间
SETB TR1 ;开启发超声波用定时器T1
OUT: RETI
;T1中断,发超声波用
INTT1: CPL VOUT
DJNZ R4,RETIOUT
CLR TR1 ;超声波发送完毕,关T1
CLR ET1 ;
MOV R4,#04H
SETB EX0 ;开启接收回波中断
RETIOUT: RETI
;外中断0,收到回波时进入
PINT0: CLR TR0 ;关计数器
CLR TR1
CLR ET1
CLR EA ;
CLR EX0 ;
MOV 44H,TL0 ;将计数值移入处理单元
MOV 45H,TH0 ;
SETB 00H ;接收成功标志
RETI
;
;****************************************************
;* 显示程序 *
;****************************************************
; 40H为最高位,43H为最低位,先扫描高位
DISPLAY: MOV R1,#40H;G
MOV R5,#0F7H;G
PLAY: MOV A,R5
MOV P0,#0FFH
MOV P2,A
MOV A,@R1
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
LCALL DL1MS
INC R1
MOV A,R5
JNB ACC.0,ENDOUT;G
RR A
MOV R5,A
AJMP PLAY
ENDOUT: MOV P2,#0FFH
MOV P0,#0FFH
RET
;
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,88H,0BFH
;共阳段码表 "0" "1" "2" "3" "4" "5""6" "7" "8" "9" "不亮""A""-"
;
;****************************************************
;* 延时程序 *
;****************************************************
;
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;
;****************************************************
;* 距离计算程序 (=计数值*17/1000cm) *
;****************************************************
;
work: PUSH ACC
PUSH PSW
PUSH B
MOV PSW, #18h
MOV R3, 45H
MOV R2, 44H
MOV R1, #00D
MOV R0, #17D
LCALL MUL2BY2
MOV R3, #03H
MOV R2, #0E8H
LCALL DIV4BY2
LCALL DIV4BY2
MOV 40H, R4
MOV A,40H
JNZ JJ0
MOV 43H,#0AH
JJ0: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #100D
LCALL DIV4BY2
MOV 42H, R4
MOV A,42H
JNZ JJ1
MOV A,40H
SUBB A,#0AH
JNZ JJ1
MOV 42H,#0AH
JJ1: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #10D
LCALL DIV4BY2
MOV 41H, R4
MOV A,41H
JNZ JJ2
MOV A,42H
SUBB A,#0AH
JNZ JJ2
MOV 41H,#0AH
JJ2: MOV 40H, R0
POP B
POP PSW
POP ACC
RET
;
;****************************************************
;* 两字节无符号数乘法程序 *
;****************************************************
; R7R6R5R4 <= R3R2 * R1R0
;
MUL2BY2: CLR A
MOV R7, A
MOV R6, A
MOV R5, A
MOV R4, A
MOV 46H, #10H
MULLOOP1: CLR C
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
JNC MULLOOP2
MOV A, R4
ADD A, R2
MOV R4, A
MOV A, R5
ADDC A, R3
MOV R5, A
MOV A, R6
ADDC A, #00H
MOV R6, A
MOV A, R7
ADDC A, #00H
MOV R7, A
MULLOOP2: DJNZ 46H, MULLOOP1
RET
;
;****************************************************
;* 四字节/两字节无符号数除法程序 *
;****************************************************
;R7R6R5R4/R3R2=R7R6R5R4(商)...R1R0(余数)
;
DIV4BY2: MOV 46H, #20H
MOV R0, #00H
MOV R1, #00H
DIVLOOP1: MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
CLR C
MOV A, R0
SUBB A, R2
MOV B, A
MOV A, R1
SUBB A, R3
JC DIVLOOP2
MOV R0, B
MOV R1, A
DIVLOOP2: CPL C
DJNZ 46H, DIVLOOP1
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
RET
;
END
『叁』 超声波测距程序
以下是用汇编语言编写的超声波测距控制源程序:采用AT89S51 12MHz晶振 显示缓冲单元在40H~43H,使用内存44H、45H、46H用于计算距离
20H用于标志
VOUT EQU P1.0 ;脉冲输出端口
*中断入口程序*
ORG 0000H
LJMP START
ORG 0003H
LJMP PINT0
ORG 000BH
LJMP INTT0
ORG 0013H
RETI
ORG 001BH
LJMP INTT1
ORG 0023H
RETI
ORG 002BH
RETI
*主程序*
START: MOV SP, #4FH
MOV R0, #40H ;40~43H为显示数据存放单元(40为最高位)
MOV R7,#0BH
CLEARDISP:MOV @R0, #00H
INC R0
DJNZ R7, CLEARDISP
MOV 20H, #00H
MOV TMOD, #21H ;T1为8位自动重装模式,T0为16位定时器
MOV TH0, #00H ;65ms初值
MOV TL0, #00H ;40KHz初值
MOV TH1, #0F2H
MOV TL1, #0F2H
MOV P0, #0FFH
MOV P1, #0FFH
MOV P2, #0FFH
MOV P3, #0FFH
MOV R4, #04H ;超声波脉冲个数控制(为赋值的一半)
SETB PX0
SETB ET0
STEB EA
CLR 00H
SETB TR0 ;开启测距定时器
START1: LCALL DISPLAY
JNB 00H, START1 ;收到反射信号时标志位为1
CLR EA
LCALL WORK;计算距离子程序
SETB EA
CLR 00H
SETB TR0;重新开启测距定时器
MOV R2, #64H ; 测量间隔控制(约4*100=400ms)
LOOP: LCALL DISPLAY
DJNZ R2, LOOP
SJMP START 1
*中断程序*
;T0中断,65ms中断一次
INTT0: CLR EA
CLR TR0
MOV TH0, #00H
MOV TL0, #00H
SETB ET1
SETB EA
SETB TR0 ;启动计时器T0,用以计算超声波来回时间
SETB TR1 ;开启发超声波用定时器T1
OUT: RETI;T1中断,发超声波用
INTT1: CPL VOUT
DJNZ R4,RETIOUT
CLR TR1;超声波发送完毕,关T1
CLR ET1
MOV R4,#04H
SETB EX0;开启接收回波中断
RETIOUT: RETI;外中断0,收到回波时进入
PINT0: CLR TR0 ;关计数器
CLR TR1
CLR ET1
CLR EA
CLR EX0
MOV 44H, TL0;将计数值移入处理单元
MOV 45H, TH0
SETB 00H ;接收成功标志
RETI
*延时程序*
DL1MS: MOV R6, #14H
DL1: MOV R7, #19H
DL2: DJNZ R6, DL2
DJNZ R6, DL1
RET
*显示程序*
;40H为最高位,43H为最低位,先扫描高位
DISPLAY: MOV R1, #40H;G
MOV R5,#0F7H;G
PLAY: MOV A, R5
MOV P0, #0FFH
MOV P2, A
MOV A, @R1
MOV DPTR, #TAB
MOVC A, @A+DPTR
MOV P0, A
LCALL DLIMS
INC R1
MOV A, R5
JNB ACC.0, ENDOUT;G
RR A
MOV R5, A
AJMP PLAY
ENDOUT: MOV P2, #0FFH
MOV P0, #0FFH
RET
TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,88H,0BFH
;共阳数码管 0 ,1, 2,3,4,5,6,7,8,9,不亮,A,
*距离计算程序(=计算值×17/1000cm) 近似
WORK: PUSH ACC
PUSH PSW
PUSH B
MOV PSW, #18H
MOV R3, 45H
MOV R2, 44H
MOV R1, #00D
MOV R0, #17D
LCALL MUL2BY2
MOV R3, #03H
MOV R2, #0E8H
LCALL DIV4BY2
LCALL DIV4BY2
MOV 40H, R4
MOV A, 40H
JNZ JJ0
MOV40H,#0AH ;最高位为0,不点亮
JJ0: MOV A R0
MOV R4, A
MOV A R1
MOV R5,A
MOV R3, #00D
MOV R2, #100D
LCALL DIV4BY2
MOV 41H, R4
MOV A, 41H
JNZ JJ1
MOV A, 40H ;此高位为0,先看最高位是否为不亮
SUBB A, #0AH
JNZ JJ1
MOV 41H, #0AH ; 最高位不亮,次高位也不亮
JJ1: MOV A, R0
MOV R4, A
MOV A, R1
MOV R5, A
MOV R3, #00D
MOV R2, #10D
LCALL DIV4BY2
MOV 42H, R4
MOV A 42H
JNZ JJ2
MOV A,41H ;次高位为0,先看次高位是否为不亮
SUBB A, #0AH
JNZ JJ2
MOV 42H, #0AH ;次高位不亮,次高位也不亮
JJ2: MOV 43H, R0
POP B
POP PSW
POP ACC
RET
*两字节无符号数乘法程序
MUL2BY2: CLR A
MOV R7, A
MOV R6, A
MOV R5, A
MOV R4, A
MOV 46H, #10H
MULLOOP1: CLR C
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
JNC MULLOOP2
MOV A, R4
ADD A, R2
MOV R4, A
MOV A, R5
ADDC A, R3
MOV R5, A
MOV A, R6
ADDC A, #00H
MOV R6, A
MOV A, R7
ADDC A, #00H
MOV R7, A
MULLOOP2: DJNZ 46H, MULLOOP1
RET
*四字节/两字节无符号数除法程序*
DIV4BY2: MOV 46H, #20H
MOV R0, #00H
MOV R1, #00H
DIVLOOP1: MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R1
RLC A
MOV R1, A
CLR C
MOV A, R0
SUBB A, R2
MOV B, A
MOV A, R1
SUBB A, R3
JC DIVLOOP2
MOV R0, B
MOV R1, A
DIVLOOP2: CPL C
DJNZ 46H, DIVLOOP1
MOV A, R4
RLC A
MOV R4, A
MOV A, R5
RLC A
MOV R5, A
MOV A, R6
RLC A
MOV R6, A
MOV A, R7
RLC A
MOV R7, A
RET
END
『肆』 51单片机超声波测距代码
1602液晶显示 的超声波模块程序
接口程序里边都有、、
#include
//#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^3;
sbit lcden=P2^2;
sbit trig=P2^0; //超声波发送
//sbit echo=P3^2; //超声波接受
//P0____________DB0-DB7
uchar dis[]="Disp_HC-SR04";
uchar num[]="0123456789";
uint distance;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=121;y>0;y--);
}
void HC_init()
{
TMOD=0x09;
TR0=1;
TH0=0;TL0=0;
}
uint HC_jisuan()
{
uint dist,timer;
timer=TH0;
timer<<=8;
timer=timer|TL0;
dist=timer/53; //晶振11.0592MHz 距离cm=微秒us/58
return dist; //1个机器周期是12个时钟周期 timer*12/(58*11.0592)=timer/53
}
void HC_run()
{
uint tempH=0x00,tempL=0x00;
TH0=0;TL0=0;
trig=0;
trig=1;
delay(1);
trig=0;
while((TH0-tempH!=0||TL0-tempL!=0)||(TH0==0&&TL0==0))
{
tempH=TH0;
tempL=TL0;
}
delay(1);
}
void lcd_write_com(uchar com) //LCD写指令
{
lcdrs=0;
P0=com;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_write_data(uchar date) //LCD写数据
{
lcdrs=1;
P0=date;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_init() //LCD初始化
{
lcden=0;
lcd_write_com(0x38);
lcd_write_com(0x0c);
lcd_write_com(0x06);
lcd_write_com(0x01);
}
void lcd_display(uchar temp)
{
uint i;
lcd_write_com(0x82);
for(i=0;i<12;i++)
{
lcd_write_data(dis[i]);
}
lcd_write_com(0x80+0x41);
lcd_write_data('D');
lcd_write_data('i');
lcd_write_data('s');
lcd_write_data('t');
lcd_write_data('a');
lcd_write_data('n');
lcd_write_data('c');
lcd_write_data('e');
lcd_write_data(':');
lcd_write_data(num[temp/100]);
lcd_write_data(num[temp/10%10]);
lcd_write_data(num[temp%10]);
lcd_write_data('c');
lcd_write_data('m');
}
void main()
{
lcd_init();
HC_init();
while(1)
{
HC_run();
distance=HC_jisuan();
lcd_display(distance);
delay(200);
}
}