一,温度传感器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通信,直接给设备发信号就行,按照通信协议,构造出设备的起始,停止,工作以及查询指令,发给设备,设备对应会进行相应的反馈,不需要控制这种底层的电平逻辑,相对于这种需要控制电平,并且一个字节读取,之前的构造数据包的还是比较简单的。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