⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chaosheng.c

📁 此程序是8051超声波液位仪的源代码 有一定的参考价值
💻 C
字号:
#include"reg51.h"
#include"intrins.h"

#define uint unsigned int
#define uchar unsigned char

sbit DS=P1^4;
sbit START=P1^5;

sbit SCK=P1^0;
sbit SI=P1^1;
sbit SO=P1^2;
sbit cs_feed=P1^3;//喂狗信号

uchar code *init="超声波液位仪";
uchar code *work_temp="工作温度      ℃";
uchar code *test=  "测量距离      mm";
uchar code *fail=": 失败mm";
uchar code *num_data="0123456789";
uchar code *chao_v="超声波速     m/s";

uchar  data temp_data[2];//={0x00,0x00}; //读出温度暂存单元 {0x91,0x01} 25度;   高位存高位 低位存低位
uint data plus_data;//存放中断时的计数
uint data  average=0;

//RT12864写指令
 void cmd (uchar intr)
{
        P2=0x04;
        P0=intr;
        P2=0x00;
        P2=0x03;// 写指令周期结束
}
//RT12864写数据
void dat (uchar  *p,uchar data j)
{
        uchar data i,k;
        for(i=0;i<j;i++)
        {
                for(k=0;k<10;k++);  //延时大约100us
                P2=0x05;
                P0=*(p+i);
                P2=0x01;
                P2=0x02;// 写数据周期结束
        }
}
 //
void delay(uint t)
{
	for(;t>0;t--);//循环一次延时11us
}

//18b20复位程序

void reset()
{
	bit bdata flag=1;
	while(flag)
	{
		while(flag)
		{
			DS=1;
			_nop_(); _nop_();  _nop_();
			DS=0;//以上程序段制造一个下降延
			delay(50);//延时550us  最短延时480us
			DS=1;//18b20在上升延后等待15~60us发出存在脉冲,低电平持续60~240us 复位成功
			delay(3);
			flag=DS;
		}

		delay(50);//延时550us 看电平能不能升高  如果能升高证明是 低电平脉冲
                DS=1;
		flag=~DS;

	   }

}
//18b20写命令函数

void write(uchar rule)
 {
 	uchar i,temp;
	for(i=0;i<8;i++)
	{
                        temp=rule&0x01;
		 	DS=1;
			_nop_(); _nop_();  _nop_();
			DS=0;//以上程序段制造一个下降延
		 	_nop_(); _nop_();  _nop_();
                       	DS=temp;//从低位起 按位取出 送给18B20
                        rule=rule>>1;
			delay(6);//延时66us
	}
	DS=1;
	delay(1);
 }

//读一温度字节
uchar read()
{
	uchar data i;
        uchar data temp=0x00;
	uchar data value=0;
	for(i=0;i<8;i++)
	{
		 	DS=1;
			_nop_(); _nop_();  _nop_();
			DS=0;//以上程序段制造一个下降延
			_nop_(); _nop_();  _nop_();
			DS=1;
			_nop_(); _nop_();  _nop_();
                        value>>=1;
                        DS=0;
                        _nop_(); _nop_();  _nop_(); _nop_();
                        DS=1;
                        _nop_(); _nop_();  _nop_(); _nop_();
                        if(DS) value|=0x80;
			delay(6);
	}
	DS=1;
	return(value);
}
//读出温度函数
void read_temp()
{
        reset();
        write(0xcc);//发skiprom命令
 	write(0x44);//发送转换命令
        reset();
 	write(0xcc);//发skiprom命令
 	write(0xbe);   //读命令
 	temp_data[0]=read();
        temp_data[1]=read();
        reset();


}

//数据处理显示函数

uchar deal_dis()
{
        uchar data k;
	uchar data tmp[2];
        uchar  data  dis_data[6];
        dis_data[0]=':';
	if(temp_data[1]>127)  //判断小于零
	{
	   	temp_data[1]=~temp_data[1]+1;
		temp_data[0]=~temp_data[0]+1;
		dis_data[1]='-';
	}
        else
                dis_data[1]=0x20;   //清空单元
	tmp[0]=temp_data[1]<<4;
	tmp[1]=temp_data[0]>>4;
	tmp[1]=tmp[1]&0x0f;
	tmp[0]=tmp[0]|tmp[1];//整数部分
	tmp[1]=temp_data[0]&0x0f;  //小数部分
	dis_data[2]=*(num_data+tmp[0]%100/10);
	dis_data[3]=*(num_data+tmp[0]%10);	//dis_data[0--3]内容是"-" 高位到低位
	dis_data[4]='.';
        if(tmp[1]==0x00)
              dis_data[5]='0';
        else if(tmp[1]==0x0f)
             dis_data[5]='9';
        else
             dis_data[5]= *(num_data+tmp[1]/2+1);
        for(k=0;k<10;k++);  //延时大约100us
        cmd(0x94); //位置 //
        for(k=0;k<10;k++);  //延时大约100us
        dat(dis_data ,6);     //  温度
        return(tmp[0]); //返回温度整数部分用来超声波计算超声波速度

}
 //开始发送超声波
void send_wave()
{
        uchar w;
        START=0;//开始发送超声波
        TR0=1;
        for(w=0;w<15;w++);//延时大约100us
        START=1;  //停止发送
        for(w=0;w<5;w++);//延时等待超声波换能器余震 过去
        EX0=1;//外部中断0允许
}

