VHDL编写的DS18B20驱动代码

使用VDHL编写了一个DS18B20的驱动代码,实现12位精度的温度采集,输出使用原始数据输出,需要自己进行符号位及小数位的处理。

时钟50MHz,DATA_RD高电平时,输出有效,这里可以自己再修改一下。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

ENTITY DS18B20 IS
PORT(	clk			: in std_logic;		--50Mhz
		rerst		: in std_logic;
		
		DQ_OUT			: inout std_logic;
		
		data_req	: in std_logic;
		data_out	: out std_logic_vector(11 downto 0);
		data_rd		: out std_logic
	);
END ENTITY DS18B20;

ARCHITECTURE behav OF DS18B20 IS
	--SIGNAL Define
	SIGNAL div_clk : std_logic;
	SIGNAL DQ : std_logic;
	SIGNAL data_out_temp : std_logic_vector(11 downto 0);
BEGIN
	--Always run
	DQ_OUT <= DQ;
	data_out <= data_out_temp;

low_clock:PROCESS(clk,rerst)IS
		VARIABLE count1 : std_logic_vector(4 downto 0);
	BEGIN
		if rerst='1' then
			div_clk <= '0';
			count1 := (others => '0');
		elsif rising_edge(clk) then
			if(count1 = "11000")then		--计数到24 50M时钟分频到1M
				div_clk <= not div_clk;
				count1 := (others => '0');
			else
				div_clk <= div_clk;
				count1 := count1 + '1';
			end if;
		end if;
	END PROCESS low_clock;	

main:PROCESS(div_clk,rerst)IS
		--VARIABLE Define
		VARIABLE count2 : integer range 0 to 510;
		VARIABLE delay : integer range 0 to 1000001;
		VARIABLE state : integer range 0 to 31;
		VARIABLE state_temp : integer range 0 to 12;
		VARIABLE readnum : integer range 0 to 12;
		VARIABLE sendnum : integer range 0 to 10;
		VARIABLE cmd : std_logic_vector(7 downto 0) := "00000000";
	BEGIN
		if rerst='1' then
			data_rd <= '0';
			DQ <= 'Z';
			count2 := 0;
			delay := 0;
			state := 0;
			state_temp := 0;
			readnum := 0;
			sendnum := 0;
		elsif rising_edge(div_clk) then
			case state IS
				--Initialization start
				WHEN 0 =>
					data_rd <= '0';
					count2 := 0;
					if(data_req = '1')then
						state := 1;
					else
						state := 0;
					end if;
				WHEN 1 =>
					state_temp := 2;
					count2 := 0;
					state := 12;	--rst and check DS18B20
				WHEN 2 =>
					cmd := "11001100";
					state_temp := 3;
					count2 := 0;
					state := 17;	--send 0xCC
				WHEN 3 =>
					cmd := "01000100";
					state_temp := 4;
					count2 := 0;
					state := 17;	--send 0x44
				WHEN 4 =>
					if(delay < 1000000)then
						delay := delay + 1;
						state := state;
					else
						delay := 0;
						state := 5;	--delay 1000ms
					end if;
				WHEN 5 =>
					state_temp := 6;
					count2 := 0;
					state := 12;	--rst and check DS18B20
				WHEN 6 =>
					cmd := "11001100";
					state_temp := 7;
					count2 := 0;
					state := 17;	--send 0xCC
				WHEN 7 =>
					cmd := "10111110";
					state_temp := 8;
					count2 := 0;
					state := 17;	--send 0xBE
				WHEN 8 =>
					state_temp := 9;
					count2 := 0;
					state := 21;	--read data
				WHEN 9 =>
					data_rd <= '1';
					state := 0;
				
----------------------------------------------------------------------
				
				--rst DS18B20
				WHEN 12 =>
					if(count2 <= 500)then
						DQ <= '0';
						count2 := count2 + 1;
						state := state;
					else
						DQ <= 'Z';
						count2 := 0;
						state := 13;
					end if;
				WHEN 13 =>
					if(count2 <= 30)then
						DQ <= 'Z';
						count2 := count2 + 1;
						state := state;
					else
						state := 14;
					end if;
				--check DS18B20
				WHEN 14 =>
					count2 := count2 + 1;
					if(DQ = '0')then
						state := 15;
					else
						state := state;
					end if;
				WHEN 15 =>
					if(count2 = 500)then
						count2 := 0;
						state := 16;
					else
						count2 := count2 + 1;
						state := state;
					end if;
				WHEN 16 =>
					state := state_temp;
				--send BYTE
				WHEN 17 =>
					DQ <= '0';
					count2 := 0;
					state := 18;
				WHEN 18 =>
					state := 19;
				WHEN 19 =>
					if(count2 <= 60)then		--send data
						count2 := count2 + 1;
						DQ <= cmd(sendnum);
						state := state;
					elsif(count2 <= 63)then		--send gap
						count2 := count2 + 1;
						DQ <= 'Z';
						state := state;
					else
						sendnum := sendnum + 1;
						count2 := 0;
						state := 20;
					end if;
				WHEN 20 =>
					if(sendnum <= 7)then
						state := 17;
					else
						sendnum := 0;
						state := state_temp;
					end if;
				--read BYTE
				WHEN 21 =>
					DQ <= '0';
					if(count2 <= 2)then
						count2 := count2 + 1;
						state := state;
					else
						count2 := 0;
						state := 22;
					end if;
				WHEN 22 =>
					DQ <= 'Z';
					state := 23;
				WHEN 23 =>
					if(count2 <= 10)then
						count2 := count2 + 1;
						state := state;
					else
						count2 := 0;
						data_out_temp <= DQ & data_out_temp(11 downto 1);
						state := 24;
					end if;
				WHEN 24 =>
					if(count2 <= 50)then
						DQ <= 'Z';
						count2 := count2 + 1;
						state := state;
					else
						count2 := 0;
						readnum := readnum + 1;
						state := 25;
					end if;
				WHEN 25 =>
					if(readnum <= 11)then
						state := 21;
					else
						readnum := 0;
						state := state_temp;
					end if;
				WHEN OTHERS =>
					cmd := "00110011";
					state := 0;
			end case;
		end if;
	END PROCESS main;
END ARCHITECTURE behav;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值