C51-温度传感器显示
一,温度传感器DS18B20芯片
通过电源线两根,GND和VDD,通过控制DQ(P3^7)这个引脚,利用高低电平,以及相应的时间,能够控制温度传感器进行温度数据的传输,然后根据数据的格式,比如正负,数值大小,进行相应的转化,输出到数码管上,进行相应的显示。
初始化时序:
void DS18B20_reset(void)//复位脉冲
{
IO_PORT=0;
delay_10us(40);
IO_PORT=1;
delay_10us(2);
}
u8 DS18B20_ack(void)//判断响应
{
u8 count1=0;
IO_PORT=1;
while(IO_PORT==1&&count1<20)//因为复位脉冲后,为高电平,因此判断是不是一直保持高电平
{
count1++;
delay_10us(1);
}
if(count1>=20) return 1;//一直为高电平,不响应
else count1=0;
while((!IO_PORT)&&count1<20)//判断为低电平,然后判断是不是一直为低电平(不响应),若出现高电平证明有响应
{
count1++;
delay_10us(1);
}
if(count1>=20) return 1;//一直为低电平
return 0;
}
u8 DS18B20_init(void)//对复位和响应,即初始化
{
DS18B20_reset();
return DS18B20_ack();
}
写时序:

写的时候,若为1,低电平延时2us,然后为高电平,延时60ms,写1,低电平延时60,然后高电平,延时2us.
void DS18B20_write(u8 DS_date)//写 字节的低位开始 从低到高
u8 i=0;
for(i=0;i<8;i++)
{
if(DS_date&0x01==1)// 低位为1
{
IO_PORT=0;
_nop_();_nop_();
IO_PORT=1;
delay_10us(6);
}else//为0
{
IO_PORT=0;
delay_10us(6);
IO_PORT=1;
_nop_();_nop_();
}
DS_date>>=1;//把次低位移动过来
}
}
读时序:

由0变为1,按照2us,然后判断其高低电平,高电平则1,低电平则0,因为为读函数,因此要读出一个结果,函数定义为unsigned char类型。
u8 DS18B20_read(void)//¶Á×Ö½Ú
{
u8 DS_result=0,i=0;
for(i=0;i<8;i++)
{
IO_PORT=0;
_nop_();_nop_();
IO_PORT=1;
_nop_();_nop_();
DS_result>>=1;
if(IO_PORT==0)
{
DS_result=DS_result&0x7f;
}
else
{
DS_result=DS_result|0x80;
}
delay_10us(5);
}
return DS_result;
}
整体流程:DS18B20 的典型温度读取过程为:复位→发 SKIP ROM 命令(0XCC)→发开始转 换命令(0X44)→延时→复位→发送 SKIP ROM 命令(0XCC)→发读存储器命令 (0XBE)→连续读出两个字节数据(即温度)→结束。
float DS18B20_use(void)
{
u8 date_heigh=0,date_low=0;
float DS_result=0;
u16 change_result=0;
DS18B20_reset();
DS18B20_ack();
DS18B20_write(0xcc);
DS18B20_write(0x44);
DS18B20_reset();
DS18B20_ack();
DS18B20_write(0xcc);
DS18B20_write(0xbe);
date_low=DS18B20_read();
date_heigh=DS18B20_read();
change_result=(date_heigh<<8)|date_low;
if((change_result&0xf800)==0xf800)
{
change_result=~change_result+1;//Ϊ¸ºÊý
DS_result=change_result*(-0.0625);
}else
DS_result=change_result*0.0625;//ΪÕýÊý
return DS_result;
}
二,主函数和数码管函数
主函数:关键是把这个浮点型数据转化为数码管能显示数据,还要在前面有正负号的显示,因此对浮点型输出数据进行乘10处理,再把每一位用数码管显示。数码管显示时候,可以直接把传递数据变成数组,即每一位对应的数码管值,段选,把这个数组带到数码管的显示函数中。
#include "smg.h"
#include "T.h"
void main()
{
u16 on_result=0;
u8 DS18B20_0n[5];
DS18B20_init();
while(1)
{
on_result=DS18B20_use()*10;
if(on_result>0)
{
DS18B20_0n[0]=0x00;
}else
{
DS18B20_0n[0]=0x40;//ÏÔʾ¸ººÅ
on_result=-on_result;
}
DS18B20_0n[1]=xianshi_shuzhu[on_result/1000];//ǧλ
DS18B20_0n[2]=xianshi_shuzhu[on_result%1000/100];//bai
DS18B20_0n[3]=xianshi_shuzhu[on_result%1000%100/10]|0x80;
DS18B20_0n[4]=xianshi_shuzhu[on_result%1000%100%10];
smg_play(DS18B20_0n);
}
}
数码管函数:
#include "smg.h"
void smg_play(u8 dat[])
{
int i=0;
for(i=0;i<5;i++)
{
switch(i)
{
case 0:
WEIA=1;WEIB=1;WEIC=1;
smg_duan=dat[0];
break;
case 1:
WEIA=1;WEIB=1;WEIC=0;
smg_duan=dat[1];
break;
case 2:
WEIA=1;WEIB=0;WEIC=1;
smg_duan=dat[2];
break;
case 3:
WEIA=1;WEIB=0;WEIC=0;
smg_duan=dat[3];
break;
case 4:
WEIA=0;WEIB=1;WEIC=1;
smg_duan=dat[4];
break;
}
delay_10us(100);
smg_duan=0x00;
}
}
总结:这个实验跟上面的EPROM其实差不多,都是根据电平信号控制数据的传输,EPROM主要是通过时钟信号控制,这个是通过自己带的引脚控制,这个也最麻烦,控制这个电平信号的初始化(复位以及响应)和读写操作,处理过程中,主要对数据的读写,重要的是读完后,对特定格式数据的处理,把它转化为想要的数据格式,然后是去展示这个数据,利用数码管。
之前做485或者422通信,直接给设备发信号就行,按照通信协议,构造出设备的起始,停止,工作以及查询指令,发给设备,设备对应会进行相应的反馈,不需要控制这种底层的电平逻辑,相对于这种需要控制电平,并且一个字节读取,之前的构造数据包的还是比较简单的。
更多推荐
所有评论(0)