基于Proteus的DS18B20仿真实验

目的:

                使用DS18B20测量温度,并通过单片机在数码管上显示出来.(本次仿真使用的是一个传感器)

硬件内容:

        DS18B20结构如下:                       

        RAM中 64位序列号在出厂时已经设置好,相当于传感器的地址,用于一根总线上挂载多个传感器时,主设备搜索的依据。 


        配置寄存器用于选择传感器的运作方式和配置温度变化的精度,结构如下:

         TM:模式测量位,该位为“0”时是工作模式,为“1”时是测量模式(默认为0,不需要改动)。

        R0,R1:温度测量精度选择位。写入不同的位数,设置传感器的测量精度(默认精度为0.0625°C)

R0R1温度测量精度
000.5°C
010.25°C
100.125°C
110.0625°C


         高速缓存寄存器:由9个字节组成,但是本实验只需要前两个字节,传感器测量后温度会以二进制补码的形式将数据存放于前两个字节。高八位,前5位为符号位S,后11位为数据位。数据格式如下。

        MS Byte:高八位

         LS Byte:低八位

 

         如果测得的温度大于 0,S位为‘ 0’,只要将测到的数值乘以 0.0625 (默认精度是 12 位)即可得到实际温度;如果温度小于 0,这 5 位为‘ 1’, 测到的数值需要取反加 1 再乘以 0.0625 即可得到实际温度。温度与数据对应 关系如下:

 

设计思路: 

        通过DS18B20来测量温度,采用电源供电,然后讲数据传单片机并在数码管上实现显示。数据低位在前,高位在后。过程其实很简单,只需要记住几个时序就可以,分别为,写时序,读时序,初始化时序

        测量过程:复位→发 SKIP ROM 命令(0XCC)→发开始转 换命令(0X44)→延时→复位→发送 SKIP ROM 命令(0XCC)→发读存储器命令 (0XBE)→连续读出两个字节数据(即温度)→结束

        DS18B20:要实现数据的读取和命令的写入,首先需要初始化,然后是写时序和读时序。而两种时序又分别为写0、写1、读0、,读1;

        初始化(传感器的一切指令起始于初始化):主机低电平,持续480us,主机高电平,延时15-60us

        写时序(用于命令的写入):总时长至少60us,两次写时序之间间隔至少2us

        写1:主机低电平,延时2us,主机高电平,延时60us

        写0:主机低电平,延时60us,主机高电平,延时2us

         读时序(用于温度数据的读取):主机输出低电平延时 2us,然后主机转入输入模式延 时 12us,然后读取单总线当前的电平,然后延时 50us。

软件内容:

        DS18B20配置函数如下:

void ds18b20_reset(void)//初始化函数
{
	DS=0;	//拉低DQ
	delay_10us(75);	//拉低750us
	DS=1;	//DQ=1
	delay_10us(2);	//20US
}

u8 ds18b20_check(void)//检测函数
{
	u8 time_temp=0;

	while(DS&&time_temp<20)	//等待DQ为低电平
	{
		time_temp++;
		delay_10us(1);	
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	else time_temp=0;
	while((!DS)&&time_temp<20)	//等待DQ为高电平
	{
		time_temp++;
		delay_10us(1);
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	return 0;
}

u8 ds18b20_read_bit(void)//读取一位函数
{
	u8 dat=0;
	
	DS=0;
	_nop_();_nop_();
	DS=1;	
	_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
	if(DS)dat=1;	//如果总线上为1则数据dat为1,否则为0
	else dat=0;
	delay_10us(5);
	return dat;
} 

u8 ds18b20_read_byte(void)//读取一个字节函数
{
	u8 i=0;
	u8 dat=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次读取一位,从低到高
	{
		temp=ds18b20_read_bit();
		dat=(temp<<7)|(dat>>1);
	}
	return dat;	
}

void ds18b20_write_byte(u8 dat)//写命令函数
{
	u8 i=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
	{
		temp=dat&0x01;//选择低位准备写入
		dat>>=1;//将次高位移到低位
		if(temp)
		{
			DS18B20_PORT=0;
			_nop_();_nop_();
			DS18B20_PORT=1;	
			delay_10us(6);
		}
		else
		{
			DS=0;
			delay_10us(6);
			DS=1;
			_nop_();_nop_();	
		}	
	}	
}

void ds18b20_start(void)//开始转换函数
{
	ds18b20_reset();//复位
	ds18b20_check();//检查DS
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0x44);//转换命令	
}

u8 ds18b20_init(void)//初始化函数
{
	ds18b20_reset();
	return ds18b20_check();	
}

float ds18b20_read_temperture(void)//温度处理函数
{
	float temp;
	u8 dath=0;
	u8 datl=0;
	u16 value=0;

	ds18b20_start();//开始转换
	ds18b20_reset();//复位
	ds18b20_check();
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0xbe);//读存储器

	datl=ds18b20_read_byte();//低字节
	dath=ds18b20_read_byte();//高字节
	value=(dath<<8)+datl;//合并为16位数据

	if((value&0xf800)==0xf800)//判断符号位,负温度
	{
		value=(~value)+1; //数据取反再加1
		temp=value*(-0.0625);//乘以精度	
	}
	else //正温度
	{
		temp=value*0.0625;	
	}
	return temp;
}

