📄 ds18b20_.vhd
字号:
-- modifed by Butcher 2009/3/20 17:07:34
-- DS18b20 驱动程序
-- 使用外部电源 3.3V
-- 间隔100ms 检测一次温度
-- 只读出了12位温度数据
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--**********************************************************************************
entity ds1820 is
port(P_Reset : in std_logic;
P_CLK24 : in std_logic;
P_dq : inout std_logic;
P_RD_Temp : out std_logic_vector(11 downto 0)
);
end ds1820;
--*****************************************************************************
architecture Behavioral of ds1820 is
TYPE STATE_TYPE is (T_Reset_st , T_CMD_CC , T_CMD_44 , T_CMD_BE ,
T_WriteByte, T_ConvWait, T_Write0 , T_Write1 ,
T_Read_Bit , T_GetTemp, T_DS_Rest);
signal S_State : STATE_TYPE:=T_Reset_st; -- 状态机
signal S_CLK_1M : std_logic := '0'; -- 一兆赫兹的脉冲
signal S_RD_Bit : std_logic;
begin
-- 此处使用24MHz的时钟分频为1MHz的时钟
L_ClkDivider: process (P_Reset,P_CLK24)
variable V_Count : integer range 0 to 25:=0;
begin
if P_Reset = '0'then
V_Count := 0 ;
S_CLK_1M <= '0';
else
if rising_edge(P_CLK24) then
if (V_Count = 12) then
V_Count := 0;
S_CLK_1M<= not S_CLK_1M;
else
V_Count := V_Count +1;
end if;
end if;
end if;
end Process;
--===============================================================================
-- DS18b20 驱动程序
L_STATE_TRANSITION: process(P_Reset,S_State,S_CLK_1M)
variable V_Counter : integer range 0 to 300_009:=0; -- 计数器
variable V_ms_Counter : integer range 0 to 101 :=0; -- 毫秒计时器
variable V_WRByteCNT : integer range 0 to 4:=0; -- 字节计数器 (写)
variable V_WR_BitCNT : integer range 0 to 8:=0; -- 位计数器 (写)
variable V_RD_BitCNT : integer range 0 to 12:=0; -- 位计数器 (读)
variable V_ReadTemp : std_logic_vector(11 downto 0):= X"000"; -- 读数据缓存
variable V_WriteTemp : std_logic_vector(7 downto 0):= X"00"; -- 写数据缓存
variable V_Write0_CNT : integer range 0 to 2:=0; -- 写0 的状态机
variable V_Write1_CNT : integer range 0 to 2:=0; -- 写1 的状态机
variable V_DS_Read_st : integer range 0 to 3:=0; -- 读一个bit的状态机
begin
if P_Reset = '0' then
S_State <= T_Reset_st;
V_ReadTemp := X"000";
V_WR_BitCNT := 0;
V_WRByteCNT := 0;
V_RD_BitCNT := 0;
V_ms_Counter := 0;
else
if rising_edge(S_CLK_1M) then
case S_State is
when T_Reset_st => -- 复位状态
if V_Counter < 500 then
V_Counter := V_Counter+1;
P_dq<='0';
elsif V_Counter < 515 then
V_Counter := V_Counter+1;
P_dq<='1';
S_State<=T_Reset_st;
elsif V_Counter < 560 then
V_Counter := V_Counter+1;
P_dq <= 'Z';
elsif V_Counter < 800 then
if P_dq = '0' then -- DS18b20 回应 低电平
S_RD_Bit <= '0'; -- 实际是给后面的判断用
V_Counter := 800; -- 跳出此处
else
S_RD_Bit <= '1'; -- 实际是给后面的判断用
V_Counter := V_Counter+1;
end if;
elsif V_Counter < 1288 then
V_Counter := V_Counter+1;
else
if S_RD_Bit = '0' then --
S_State <= T_CMD_CC;
else
S_State <= T_Reset_st;
end if;
V_Counter := 0;
end if;
when T_CMD_CC=> --Master issues Skip ROM command
V_WriteTemp:= X"CC";
S_State <= T_WriteByte;
when T_CMD_44=> -- 温度转换命令
V_WriteTemp:= X"44";
S_State<=T_WriteByte;
when T_ConvWait=> -- 等待温度转换完成
if V_Counter < 20 then
P_dq <= '1';
V_Counter := V_Counter + 1;
elsif V_Counter < 50 then
P_dq <= 'Z';
V_Counter := V_Counter + 1;
elsif (V_Counter <240_000) then
if V_ReadTemp = X"FFF" then -- 读到全是高电平
S_State <= T_Reset_st;
V_Counter := 0;
V_ReadTemp := X"000" ;
else
V_ReadTemp := V_ReadTemp(10 downto 0) & '0'; -- 左移一位
V_ReadTemp(0) := P_dq;
V_Counter := V_Counter + 1;
end if;
else -- 超时 没有等到转换成功
S_State <= T_Reset_st;
V_Counter := 0;
V_ReadTemp := X"000" ;
V_WRByteCNT := 0;
end if;
when T_CMD_BE=>
V_WriteTemp:= X"BE";
S_State <= T_WriteByte;
when T_WriteByte=>
case V_WR_BitCNT is
when 0 to 7 =>
if (V_WriteTemp(V_WR_BitCNT)='0') then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -