程序编程代考

程序编程代考 library IEEE;  use IEEE.STD_LOGIC_1164.ALL;  use IEEE.STD_LOGIC_ARITH.ALL;  use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ds18B20 is

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

dq  : inout std_logic;  –DQ数据输出输入端

rst: in std_logic;

 

LED : out std_logic;    –指示灯,标志程序进行到哪一步

LED2 : out std_logic;

LED3 : out std_logic;

 

dataout1,dataout2,dataout3 : out std_logic_vector(6 downto 0 ));  –数据输出端

end ds18B20;

 

architecture Behavioral of ds18B20 is

 

TYPE  STATE_TYPE  is (RESET,CMD_CC,WRITE_BYTE,WRITE_LOW,WRITE_HIGH,READ_BIT,

<span style=”white-space:pre”> </span>CMD_44,CMD_BE,WAIT800MS,GET_TMP,WAIT4MS);   –状态机

signal STATE: STATE_TYPE:=RESET;   –初始化状态机

 

signal clk_temp : std_logic:=’0′;  –监测总线上的数据

signal clk1m : std_logic; –分频后得到的1M时钟

signal cp: std_logic;  — 为时序而产生的1ms时钟

 

begin  程序编程代考

———-分频程序,分到1MHz—————-

ClkDivider:process (clk,clk_temp)

begin

if rising_edge(clk) then

if (count = 24) then

count <= 0;

clk_temp<= not clk_temp;

else

count <= count +1;

end if;

end if;

clk1m<=clk_temp;

end Process;

———-为时序产生1ms时钟—————-

 

process (clk1m)

variable n: integer range 0 to 12000:=0;

begin             —–cp 1ms

if rising_edge(clk1m) then

n:=n+1;

if (n>12000) then n:=0;  cp<=not cp;  end if;

end if;

end Process;

STATE_TRANSITION:process(STATE,clk1m)    –重头戏,状态机开始啦

begin

if rising_edge(clk1m) then

if(rst=’0′) then

STATE<=RESET;

else

case STATE is

when RESET=>  –如果处在复位状态

LED2<=’0′;

LED3<=’0′;

if (cnt>=0 and cnt<500) then — 500μs的复位低电平

dq<=’0′;   –dq作为输出

cnt<=cnt+1;

STATE<=RESET;  –在一定时序内保持复位状态

elsif (cnt>=500 and cnt<510) then

dq<=’Z’;  –高阻态再输入下一级电路的话,对下级电路无任何影响,和没接一样,高阻态可以应用在inout端口里面,这样在inout没有输出的时候就弄个高阻态,这样就其电平就可以由外面的输入信号决定了

       cnt<=cnt+1; 程序编程代考

STATE<=RESET;  –拉高dq

elsif (cnt>=510 and cnt<750) then   — 240μs

temp<=dq;  –dq作为输入(对于控制器来说是输入,对于DS18b20来说是输出,这个道理大家应该都明白吧)

if(cnt=580) then

temp<=dq;

if(temp=’1′) then  –如果temp为1说明DS18B20存在(因为检测到了存在脉冲)

LED<=’0′;

else

程序编程代考
程序编程代考

LED<=’1′;

end if;

end if;

cnt<=cnt+1;

STATE<=RESET;

elsif (cnt>=750) then  –初始化时序结束

cnt<=0; –计数器清零

STATE<=CMD_CC;  –复位过程伴随着忽略rom指令“CC”

end if;

when CMD_CC=>  –忽略rom指令“CC”

LED2<=’1′;

LED3<=’0′;

write_temp<=”11001100″;  –将write_temp设为“11001100”

STATE<=WRITE_BYTE;

when WRITE_BYTE=>

case WRITE_BYTE_CNT is

when 0 to 7=>

if (write_temp(WRITE_BYTE_CNT)=’0′) then  –判断当前write_temp第WRITE_BYTE_CNT上是否为’0′

STATE<=WRITE_LOW;  –如果当前write_temp第WRITE_BYTE_CNT上是’0’,进入WRITE_LOW状态(即对DS18b20写低)

LED3<=’1′;

           else 程序编程代考

STATE<=WRITE_HIGH;  –如果当前write_temp第WRITE_BYTE_CNT上是’1’,进入WRITE_HIGH状态(即对DS18b20写高)

end if;

WRITE_BYTE_CNT<=WRITE_BYTE_CNT+1;  –判断write_temp的下一位

