本帖最后由 xiaoliping1945 于 2013-8-22 10:10 编辑
#include<stc12c5a60s2.h>
#include<intrins.h>
#include"HC_SR04.h"
#include"lcd_1602.h"
#define first 0x00 //LCD显示第1行
#define second 0x40 //LCD显示第2行
unsigned int distance=0;
/**********单片机串行输出,用74HC595串转并即刻并行进入LCD1602显示 *****************/
unsigned char juli[]="000.0cm";
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
i = 23;
j = 205;
k = 120;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
init_SR04(); //初始化超声波
init_lcd(); //初始化液晶1602
write_com(0x01); //清屏
delayus(100;
while(1)
{
distance=sonic(); //获取距离
chuli(distance,juli); //数据处理为lcd要显示的内容
lcd_1602(first,0,juli); //显示
Delay500ms(); //0.5秒测一次,也可用定时器
}
}
/***********************************串行lcd1602头文件***********************************/
#ifndef __lcd_1602_H__
#define __lcd_1602_H__
#define uint unsigned int
#define uchar unsigned char
sbit rs=P2^2;
//rw=0; 只往lcd写入,不读出,故rw=0;
sbit en=P2^1;
sbit sclk=P2^2; //移位时钟
sbit ds=P2^0; //数据线
sbit rclk=P2^1 ; //锁存输出时钟
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delayus(uint i)
{
while(i--);
}
void write_595(uchar date)
{
uchar i;
for(i=0;i<8;i++)
{
sclk=0;
ds=date&0x80;
delay(2);
sclk=1;
date<<=1; //sclk给一个上升沿脉冲即可读走一位
}
}
void write_com(uchar com) //写指令
{
write_595(com);
rs=0;
delay(1);
//rw=0;
rclk=1;
delay(1);
rclk=0; //令595输出,并用en输出一个高脉冲
}
void write_data(uchar date ) //写数据
{
write_595(date); //写入数据
rs=1;
delay(5);
rclk=1;
delayus(10);
rclk=0; //令595输出,并用en输出一个高脉冲
}
void init_lcd() //初始化LCD
{
write_com(0x38);
delayus(50);
write_com(0x0c);
delayus(50);
write_com(0x06);
delayus(50);
// write_com(0x01); // 暂时不用清屏,在显示前可清次屏,可自行加入或屏蔽这句。
//delayus(50);
}
void lcd_1602(uchar x,uchar y,uchar *s) //第X行,第y例开始显示
{
init_lcd();
write_com(0x80+x+y);
while(*s!='\0')
{
write_data(*s++);
delay(5);
}
}
#endif
/***********************HC-SR04头文件*************************************/
#ifndef __HC_SR04_H_
#define __HC_SR04_H_
sbit RX=P3^7; //echo 接收端
sbit TX=P1^0; //trig 发送端
/*********LCD显示字符转换表*************/
unsigned char code table[]="0123456789";
/**********函数声明*************/
void init_SR04(void); // 初始化
void Delay20us(); // 延时
void Clr_timer(); // 定时器清零
void send(); // 发送10US以上高电平
unsigned int sonic();// 测距
void chuli(unsigned int range,unsigned char *s); // 数据处理
void init_SR04(void)
{
TMOD = 0x01; // 超声用定时器0
EA = 1; //开总中断
ET0= 1;
TR0=0;
TF0=0;
RX=1; //置1,作为输入端查询,(51单片机特性,可查阅相关资料
//若输入电平为1则1&1=1,若输入0则0&1=0,
//如果RX=0:则无论引脚输入是1还是0,与原先置为0的RX脚&
//则得到的总是0,也就无法检测后面输入RX的电平)
TX=0;
}
void send() //发送端TRI发送20us高电平
{
TX = 0;
Delay20us();
TX=1;
Delay20us();
TX=0;
}
void Clr_timer() //定时器清零
{
TH0=0;
TL0=0;
TF0=0;
}
unsigned int sonic() //超声波测距
{
unsigned int ceju1,time;
Clr_timer();
Delay20us();
send();
while(!RX) ; //等待接收端变为高电平
TR0=1; //启动计数
while(RX); //等待接收端变为低电平
TR0=0; //停止计数
if(TF0)
ceju1=9999;
else
{
time=TH0*256+TL0; //得到距离所用时间
ceju1=time*0.172+0.5; //放大10倍,取一位小数,此处已转化为cm单位,
//无需再转换,只是放大了10倍,四舍五入取位小数而已
//计算公式distance=time*344/2/1000000=time*0.0172 单位为cm,若为英尺好像是有个58什么来着来着,忘记了,自己百度吧
}
if(ceju1>5000) //大于5米,超出测距范围,置为无效数据
ceju1=9999;
return ceju1;
}
void chuli(unsigned int range,unsigned char *s) //带参数——>距离rangge,数据处理装载->*s
{
s[0]=table[range/1000];
s[1]=table[range%1000/100];
s[2]=table[range%100/10];
s[4]=table[range%10];
}
void Delay20us() //@12.000MHz
{
unsigned char i;
i = 57;
while (--i);
}
#endif |