程序编程代考
程序编程代考 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;