📄 shuiwenkongzhi.c
字号:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit tempra=P1^0; //继电器控制端口
sbit DS=P1^7; //DS18B20数据输出
void mdelay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*~~~~~~~~~~~~液晶显示定义~~~~~~~~~~~~~~~~*/
sbit E=P2^4;
sbit RS=P2^6;
sbit RW=P2^5;
const uchar NoDisp=0;
const uchar NoCur=1;
const uchar CurNoFlash=2;
const uchar CurFlash=3;
/*~~~~~~~~~~~~液晶显示驱动~~~~~~~~~~~~~~~~*/
void WaitIdle()
{
RS=0;
RW=1;
E=1;
mdelay(5);
while((P0&0x80)==0x80)//控制字最高位为'1' 才能允许读写操作
{
E=0; //这两句protues仿真必须加;仿真器仿真也通过。
E=1;
};
E=0;
}
void LcdWcn(uchar c) //无忙时检测 向液晶写入命令
{
RS=0;
RW=0;
P0=c;
mdelay(5);
E=1;
mdelay(5);
E=0;
}
void LcdWc(uchar c) //有忙时检测 向液晶写入命令
{
WaitIdle();
LcdWcn(c);
}
void LcdWd(uchar c) //有忙时检测 向液晶写入数据
{
WaitIdle();
RS=1;
RW=0;
P0=c;
mdelay(5);
E=1;
mdelay(5);
mdelay(5);
E=0;
}
void ClrLcd() //显示清屏
{
LcdWc(0x01);
}
void RstLcd() //初始化
{
E=0;
LcdWc(0x38); //显示模式设置 16*2
LcdWc(0x0f); //开显示 开光标 光标闪烁
LcdWc(0x06); //读或写一个字节侯 光标加1 指针加1
LcdWc(0x01); //显示清屏
}
void SetCur(uchar Para)
{
mdelay(2);
switch(Para)
{ //光标模式设置
case 0:LcdWc(0x08);break; // NoDisp
case 1:LcdWc(0x0c);break; // NoCur
case 2:LcdWc(0x0e);break; // CurNoFlash
case 3:LcdWc(0x0f);break; // CurFlash
default:break;
}
}
void LcdPos(uchar xPos,uchar yPos)
{
uchar tmp;
xPos&=0x0f; //列定位 最大为16列
yPos&=0x01; //行定位 最大为2行
if(yPos==0)
tmp=xPos;
else
tmp=xPos+0x40; //第二行第一列的地址为 0x80+0x40
tmp|=0x80; //第一行第一列的地址为 0x80
LcdWc(tmp);
}
void WriteChar(uchar c,uchar xPos,uchar yPos)
{ //在指定位置写入一个字符
LcdPos(xPos,yPos);
LcdWd(c);
}
void WriteString(uchar *s,uchar xPos,uchar yPos)
{ //在指定位置写入一个字符串
uchar i;
if(*s==0)
return;
for(i=0;;i++)
{
if(*(s+i)==0)
break;
WriteChar(*(s+i),xPos,yPos);
xPos++;
if(xPos>=15)
break;
}
}
/*~~~~~~~~~~~~~~~~~~18B20驱动~~~~~~~~~~~~~~~~~~~*/
void dsreset(void) // DS18B20初始化
{
uint i;
DS=0; // 首先拉低,要求480us
i=103;
while(i>0)i--;
DS=1; // 上升沿,要求15~60us
i=4;
while(i>0)i--;
}
void rxwait() //等待应答脉冲
{
uint i;
while(DS);
while(~DS);
i=8;while(i>0)i--;
}
bit tmpreadbit(void) //读一位
{
uint i;
bit dat;
DS=0;
i++; //1us延时
DS=1; //15us内,主机必须停止将DS引脚置低
i++;i++; //15us延时
dat=DS;
i=8;while(i>0)i--; //读时隙不低于60us延时
return (dat);
}
uchar tmpread(void) // 读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void tmpwritebyte(uchar dat) //写一个字节到DS18B20里
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写1部分
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //写0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //发送温度转换命令
{
dsreset(); //初始化DS18B20
rxwait(); //等待应答脉冲
mdelay(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}
uint tmp() //获得温度
{
float tt;
uchar a,b;
uint temp;
dsreset();
rxwait(); //等待应答脉冲
mdelay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp<<=8; //出厂默认设置为12位分辨率
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
temp=tt*1000+0.5; //放大百倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
void main()
{
uchar xPos0,yPos0,xPos1,yPos1,i;
uchar * s0;
uint temp;
uchar A1,A2,A3,A4,A5;
RstLcd();
ClrLcd();
SetCur(NoCur);
xPos0=0;yPos0=0;
s0="Temperature is:";
WriteString(s0,xPos0,yPos0);
xPos1=2;yPos1=1; //显示小数点 温度单位
WriteChar('.',xPos1,yPos1);
xPos1=6;yPos1=1;
WriteChar(0xdf,xPos1,yPos1);
xPos1=7;yPos1=1;
WriteChar(0x43,xPos1,yPos1);
while(1)
{
for(i=0;i<=5;i++)
{
tmpchange();
temp=tmp();
A1=temp/10000;
A2=temp%10000/1000;
A3=temp%1000/100;
A4=temp%100/10;
A5=temp%10;
if(i>1)
{
xPos1=0;yPos1=1;
WriteChar(0x30+A1,xPos1,yPos1);
xPos1=1;yPos1=1;
WriteChar(0x30+A2,xPos1,yPos1);
xPos1=3;yPos1=1;
WriteChar(0x30+A3,xPos1,yPos1);
xPos1=4;yPos1=1;
WriteChar(0x30+A4,xPos1,yPos1);
xPos1=5;yPos1=1;
WriteChar(0x30+A5,xPos1,yPos1);
}
if(temp<30000)
tempra = 0; //继电器打开 加热
if(temp>30000)
tempra = 1; //继电器关闭 冷却
mdelay(300);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -