📄 chaosheng.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 + -