找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1386|回复: 0
打印 上一主题 下一主题
收起左侧

超声波测试仪的设计仿真

[复制链接]
跳转到指定楼层
楼主


#include <reg51.h>                                //预处理命令,定义SFR的头
#include <math.h>
#include <intrins.h>                           //内部函数库文件
#define uchar unsigned char            //定义缩写字符uchar
#define uint unsigned int                //定义缩写字符uint
#define lcd_data P0            //定义LCD1602接口 P0
sbit DQ =P1^7;                             //将18B20DQ位定义为P1.7引脚
sbit lcd_RS=P2^0;                           //将18B20RS位定义为P2.0引脚
sbit lcd_RW=P2^1;                           //将18B20RW位定义为P2.1引脚
sbit lcd_EN=P2^2;                           //将18B20EN位定义为P2.2引脚       
sbit BEEP=P3^0;              //测量超出指定范围,报警  
sbit Trig=P2^5;                  //HC-SR04触发信号输入
sbit Echo=P2^6;                  //HC-SR04回响信号输出
uint Distance;              //测量的距离值
uint SPEEDSOUND;            //声速
uint t[2];              //将距离转换成十进制数时,中间变量
uchar Buffer1[12]={0x20,0x20,0x20,0x20,0x63,0x6d,'\0'};         //距离显示cm
uchar tab[16]={0x20,0x20,0x20,0x20,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,'\0'};  //显示"Distance"       
/**********lcd显示子程序************/
void delay20us(void)        //20us延时
{   
  unsigned char a;   
  for(a=100;a>0;a--);
  }       

void delay_20ms(void)          /*延时20ms函数*/
{
   uchar i,temp;               //声明变量i,temp
   for(i = 20;i > 0;i--)       //循环
   {
    temp = 248;                //给temp赋值248
    while(--temp);             //temp减1是否等于0,否则继续执行该行
    temp = 248;                //给temp赋值248
    while(--temp);             //temp减1是否等于0,否则继续执行该行
    }
}
void delay_38us(void)          /*延时38us函数*/
{   uchar temp;                //声明变量temp
    temp = 18;                 //给temp赋值
    while(--temp);             //temp减1是否等于0,否则继续执行该行
}
void delay_1520us(void)         /*延时1520us函数*/
{  uchar i,temp;                //声明变量i,temp
   for(i = 3;i > 0;i--)         //循环
   {
    temp = 252;                 //给temp赋值
    while(--temp);              //temp减1是否等于0,否则继续执行该行
    }
}
uchar lcd_rd_status( )          /*读取lcd1602的状态,主要用于判断忙*/
{
uchar tmp_sts;                 //声明变量tmp_sts
lcd_data = 0xff;               //初始化P3口
lcd_RW = 1;                    //RW =1  读      
lcd_RS = 0;                    //RS =0  命令,合起来表示读命令(状态)
lcd_EN = 1;                    //EN=1,打开EN,LCD1602开始输出命令数据,100nS之后命令数据有效
tmp_sts = lcd_data;            //读取命令到tmp_sts
lcd_EN = 0;                    //关掉LCD1602
lcd_RW = 0;                    //把LCD1602设置成写
return tmp_sts;                //函数返回值tmp_sts
}
void lcd_wr_com(uchar command )  /*写一个命令到LCD1602*/
{
  while(0x80&lcd_rd_status()); //写之前先判断LCD1602是否忙,看读出的命令的最高位是否为1,为1表示忙,继续读,直到不忙
  lcd_RW = 0;
  lcd_RS = 0;                  //RW=0,RS=0 写命令
  lcd_data = command;          //把需要写的命令写到数据线上
  lcd_EN = 1;  
  lcd_EN = 0;                  //EN输出高电平脉冲,命令写入
}
void lcd_wr_data(uchar sjdata )  /*写一个显示数据到lcd1602*/
{
while(0x80&lcd_rd_status());  //写之前先判断lcd1602是否忙,看读出的命令的最高位是否为1,为1表示忙,继续读,直到不忙
lcd_RW = 0;
lcd_RS = 1;                   //RW=0,RS=1 写显示数据
lcd_data = sjdata ;            //把需要写的显示数据写到数据线上
lcd_EN = 1;
lcd_EN = 0;                   //EN输出高电平脉冲,命令写入
lcd_RS = 0;                 
}
void Init_lcd(void)            /*初始化lcd1602*/
{
  delay_20ms();                //调用延时
  lcd_wr_com(0x38);            //设置16*2格式,5*8点阵,8位数据接口
  delay_38us();                //调用延时
  lcd_wr_com(0x0c);            //开显示,不显示光标
  delay_38us();                //调用延时
  lcd_wr_com(0x01);            //清屏
  delay_1520us();              //调用延时
  lcd_wr_com(0x06);            //显示一个数据后光标自动+1
}       
void GotoXY(uchar x, uchar y)  //设定位置,x为行,y为列
{
        if(y==0)                        //如果y=0,则显示位置为第一行
                lcd_wr_com(0x80|x);
        if(y==1)
                lcd_wr_com(0xc0|x);           //如果y=1,则显示位置为第二行
}

void Print(uchar *str)                   //显示字符串函数
{
        while(*str!='\0')                   //判断字符串是否显示完
        {
                lcd_wr_data(*str);           //写数据
                str++;                                  
        }
}
void LCD_Print(uchar x, uchar y, uchar *str)//x为行值,y为列值,str是要显示的字符串   
{
  GotoXY(x,y);                                   //设定显示位置
  Print(str);                                   //显示字符串
}
                                                  
