【学习笔记】DS18B20

        DS18B20 是单总线数字温度传感器,其可直接将温度 转化成数字信号输出,具有体积小、低功耗、抗干扰能力强、精度高等优点。

        同红外遥控,时间有点远。不再给出数码管显示模块代码,只是给出DS18B20代码。

状态机:

 

 

 

 DS18B20模块:

 

 

 

 

 代码:

module DS18B20	(
	input	wire	clk_sys		,
	input	wire	rst_n_sys	,
	
	inout	wire	dq				,
	
	output	reg	[19:0]data	,
	output	reg	sign			
);

parameter	INIT			=6'B000_001		,
				WR_CMD		=6'B000_010		,
				WAIT			=6'B000_100		,
				INIT_AGAIN	=6'B001_000		,
				RD_CMD		=6'B010_000		,
				RD_TEMP		=6'B100_000		;

parameter	INIT_CNT		=20'D999			,
				WAIT_CNT		=20'D750_000	,
				CMD_CNT		=20'D64			,
				CMD_CNT_GET	=20'D30			,
				TEMP_CNT_GET=20'D13			;
				
parameter	CNT_BIT_CMD_MAX	=4'd15			,
				CNT_BIT_TEMP_MAX	=4'D15		;

parameter	WR_44_CC		=16'H44_CC	,
				RD_BE_CC		=16'HBE_CC	;


	reg	us_clk				;
	reg	[4:0]cnt_us			;

	reg	[5:0]state			;
	reg	[19:0]cnt_state	;
	reg	[3:0]cnt_bit		;
	reg	flag_init			;
	reg	[15:0]temp			;
	reg	[11:0]reg_date		;
	reg	dq_en					;
	reg	dq_out				;
	