when 8=>

if (WRITE_BYTE_FLAG=0) then — 第一次写0XCC完毕

STATE<=CMD_44;  –开启温度转换指令

WRITE_BYTE_FLAG<=1;

elsif (WRITE_BYTE_FLAG=1) then –写0X44完毕 (写温度转换指令后没有读数据?)

STATE<=RESET;

WRITE_BYTE_FLAG<=2;

elsif (WRITE_BYTE_FLAG=2) then –第二次写0XCC完毕

STATE<=CMD_BE;

WRITE_BYTE_FLAG<=3;

elsif (WRITE_BYTE_FLAG=3) then –写0XBE完毕

             STATE<=GET_TMP;

WRITE_BYTE_FLAG<=0;

end if;

WRITE_BYTE_CNT<=0;

when others=>STATE<=RESET;

end case;

when WRITE_LOW=>  进入写0时序,参看前面

LED3<=’1′;

case WRITE_LOW_CNT is

when 0=>

dq<=’0′;

if (cnt=70) then  –等待时序

cnt<=0;

WRITE_LOW_CNT<=1;

else

cnt<=cnt+1;

end if;

when 1=>

dq<=’Z’;

if (cnt=5) then

cnt<=0;

WRITE_LOW_CNT<=2;

else

cnt<=cnt+1;

end if;

when 2=>

STATE<=WRITE_BYTE;

WRITE_LOW_CNT<=0;

when others=>WRITE_LOW_CNT<=0;

end case;

when WRITE_HIGH=>    –进入写1时序,参看前面

case WRITE_HIGH_CNT is

when 0=>

dq<=’0′;

if (cnt=8) then

cnt<=0;

WRITE_HIGH_CNT<=1;

           else  程序编程代考

cnt<=cnt+1;

end if;

when 1=>

dq<=’Z’;

if (cnt=72) then

cnt<=0;

WRITE_HIGH_CNT<=2;

else

cnt<=cnt+1;

end if;

when 2=>

STATE<=WRITE_BYTE;

WRITE_HIGH_CNT<=0;

when others=>WRITE_HIGH_CNT<=0;

end case;

when CMD_44=>

write_temp<=”01000100″;  –写指令44h

STATE<=WRITE_BYTE;

when CMD_BE=>

write_temp<=”10111110″;  –写指令BEh

STATE<=WRITE_BYTE;

when READ_BIT=>

case READ_BIT_CNT is

when 0=>

dq<=’0′;  –4μs的低电平

if (cnt=4) then

READ_BIT_CNT<=1;

cnt<=0;

else

cnt<=cnt+1;

           end if;

when 1=>

dq<=’Z’; –4μs的高电平

if (cnt=4) then

READ_BIT_CNT<=2;

cnt<=0;

else

cnt<=cnt+1;

end if;

when 2=>

dq<=’Z’;

TMP_BIT<=dq; –12μs读出数据 ,就是最后一次赋值的结果。

if (cnt=4) then

READ_BIT_CNT<=3;

cnt<=0;

else

cnt<=cnt+1;

end if;

when 3=>

dq<=’Z’;    –控制器拉高总线

if (cnt=50) then –读出数据后,等待50us

cnt<=0;

READ_BIT_CNT<=0;

STATE<=GET_TMP;

else

cnt<=cnt+1;

end if;

when others=>READ_BIT_CNT<=0;

end case;

 

     when GET_TMP=>  –读数据 程序编程代考

case GET_TMP_CNT is

when 0 =>

STATE<=READ_BIT;

GET_TMP_CNT<=GET_TMP_CNT+1;

when 1 to 12=>

STATE<=READ_BIT;

TMP(GET_TMP_CNT-1)<=TMP_BIT;–将读出的每一位数据按顺序存进 TMP(0 to 11)里面

GET_TMP_CNT<=GET_TMP_CNT+1; –存的是读出的0到11位,第十二位没有存

when 13=>

GET_TMP_CNT<=0;

STATE<=WAIT4MS;

end case;

when WAIT4MS=>  –等待4ms

if (cnt>=4000) then

–STATE<=WAIT4MS;

STATE<=RESET;

cnt<=0;

else

cnt<=cnt+1;

STATE<=WAIT4MS;

end if;

when others=>STATE<=RESET; 程序编程代考

LED<=’0′;

LED2<=’0′;

LED3<=’0′;

end case;

 

end if;

end if;

end process;

 

end;