/****温度转换函数,2字节转换为1字节 *****************/

void convert1()                       //温度转化程序,存放在x
{
   uchar x=0x00;                           //变量初始化
   if(t[1]>0x07)               //判断温度为负值
   {
    x=14;
   }
   else                    //温度为正值
    t[1]<<=4;                           //将高字节左移4位
    t[1]=t[1]&0x70;                       //取出高字节的3个有效数字位
    x=t[0];                                   //将t[0]暂存到X,因为取小数部分还要用到它
    x>>=4;                                           //右移4位
    x=x&0x0f;                                   //和前面两句就是取出t[0]的高四位       
    t[1]=t[1]|x;                           //将高低字节的有效值的整数部分拼成一个字节
    x=t[1];                                                                 
  }

/*******************DS18B20初始化函数**********************/

void delay_18B20(uint i)                        //延时程序
{
        while(i--);
}
void Init_DS18B20(void)                          //ds18b20初始化函数
{
         uchar x=0;
         DQ = 1;                                          //DQ复位
         delay_18B20(8);                                  //稍做延时
         DQ = 0;                                          //单片机将DQ拉低
         delay_18B20(80);                                 //精确延时大于480us
         DQ = 1;                                          //拉高总线
         delay_18B20(14);
         x=DQ;                                            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
         delay_18B20(20);
}
uchar ReadOneChar(void)                                 //ds18b20读一个字节函数
{
        unsigned char i=0;
        unsigned char dat0 = 0;
        for (i=8;i>0;i--)
         {
                  DQ = 0;                    //读前总线保持为低
                  dat0>>=1;
                  DQ = 1;                    //开始读总线释放
                  if(DQ)                                         //从DS18B20总线读得一位
                  dat0|=0x80;
                  delay_18B20(4);                         //延时一段时间
         }
        return(dat0);                                     //返回数据
}
void WriteOneChar(uchar dat1)                 //ds18b20写一个字节函数
{
        uchar i=0;
        for (i=8; i>0; i--)
        {
                  DQ = 0;                                                 //开始写入DS18B20总线要处于复位(低)状态
                DQ = dat1&0x01;                                 //写入下一位
            delay_18B20(5);
                DQ = 1;                                                 //重新释放总线
            dat1>>=1;                                         //把一个字节分成8个BIT环移给DQ
}
}
void ReadTemperature()                            //读取ds18b20当前温度
{       
        delay_18B20(80);                //延时一段时间
        Init_DS18B20();       
        WriteOneChar(0xCC);                // 跳过读序号列号的操作
        WriteOneChar(0x44);           // 启动温度转换
        delay_18B20(80);              // 延时一段时间
        Init_DS18B20();                                //DS18B20初始化
        WriteOneChar(0xCC);                 //跳过读序号列号的操作
        WriteOneChar(0xBE);                 //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
        delay_18B20(80);                            //延时一段时间
    t[0]=ReadOneChar();                //读取温度值低位
    t[1]=ReadOneChar();               //读取温度值高位
}

void HCSR04_Initialize()     //HCSR04初始化
{  
  SPEEDSOUND=334.1+25*0.61;   //温度25度时声速的值
  Trig=0;   
  Echo=0;  
  TMOD=0x01;                         //T0定时方式1
}  

float MeasuringDistance()                 //测量距离
{  
TH0=0;  TL0=0;                           //最大定时时间约65ms
  Trig=1;                                      //生成20us脉冲宽度的触发信号
  delay20us();           //20us脉冲
  Trig=0;
  while(!Echo);                           //等待回响信号变高电平
TR0=1;                                          //启动定时器0
  while(Echo);                            //等待回响信号变低电平
TR0=0;                  //关闭定时器0
return (SPEEDSOUND*(TH0*256+TL0))/2000; }  //返回距离值mm

void DisplayDistance()         //显示距离
{
Distance= MeasuringDistance();
if(Distance<20)
{
BEEP=0;
}   
        t[1]=Distance/10;
    Buffer1[1]=t[1]/100+0x30;    //加0x30 为变 0~9 ASCII码
    Buffer1[2]=(t[1]%100)/10+0x30;     //分离出十位
    Buffer1[3]=(t[1]%100)%10+0x30;     //分离出个位       
    LCD_Print(4,1,Buffer1);             //显示距离
}                    

/*************************main主程序*********************/
void main(void)
{
    uchar x;
        BEEP=1;                          //关闭报警   
        delay_20ms();           //系统延时20ms启动
           Init_lcd();                        //调用LCD初始化函数
        delay_20ms();                                           //延时一段时间
        LCD_Print(0,0,tab);
    HCSR04_Initialize();                           //HC-SR04初始化
    while(1)
        {
        ReadTemperature();            //测温度,存放在t[1]t[0]
    delay_18B20(100);
    convert1();               //温度转换,存放在x
        if(x<14)                       //温度界限判断
     x=14;
    else if(x>26)  
         x=26;
    SPEEDSOUND=334.1+x*0.61;    //声速修正M/S
        DisplayDistance();                //显示距离值
    }
   }


搜狗截图18年12月05日1038_2.png (35.21 KB, 下载次数: 34)

搜狗截图18年12月05日1038_2.png

8超声测距.rar

86.89 KB, 下载次数: 6, 下载积分: 黑币 -5

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表