assign	dq= (dq_en==1'b1)?dq_out:1'bz	;	
	
	

always@(posedge clk_sys or negedge rst_n_sys)
	if(!rst_n_sys)
		cnt_us<=5'b0			;
	else	if (cnt_us==5'd24)
		cnt_us<=5'b0			;
	else	
		cnt_us<=cnt_us+1'b1	;
	
always@(posedge clk_sys or negedge	rst_n_sys)
	if(!rst_n_sys)
		us_clk<=1'b0			;
	else	if(cnt_us==5'd24)
		us_clk<=~us_clk		;
	else
		us_clk<=us_clk			;
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		state	<=	INIT	;
	else	
		case(state)
			INIT:
				if (flag_init==1'b1  && cnt_state==INIT_CNT)
					state<=WR_CMD		;
				else
					state<=state		;
			WR_CMD:
				if (cnt_bit==CNT_BIT_CMD_MAX && cnt_state==CMD_CNT)
					state<=WAIT			;
				else		
					state<=state		;
			WAIT:
				if	(cnt_state==WAIT_CNT)
					state<=INIT_AGAIN	;
				else
					state<=state		;
			INIT_AGAIN:
				if (flag_init==1'b1  && cnt_state==INIT_CNT)
					state<=RD_CMD		;
				else
					state<=state		;
			RD_CMD:
				if (cnt_bit==CNT_BIT_CMD_MAX && cnt_state==CMD_CNT )
					state<=RD_TEMP		;
				else		
					state<=state		;
			RD_TEMP:
				if(cnt_bit==CNT_BIT_TEMP_MAX && cnt_state==CMD_CNT)
					state<=INIT			;
				else
					state<=state		;
			default:	state<=INIT		;
			endcase
			
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		begin
		dq_out<=1'b0	;
		dq_en	<=1'b0	;
		end
	else	
		case(state)
			INIT:
				if(cnt_state<=20'd500)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
				else 
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
			WR_CMD:
				if(WR_44_CC[cnt_bit]==1'b0)
					if(cnt_state>=20'd63)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
					else
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
				else if(WR_44_CC[cnt_bit]==1'b1)
					if(cnt_state>=20'd2)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
					else
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
			WAIT:
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b1		;
					end
			INIT_AGAIN:
					if(cnt_state<=20'd500)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
				else 
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
			RD_CMD:
				if(RD_BE_CC[cnt_bit]==1'b0)
					if(cnt_state>=20'd63)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
					else
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
				else if(WR_44_CC[cnt_bit]==1'b1)
					if(cnt_state>=20'd2)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
					else
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
			RD_TEMP:
				if(cnt_state<=1)
					begin
					dq_en	<=1'b1		;
					dq_out<=1'b0		;
					end
				else	
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
			default:	
					begin
					dq_en	<=1'b0		;
					dq_out<=1'b0		;
					end
		endcase
		
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		cnt_state<=20'd0				;
	else	if (((state==RD_TEMP || state==WR_CMD ||state==RD_CMD)&&cnt_state==CMD_CNT)||
			((state==INIT || state==INIT_AGAIN) && cnt_state==INIT_CNT)||
			(state==WAIT && cnt_state==WAIT_CNT))
		cnt_state<=20'd0				;
	else	
		cnt_state<=cnt_state+1'b1	;
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		flag_init<=1'b0					;
	else if(state==INIT_AGAIN || state==INIT )
		if(cnt_state==20'd600 && dq==1'b0)
			flag_init<=1'b1				;
		else
			flag_init<=flag_init			;
	else
		flag_init	<=1'b0				;
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		cnt_bit<=4'd0				;
	else if((((state==WR_CMD ||state==RD_CMD )&& cnt_bit==CNT_BIT_CMD_MAX ) ||
				(state==RD_TEMP && cnt_bit==CNT_BIT_TEMP_MAX))&& cnt_state==CMD_CNT)
		cnt_bit<=4'd0				;
	else	if(state==RD_TEMP || state==WR_CMD ||state==RD_CMD)
		cnt_bit<=cnt_bit+1'b1	;
	else	
		cnt_bit<=4'b0				;
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		temp<=1'b0				;
	else	if(state==RD_TEMP && cnt_state==TEMP_CNT_GET)
		temp[cnt_bit]<=dq		;
	else
		temp<=temp				;

always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		begin
		reg_date	<=12'd0					;
		sign		<=1'b0					;
		end
	else	if(state==RD_TEMP && cnt_bit==CNT_BIT_TEMP_MAX && cnt_state==20'd60)
		if (temp[15]==1'b0)
			begin
			reg_date	<=temp[11:0]		;
			sign		<=1'b0				;
			end
		else 
			begin
			reg_date	<=~temp[11:0]+1'b1	;
			sign		<=1'b1					;
			end
	else
		begin
		reg_date	<=reg_date					;
		sign		<=sign						;
		end
		
always@(posedge us_clk or negedge rst_n_sys)
	if(!rst_n_sys)
		data<=19'd0									;		
	else 
		data<=(temp[11:0]*10'd625)/4'd10		;
		

		
		
endmodule
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
单片机使用系统设计 课 题:基于DS18B20的多点温度测量系统的设计 姓 名: 班 级: 学 号: 指导老师: 日 期: 引 言 在粮库测温系统、冷库测温系统、智能化建筑控制系统、中央空调系统等多种系统中都 需要多点温度测量系统。因此,多点温度测量技术实现尤为重要。美国Dallas公司推出 的数字温度传感器DSl8B20,电源供电范围在3.0~5.5V;温度测量范围为- 55~+125 ;具有独特的单总线接口,仅需要占用一个通用I/O端口即可完成和微处理器 的通信;在- 10~+85 温度范围内具有±0.5 精度;用户可编程设定9~12位的分辨率。以上特性使得 DSl8B20非常适用于构建高精度、多点温度测量系统。 DS18B20简介 DSl8B20是美国Dallas半导体公司推出的一种智能数字温度传感器。和传统的热敏电阻相 比,它能够直接读出被测温度,并且可根据实际要求通过编程实现9~12位的数字值读数 方式;可以分别在93.75ms和750 ms内完成9位和12位的数字量;从DS18B20读出信息或写入DS18B20信息仅需要1根口线(单 线接口);温度变换功率来源于数据总线,总线本身也可以向所挂接的DS18B20供电,而 无需额外电源。使用DS18B20可使系统结构更趋简单,可靠性更高。 1系统硬件设计 由DS18B20和Atmel公司推出的单片机AT89C51以及相关外围电路组成的高精度、多点温度 测量系统的结构框图如图1所示。系统采用8片DS18B20构成小型温度传感器网络[3],通 过并行连接方式连接至单片机的通用I/O端口。单片机获得温度信息后,通过特定的算法 ,将处理后的温度信息通过LED显示出来,同时通过串行口送上位机处理。 DS18B20内部均有一个独立的64位序列号,单片机通过序列号可以对一条总线上的多支D S18B20进行控制,读取它们的温度。但是,要完成这个操作,软件设计比较复杂,同时 存在一个缺点——速度太慢。无法适用于一些实时性要求高的测温场合。所以本次设计采 取一种利用单片机的并口,同步快速读取8支DS18B20的方法。 2系统软件设计 2.1 并行同步快速读取8支DS18B20的方法 对于一支DS18B20,我们要输出或输入各类数据时,可以采用位寻址,比如:sbit DQ=P3^3; DQ=0; DQ=1; 而对于8支DS18B20,如果还采用位寻址的方法,采用单总线,通过查询序列号依次读取 ,程序就非常复杂,而且速度会大大减慢,所以将位寻址扩展为字节寻址,比如: #define DQ P3; DQ=0x00; DQ=0xff; 即可一次输出或输入8个位数据,从而达到同步读取的目的。 2.2 系统的温度合成处理 采用上述方法一次读取8支DS18B20的时间不超过1秒,但读取的数据在RAM中并不顺序排 列的。必须用软件合成处理,才能得到所需要的温度值。如表- 1所示,纵向排列的是存放每次读取数据的Buf,而横向才是我们需要的温度值,此时设计 一个将纵向数据转为横向温度的程序,连续执行两次,就可以将DS18B20的高和低字节全 部合成标准的温度数据。 2.3 系统软件流程图 主程序执行流程如图2所示,主程序先对各DS18B20进行初始化,然后重复调用写命令和 读数据模块,最后将数据处理后送入LED显示。 2. 4 系统电路图 3系统仿真 Proteus软件是Labcenter公司的一款电路设计和仿真软件,它包括ISIS、ARES等软件模 块,ARES模块主要用来完成PCB的设计,而ISIS模块用来完成电路原理图的绘制和仿真。 Proteus的软件仿真基于VSM技术,它和其他软件最大的不同也是最大的优势就在于它能 仿真大量的单片机芯片,比如MCS- 51系列、PIC系列等等,以及单片机外围电路,比如键盘、LED、LCD等等。通过Proteus 软件的使用我们能够轻易地获得一个功能齐全、实用方便的单片机实验环境。 本设计的核心部分为八点温度数据的快速准确读取,完成电路设计和软件编程后,将程 序在KEIL下编译,装入单片机,进行仿真,可以看到,同步快速多点温度测量得到了实 现。仿真中的一个画面如下面图3中的效果所示,此时采集的是第5通路的测量温度。 4系统运行和数据分析 根据系统软件和硬件设计方案搭建实际系统电路,依次采集八路温度测量数据,并且在 LED数码管上显示所测温度,同时和现场温度计测量值进行比较,系统运行结果如下,见 表-2: 表-2 传感器和温度计数据对照 测量结果数据和温度计直接测量吻合,符合仿真结果,本系统的测量范围为0-99 ,DS 18B20数字值读取位数为8位,精确到1 ,满足日常测量使用。另外可以通过改变DS18B2 0数字值读取位数提高精度,也可以根据实际使用要求扩大量程。在

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值