⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds18b20_.vhd

📁 自己写的一个测温元件(ds18b20)的驱动程序
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- 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 + -