主函数如下:

#include "public.h"
#include "smg.h"
#include "ds18b20.h"

u8 a[4]={0x01,0x02,0x04,0x08};


void main()
{	
	u8 i=0;
   	int temp_value;
	u8 temp_buf[5];

	ds18b20_init();//初始化DS18B20

	while(1)
	{	
		u8 j;
		i++;
		if(i%50==0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间
			temp_value=ds18b20_read_temperture()*10;//保留温度值小数后一位
		if(temp_value<0)//负温度
		{
			temp_value=-temp_value;
			temp_buf[0]=0xbf;//显示负号	
		}
		else
			temp_buf[0]=0xff;//不显示
		//temp_buf[1]=gsmg_code[temp_value/1000];//百位
		temp_buf[1]=gsmg_code[temp_value%1000/100];//十位
		temp_buf[2]=gsmg_code[temp_value%1000%100/10]&0x7f;//个位+小数点
		temp_buf[3]=gsmg_code[temp_value%1000%100%10];//小数点后一位
		//smg_display(temp_buf);
		
	
		for(j=0;j<4;j++)
		{
			SMG_A_DP_PORT=temp_buf[j];
			DIS=a[j];
			delay_10us(100);
			SMG_A_DP_PORT=0xff;
			
		}
		

	}		
}

延时函数:

#include "public.h"


void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}


void delay_ms(u16 ms)
{
	u16 i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
}

原理图:

 

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
基于Proteus仿真的30秒计时器课程设计是一项将电子设计与编程应用于实际场景中的项目。该设计旨在培养学生的电子设计和编程能力,同时加深对计时器原理的理解。 首先,我们需要使用Proteus软件进行电路设计。我们可以利用555定时器芯片和一些其他电子元件设计一个简单的30秒计时器电路。学生需要了解555定时器的工作原理和引脚连接方式,并在Proteus中进行电路设计。通过仿真,学生可以验证电路的正确性并进行调试。 接下来,我们需要编程实现30秒计时功能。学生可以选择使用C语言或基于Arduino的编程语言进行编程。他们需要能够通过代码控制计时器的开始、暂停和重置功能。通过编程,学生不仅可以理解计时器工作的原理,还可以培养他们的编程能力。 在课程设计中,我们可以设置一些实际的应用场景,如定时开关灯、计时比赛等,让学生将仿真和实际应用相结合。这样学生可以将所学的知识应用于实际情境中,提高他们的综合能力和问题解决能力。 此外,我们还可以设置一些实验和小组项目,让学生在实际操作中更深入地了解电子设计和编程方面的知识。这些实践项目可以提高学生的动手能力和团队合作精神。 总之,基于Proteus仿真的30秒计时器课程设计可以帮助学生理解电子设计原理、提高他们的编程能力,并将所学的知识应用于实际场景中。这个课程设计将帮助学生培养综合能力和问题解决能力,为他们未来的学习和职业发展打下坚实基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值