#include"reg52.h"
成都网络公司-成都网站建设公司创新互联建站10多年经验成就非凡,专业从事成都网站建设、做网站,成都网页设计,成都网页制作,软文营销,广告投放平台等。10多年来已成功提供全面的成都网站建设方案,打造行业特色的成都网站建设案例,建站热线:13518219792,我们期待您的来电!
#include"intrins.h"
#define uchar unsigned char //无符号8位
#define uint unsigned int //无符号16位
#define ulong unsigned long //无符号32位
sbit K1=P1^0; //按下K1后,开始测距
sbit LEDRed=P1^1; //测距指示灯,亮表示正在测距,灭表示测距完成
//sbit BEEP=P1^2; //报警测量超出范围
sbit Trig=P2^5; //HC-SR04触发信号输入
sbit Echo=P2^6; //HC-SR04回响信号输出
float xdata DistanceValue=0.0; //测量的距离值
float xdata SPEEDSOUND; //声速
float xdata XTALTIME; //单片机计数周期
uchar xdata stringBuf[6]; //数值转字符串缓冲
//LCD1602提示信息
uchar code Prompts[][16]=
{
{"Measure Distance"}, //测量距离
{"- Out of Range -"}, //超出测量范围
{"MAX range 400cm "}, //测距最大值400cm
{"MIN range 2cm "}, //测距最小值2cm
{" "}, //清屏
{" Press K1 Start "} //按键开始测量
};
uchar xdata DistanceText[]="Range: "; //测量结果字符串
uchar xdata TemperatureText[]="Temperature: ";//测量温度值
extern void LCD_Initialize(); //LCD初始化
extern void LCD_Display_String(uchar *, uchar); //字符串显示
extern void ReadTemperatureFromDS18B20(); //从DS18B20读取温度值
extern int xdata CurTempInteger;
//毫秒延时函数
void DelayMS(uint ms);
//20微秒延时函数
void Delay20us();
//HCSR04初始化
void HCSR04_Initialize();
//测量距离
float MeasuringDistance();
//测距的数值排序求平均
float DistanceStatistics();
//输出距离值到LCD1602上
void DisplayDistanceValue(float dat);
//将无符号的整数转成字符串,返回字符串长度,不包括'\0'结束符
uchar UnsigedIntToString(uint value);
//蜂鸣器
//void Beep(uchar time);
//显示温度值
void DisplayTemperatureValue();
void main()
{
LCD_Initialize();//LCD1602初始化
LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(Prompts[5],0x40);
ReadTemperatureFromDS18B20(); //测温度
HCSR04_Initialize(); //HC-SR04初始化
while(1)
{
if(K1==0)
{
DelayMS(5);
if(K1==0)
{
//Beep(1);
while(K1==0);
LEDRed=0;
ReadTemperatureFromDS18B20();//测温度
DisplayTemperatureValue();
if(CurTempInteger14)
CurTempInteger=14;
else if(CurTempInteger26)
CurTempInteger=26;
SPEEDSOUND=334.1+CurTempInteger*0.61;//计算声速
DistanceValue=DistanceStatistics(); //测距并返回距离值
DisplayDistanceValue(DistanceValue); //显示距离值
LEDRed=1;
}
}
}
}
//测距的数值排序求平均
float DistanceStatistics()
{
uchar i,j;
float disData[7],t;
//连续测距
for(i=0;i7;i++)
{
disData=MeasuringDistance();
DelayMS(80);
}
//排序
for(j=0;j=6;j++)
{
for(i=0;i7-j;i++)
{
if(disDatadisData[i+1])
{
t=disData;
disData=disData[i+1];
disData[i+1]=t;
}
}
}
return (disData[2]+disData[3]+disData[4])/3;
}
//测量距离
float MeasuringDistance()
{
//最大定时时间约65ms
TH0=0;
TL0=0;
//生成20us的脉冲宽度的触发信号
Trig=1;
Delay20us();
Trig=0;
//等待回响信号变高电平
while(!Echo);
TR0=1; //启动定时器0
//等待回响信号变低电平
while(Echo);
TR0=0; //关闭定时器0
//返回距离值(mm)
return (SPEEDSOUND*XTALTIME*((float)TH0*256+(float)TL0))/2000;
}
//HCSR04初始化
void HCSR04_Initialize()
{
//计算单片机计数周期 晶振=11.953M 单位us
XTALTIME=12/11.953;
//温度25度时声速的值
SPEEDSOUND=334.1+25*0.61;
Trig=0;
Echo=0;
TMOD=0x01;
}
//输出距离值到LCD1602上
void DisplayDistanceValue(float dat)
{
uchar i=0,j=0,len;
uint value;
value=(uint)dat;
//范围检查大于4000mm和小于20mm都为超出测量范围
if(value4000)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[2],0x40);
//Beep(2);
}
else if(value20)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[3],0x40);
//Beep(2);
}
else
{
//将数值转换成字符串
len=UnsigedIntToString(value);
//保留1位小数
while(stringBuf!='\0')
{
if(len-j==1)
{
DistanceText[6+j]='.';
j++;
}else
{
DistanceText[6+j]=stringBuf;
i++;
j++;
}
}
DistanceText[6+j]='c';
j++;
DistanceText[6+j]='m';
i=7+j;
//剩余位置补空格
while(i16)
{
DistanceText=' ';
i++;
}
//LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(DistanceText,0x40);
}
}
//显示温度值
void DisplayTemperatureValue()
{
TemperatureText[13]=CurTempInteger/10+'0';
TemperatureText[14]=CurTempInteger+'0';
TemperatureText[15]='C';
LCD_Display_String(TemperatureText,0x00);
}
//将无符号的整数转成字符串,返回字符串长度
uchar UnsigedIntToString(uint value)
{
uchar i=0,t,length;
//从个位开始转换
do
{
stringBuf='0'+value;
value=value/10;
i++;
}while(value!=0);
length=i;
//将字符串颠倒顺序
for(i=0;i(length/2);i++)
{
t=stringBuf;
stringBuf=stringBuf[length-i-1];
stringBuf[length-i-1]=t;
}
stringBuf[length]='\0';
return length;
}
//蜂鸣器
//延时函数 毫秒 @12.000MHz
void DelayMS(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
//延时函数 20微秒 @12.000MHz
void Delay20us()
{
uchar i;
_nop_();
i = 7;
while (--i);
}
//定时器0中断
void Timer0() interrupt 1
{
}
//DS18B20代码:
#include
#include
#define uchar unsigned char //无符号8位
#define uint unsigned int //无符号16位
//定义DS18B20端口DS18B20_DQ
sbit DS18B20_DQ = P2^7;
//当前采集的温度值整数部分
int xdata CurTempInteger;
//当前采集的温度值小数部分
int xdata CurTempDecimal;
void Delayus(uint count)
{
while (--count);
}
uchar Reset_DS18B20()
{
uchar status;
DS18B20_DQ=1;
Delayus(1);
//开始复位过程
DS18B20_DQ=0; //数据线拉低
Delayus(100); //延时480us-960us
DS18B20_DQ=1; //数据线拉高
Delayus(10); //延时15us-60us
status=DS18B20_DQ; //读取数据线上的状态
Delayus(120);
return status;
}
void WriteByteToDS18B20(uchar dat)
{
uchar i;
for(i=0;i8;i++)
{
DS18B20_DQ=0;
DS18B20_DQ=dat0x01; //发送1位数据
Delayus(15); //延时60us以上
DS18B20_DQ=1; //释放总线,等待总线恢复
dat=1; //准备下一位数据
}
}
uchar ReadByteFromDS18B20()
{
uchar i,dat=0;
for(i=0;i8;i++)
{
DS18B20_DQ=0; //拉低总线,产生读信号
dat=1;
DS18B20_DQ=1; //释放总线,准备读1位数据
Delayus(2); //延时4us
if(DS18B20_DQ) dat|=0x80; //合并每位数据
Delayus(15); //延时60us
DS18B20_DQ=1; //拉高总线,准备读下1位数据
}
return dat;
}
void ReadTemperatureFromDS18B20()
{
uchar flag=0;//正负符号标志
//存储当前采集的温度值
uchar TempValue[]={0,0};
if(Reset_DS18B20())
{
CurTempInteger=255;
CurTempDecimal=0;
}
else
{
WriteByteToDS18B20(0xCC);//跳过ROM命令
WriteByteToDS18B20(0x44);//温度转换命令
Reset_DS18B20();//复位
WriteByteToDS18B20(0xCC);//跳过ROM命令
WriteByteToDS18B20(0xBE);//读取温度暂存器命令
TempValue[0]=ReadByteFromDS18B20();//先读低字节温度值
TempValue[1]=ReadByteFromDS18B20();//后读高字节温度值
Reset_DS18B20();//复位
//计算温度值
//先进行正温度与负温度判断,高5位全为1(0xF8)则为负数
if((TempValue[1]0xF8)==0xF8)
{
//负温度计算:取反加1,低字节为0时,高字节取反加1,否则不需要。
TempValue[1]=~TempValue[1];
TempValue[0]=~TempValue[0]+1;
if(TempValue[0]==0x00) TempValue[1]++;
flag=1;//负数标志
}
//将温度值分为整数和小数两部分存储(默认为12位精度)
CurTempInteger=((TempValue[1]0x07)4)|((TempValue[0]0xF0)4); if(flag) CurTempInteger=-CurTempInteger;
CurTempDecimal=(TempValue[0]0x0F)*625;
}
}
//LCD1602程序代码:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
void LCDDelay(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
bit LCD_Busy_Check()
{
bit result;
LCD_RS=0; LCD_RW=1; LCD_EN=1;
Delay4us();
result=(bit)(P00x80);
LCD_EN=0;
return result;
}
void Write_LCD_Command(uchar cmd)
{
while(LCD_Busy_Check());
LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_(); _nop_();
P0=cmd; Delay4us();
LCD_EN=1; Delay4us(); LCD_EN=0;
}
void Write_LCD_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;
P0=dat;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
void LCD_Set_POS(uchar pos)
{
Write_LCD_Command(pos|0x80);
}
void LCD_Initialize()
{
Write_LCD_Command(0x01); LCDDelay(5);
Write_LCD_Command(0x38); LCDDelay(5);
Write_LCD_Command(0x0C); LCDDelay(5);
Write_LCD_Command(0x06); LCDDelay(5);
}
void LCD_Display_String(uchar *str, uchar LineNo)
{
uchar k;
LCD_Set_POS(LineNo);
for(k=0;k16;k++)
{
Write_LCD_Data(str[k]);
}
}
void LCD_Display_OneChar(uchar Dat, uchar X, uchar Y)
{
Y = 0x01; //限制Y不能大于1(2行,0-1)
X = 0x0F; //限制X不能大于15(16个字符,0-15)
if(Y) {X |= 0x40;} //当要在第二行显示时地址码+0x40;
X |= 0x80; //算出指令码
Write_LCD_Command(X);
Write_LCD_Data(Dat);
}
1、HC-SR04使用方法:给触发端子trig一个10us以上的高电平即可触发,触发后echo端子将接受到高电平,高电平的持续时间就是测距的往返时间。
2、例程:
#includereg52.h
#define uchar unsigned char
#define uint unsigned int
/*位定义*/
sbit CHUFA=P0^1; //位定义超声波触发端(10us以上高电平触发)
sbit JIESHOU=P0^3; //接收端(接受高电平)
sbit BEEP=P2^0; //蜂鸣器
sbit OUT0=P3^2; //外部中断0
uchar JS_FLAG; //接收标志
uint CF_TIME,t0,t1,shu;
/*函数声明*/
void timer0();
void int0();
void display(uint);
main(){
CHUFA=0; //初始化拉低触发端和接收端电平
JIESHOU=0;
JS_FLAG=0;
CF_TIME=15; //初始化触发时间(大于10us)
TMOD=0x11; //定时器方式选择
EA=1; //开总中断
ET0=1; //开定时器0中断
EX0=1; //开外部中断0
IT0=0; //外部中断选择下降沿触发
//JIESHOU=1;
while(1){
OUT0=JIESHOU; //外部中断0被赋值为接收端信号,当出现下降沿是触发外部中断0
if(JS_FLAG==0){ //如果没有接收到高电平则触发
CHUFA=1;
while(CF_TIME--); //10us以上高电平触发传感器
}
if(JIESHOU==1){
TR0=1; //如果接收端收到高电平则启动定时器
JS_FLAG=1; //并且标志位置1
BEEP=0; //蜂鸣器响
}
display(t1); //显示测量时间(秒)
}
}
/*定时器0中断程序*/
void timer0() interrupt 1{
TH0=(65536-10000)/256; //装初值 10ms
TL0=(65536-10000)%256;
t0++; //每进入一次中断t0加1
}
/*外部中断0中断程序*/
void int0() interrupt 0{
TR0=0; //一旦进入外部中断0,说明接收端收到下降沿信号。关闭定时器0
JS_FLAG=0; //接收标志位置0
BEEP=1; //关闭蜂鸣器
t1=t0*10/1000; //测量时间为 进入定时器中断次数t0乘以每次时间10ms,除以1000化为秒为单位
t0=0; //t0清零
}
/*数码管显数函数*/
void display(uint shu){
//数码管显示函数
}
//晶振=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 code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9
uint distance[4]; //测距接收缓冲区
uchar ge,shi,bai,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=bai;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,bai_data ;
bai_data=temp_data/100 ;
temp_data=temp_data%100; //取余运算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余运算
ge_data=temp_data;
bai_data=SEG7[bai_data];
shi_data=SEG7[shi_data];
ge_data =SEG7[ge_data];
EA=0;
bai = bai_data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ uchar bt ;
for(bt=0;bt100;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;} /*交换值
}
*/
这是个用过的程序,引脚和参数你自己调一下吧,附件里有1602显示的内容,希望对你有用。