// 测试失败
void failed()
{
         uchar k;
         for(k=0;k<10;k++);  //延时大约100us
         cmd(0x9c); //位置
         for(k=0;k<10;k++);  //延时大约100us
         dat(fail,8);    //距离
}
//计算速度和距离并显示
void  math(uchar t)
{
        uint data s;
        float  v;
        uchar data i;
        float data temp1,temp2;
        uchar data distan_data[6];
        uint data div;//记录有多少个100个脉冲 用来解决直接计算的越界问题
        v=331.5+0.6*t;
        s=v;                  //s是整形量 用来存储v的整数部分
        distan_data[0]=':';
        distan_data[1]=' ';
        distan_data[2]=*(num_data+s/100);
        distan_data[3]=*(num_data+s%100/10);
        distan_data[4]=*(num_data+s%10);
        for(i=0;i<10;i++);  //延时大约100us
        cmd(0x8c); //位置
        for(i=0;i<10;i++);  //延时大约100us
        dat(distan_data,5);    //距离
       // plus_data=50001 ;
        if(plus_data>50000||TF0==1)
         {
                failed();
                for(i=0;i<100;i++);  //延时大约100us
                return ;
         }
         plus_data/=2;
        div=plus_data/100;
        plus_data=plus_data%100;
        temp1=100*v/1000;
        temp1=div*temp1;
        temp2=plus_data*v/1000;
        s=temp1+temp2;
        if(average==0)
            average=s;       //第一次测量的是第一次值二倍的平均值
        average=(average+s)>>1;//每次测量的值都和上一次的平均值取平均 逐次逼近可以加快计算速度
        distan_data[0]=':';
        distan_data[1]=' ';
        distan_data[2]=*(num_data+average/1000);
        distan_data[3]=*(num_data+average%1000/100);
        distan_data[4]=*(num_data+average%100/10);
        distan_data[5]=*(num_data+average%10);
        for(i=0;i<10;i++);  //延时大约100us
        cmd(0x9c); //位置
        for(i=0;i<10;i++);  //延时大约100us
        dat(distan_data,6);    //距离
}

/*
sbit SCK=P1^0;
sbit SI=P1^1;
sbit SO=P1^2;
sbit cs_feed=P1^3;//喂狗信号
*/

//看门狗初始化
void WTD_init()
{
        uchar i;
        uchar instr;
        cs_feed=0;  // 用来写 WREN 写 使能
        instr=0x06;
        for(i=0;i<8;i++)
        {
                SCK=0;
                SI=instr&0x80;;
                SCK=1;
                instr<<=1;
        }
        cs_feed=1;
        _nop_();
        cs_feed=0;  //用来写状态寄存器指令
        instr=0x01;
        for(i=0;i<8;i++)
        {
                SCK=0;
                SI=instr&0x80;;
                SCK=1;
                instr<<=1;
        }
        instr=0x10;     //写状态寄存器
        for(i=0;i<8;i++)
        {
                SCK=0;
                SI=instr&0x80;;
                SCK=1;
                instr<<=1;
        }

}

//喂狗
void feed_WTD()
{
        cs_feed=1;
        _nop_(); _nop_();
        cs_feed=0;
        _nop_(); _nop_();
}

// 超声波返回中断 读取计数器中的值
void plus_count (void ) interrupt 0 using 0
{
        TR0=0;
        plus_data=TH0;
        plus_data<<=8;
        plus_data|=TL0;
}
//
void init_RT()
{
         uchar data k,w;
         cmd(0x30);//使用基本指令集
         for(k=0;k<10;k++);  //延时大约100us
         cmd(0x0c); //显示状态开关 整体,游标,游标位置
         for(k=0;k<10;k++); //延时大约100us
         cmd(0x01); //清除显示,地址计数器AC到零
         for(k=0;k<250;k++)
         for(w=0;w<200;w++);//延时大约500ms
         cmd(0x81); //位置
         for(k=0;k<10;k++);  //延时大约100us
         dat(init,12);     //超声波液位仪
         for(k=0;k<10;k++);  //延时大约100us
         cmd(0x90); //位置
         for(k=0;k<10;k++);  //延时大约100us
         dat(work_temp,16);    //温度
         for(k=0;k<10;k++);  //延时大约100us
         cmd(0x88); //位置
         for(k=0;k<10;k++);  //延时大约100us
         dat(chao_v,16);    //超声波速度
         for(k=0;k<10;k++);  //延时大约100us
         cmd(0x98); //位置
         for(k=0;k<10;k++);  //延时大约100us
         dat(test,16);    //距离

}
//主函数
void main()
{
         uchar data tempt;//当前温度
         unsigned int i;
         unsigned int j;
         TMOD=0x01;  //计数器0工作在16位定时器状态
         EA=1;
         PX0=1;  //外部中断0优先级高
         IT0=1;  //边沿触发 自动清零
        // WTD_init();  //看门狗初始化
         //init_RT();
         START=0;//开始发送超声波
         while(1)
         {  /*
            // read_temp();
             //tempt=deal_dis();   //取回温度值
             send_wave();
             while(TF0==0);
                math(tempt);//计算距离
                TF0=0;
                feed_WTD();  //喂狗
                  */
               for(i=0;i<900;i++);
                 START=~START;
        }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -