| Author |
Message
|
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#1
12 Mar 2010 16:07 Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam, jestem nowy na tym forum. Nie posiadam zbyt dużego doświadczenia w zakresie Vhdl robiłem może z parę prostych układów. Niestety w tym sem. zmuszony jestem wykonać projekt obsługi termometru 1wire ds18b20 na układzie Spartan 3e. Zauważyłem że układ ten czasami przewija się na forum jednak głównie w starszych wątkach. Jeśli znaleźliby się jacyś chętni ludzie do pomocy i wprowadzenia mnie od czego zacząć i jak z tym iść dalej, będę szczęśliwy. Zapraszam do dyskusji :)
|
|
| Back to top |
|
 |
Google

|
#
12 Mar 2010 16:07 |
|
|
|
|
|
| Back to top |
|
 |
JarekC Poziom 16

Joined: 09 Jan 2003 Posts: 315 Location: "-"
|
#2
12 Mar 2010 21:16 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam,
Najpierw należy definiować założenia projektu czyli:
- jak często będzie wykonywany odczyt temp.
- w jaki sposób będzie wyświetlana odczytana temperatura
- podać na jakim zestawie startowym będzie uruchamiany
itd.
Oczywiście należy zacząć od przeczytania karty katalogowej DS18B20.
Następnie należy pokazać co się zrobiło a forumowicze pomogą poprawić błędy.
Jeżeli oczekujesz gotowca to polecam dział "Ogłoszenia i biznes elektronika"
Pozdrawiam
JarekC
|
|
| Back to top |
|
 |
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#3
12 Mar 2010 23:42 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Cześć,
odnośnie założeń projektowych to chciałbym:
- dokonywać pomiarów tak często jak pozwoli na to ds18b20
- wyświetlanie temp odbywać się będzie na ekranie lcd do którego mam już odpowiedni sterownik
- całość odpalana będzie na zestawie „S3EStarter Kit” firmy Digilent
Orientuje się już mniej więcej na jakiej zasadzie działa komunikacja 1wire, pierwszą rzeczą którą chce zrealizować jest wykrywanie urządzenia (Presence Pulse). Mam nadzieję że uda mi się napisać kod w weekend wtedy mógłbym prosić o ew. pomoc jeśli nie będzie działać :) Niestety do płytki też mam ograniczony dostęp co może znacznie utrudniać realizacje tego projektu.
|
|
| Back to top |
|
 |
Google

|
#
12 Mar 2010 23:42 |
|
|
|
|
|
| Back to top |
|
 |
JarekC Poziom 16

Joined: 09 Jan 2003 Posts: 315 Location: "-"
|
#4
12 Mar 2010 23:50 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam,
Zgaduję, że moduł obsługi LCD to moduł nazwie LCD1x64 a DS18B20 ma być podłączony do złącza J4 zestawu startowego.
Czy mam rację?
Pozdrawiam
JarekC
|
|
| Back to top |
|
 |
Google

|
#
12 Mar 2010 23:50 |
|
|
|
|
|
| Back to top |
|
 |
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#5
13 Mar 2010 00:06 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Tak wszystko się zgadza dodatkowo choć za to już głowy nie dam układ jest zasilany zewnętrznie pod pinem E8, czyżbyś też miał okazję studiować na pwr ?
Na razie czytam jakie są zależności czasowe dla resetu i jutro chyba spróbuję to napisać. Na razie wyobrażam to sobie mniej więcej tak. Spartan ma zegar 50 mhz czyli sygnał clk co mikrosekundę, według specyfikacji master ma ustawić stan niski na 480 mikrosekund po czym po 15-60 mikrosekundach (czy da się jakoś łatwo wstawić znak mi ?) slave ustawi na tej lini 0 przez 60-240 mikrosekund czyli gdzieś tutaj muszę to sczytać aby mieć pewność że urządzenie się komunikuje
Wstępnie napisałem coś takiego
----------------------------------------------------------------------------------
-- Company: None
-- Engineer:xxxxxxxxxx
--
-- Create Date: 14:25:44 03/13/2010
-- Design Name:
-- Module Name: ds18b20 - Behavioral
-- Project Name:
-- Target Devices: Spartan 3E
-- Tool versions: Xilinx ISE 11.0
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity ds18b20 is
Port ( clk_50Mhz : in STD_LOGIC;
presence_test : out STD_LOGIC;
temperature : out STD_LOGIC_VECTOR (15 downto 0);
one_wire : inout STD_LOGIC);
end ds18b20;
architecture Behavioral of ds18b20 is
type state_type is (init, w500us, w100us, presence);
signal state: state_type;
signal reset: std_logic;
signal clk_1us: integer range 0 to 1000;
signal clk50Mhz_1us: integer range 0 to 50;
begin
process(clk_1us)
begin
case state is
when init =>
reset<='1'; -- zresetuj liczniki
one_wire<='0'; -- wymus 0 na 1wire
state<=w500us; -- nast stan -> reset
when w500us =>
reset<='0'; -- zacznij zliczac impulsy
if(clk_1us=500) then -- ustaw na 500us stan niski
one_wire<='Z'; -- podciagnij napiecie
reset<='1';
state<=w100us;
end if;
when w100us => -- odczekaj 100us
reset<='0';
if(clk_1us=100) then
reset<='1';
state<=presence;
end if;
when presence => -- sprawdz obecnosc presence pulse
if(one_wire<='0') then
presence_test<='1';
state<=init;
elsif(one_wire='1') then
presence_test<='0';
state<=init;
end if;
when others =>
state<=init;
end case;
end process;
process(clk_50Mhz, reset)
begin
if (reset='1')then
clk50Mhz_1us<=0;
clk_1us<=0;
elsif rising_edge(clk_50Mhz) then
clk50Mhz_1us<=clk50Mhz_1us+1;
if (clk50Mhz_1us = 50)then
clk_1us<=clk_1us+1;
clk50Mhz_1us<=0;
end if;
end if;
end process;
end Behavioral;
Chciałem też się zapytać czy jest to prawidłowy sposób na wyzwalanie zmiany stanów czyli czy proces od (clk_1us) będzie wyzwalany co zmianę jego wartości ? Niestety przetestować będę to mógł dopiero w środę.
Ps. Nie wiem czemu wszystkie wcięcia w kodzie umarły ;/
|
|
| Back to top |
|
 |
flapo213 Poziom 18

Joined: 21 Jan 2003 Posts: 549 Location: Rzeszów
|
#6
25 Mar 2010 14:06 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witaj,
widzę że robisz wszystko sekwencyjnie to bardzo dobrze. Mała uwaga na początek zadeklarowałeś one_wire pin jako inout, takei rozwiązanie nie jest do końca słuszne może w symulacji jakoś to obleci ale w rzeczywistym układzie to chyba nie za bardzo. Już tłumaczę o co chodzi aby w tym układzie zrobić wejście typu inout należy to mniej więcej zrobić jak poniżej
| Code: |
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity iodef is
Port ( I : in STD_LOGIC;
T : in STD_LOGIC;
IO : inout STD_LOGIC;
O : out STD_LOGIC);
end iodef;
architecture Behavioral of iodef is
begin
O <= IO;
IO <= I when T = '1' else 'Z';
end Behavioral; |
A później w top pliku vhdl dorzucasz i deklarujesz port jak poniżej:
| Code: |
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity test is
port(
io_port: inout std_logic; -- Port we/wy
s_1: in std_logic; -- Przycisk numer 1
s_2: in std_logic; -- Przycisk numer 2
led_1: out std_logic; -- Dioda Led numer 1
clk: in std_logic -- Sygna? taktuj?cy
);
end test;
architecture Behavioral of test is
component IODEF -- Komponent IOBUF
port (
I: in std_logic;
T: in std_logic;
O: out std_logic;
IO: inout std_logic
);
end component;
signal in_sig, out_sig, t_enable: std_logic;
begin
U1: IODEF port map ( I=> out_sig, T=> t_enable, O=> in_sig , IO=> io_port);
TT_LED: process(clk)
begin
... etc. |
I tak to właśnie powinno zadziałać. Szczerze się przyznam że nie testowałem tego w rzeczywistym układzie w TB śmiga to.
Gdybyś chciał się dowiedzieć więcej to w datasheet do tego układu znajdziesz dział IOBUF. Przeczytaj a zrozumiesz dlaczego tak.
Pozdrawiam i życzę sukcesów
|
|
| Back to top |
|
 |
bartekzajk6 Poziom 2

Joined: 05 Jan 2006 Posts: 4 Location: pisz
|
#7
11 Apr 2010 19:11 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam! Doczepiam się do tematu gdyż nie chce zakładać nowego wątku. Czy sposób w jaki Pan Kinder112, zainicjalizowal termometr ds18b20 (przy pomocy instrukcji case) sprawdzi się przy załączaniu wyświetlacza tft-lcd z kontrolerem ILI9320. Dodam iż sekwencja załączania zasilania(wyswietlacza) jaki i załączania samego wyświetlacza polega na ustawieniu kolejno kilku rejestrów po czym odczekaniu pewnego czasu i ponownym ustawieniu pozostałych kilku rejestrow. Sekwencje ustawienia rejestru, oraz przykładowa sekwencja załączania wyświetlacza dołączam jako obrazki. Zaznaczam iż jestem początkujący i nie za bardzo wiem jak wykonuje się takie operacje w praktyce. Pozdrawiam! Bartek
|
|
| Back to top |
|
 |
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#8
14 Apr 2010 18:35 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam dokonałem kolejnych postępów w pisaniu programu. Aktualnie wykrywam już presence pulse termometru i teoretycznie dokonuje już pomiarów temperatury. Niestety zczytują mi się same '0' co nie jest zgodne z rzeczywistością. Podejrzewam że pomyliłem się gdzieś w czasach. Wszystkie czasy przemnożone są przez 50 gdyż ostatecnie użycam clk = 50 Mhz.
| Code: |
--------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 08:25:57 04/18/08
-- Design Name:
-- Module Name: temperature - Behavioral
-- Project Name:
-- Target Device:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;
entity temperature is
port
(
clk1m: in std_logic;
temper: out std_logic_vector(15 downto 0);
wire_in: in std_logic;
pulse : out std_logic;
state_out : out std_logic_vector(2 downto 0);
wire_out: out std_logic
);
end temperature;
architecture Behavioral of temperature is
type state_type is (s0,s1,s2,s3,s4,s5,s6,s7,s8,w0,w3,w1,w2,read0,read1,read2,read3);
signal state: state_type;
signal temp: std_logic_vector( 15 downto 0);
signal reset: std_logic; --zmienna na czas
signal i: integer range 0 to 50000000;
begin
temper<= temp;
process(clk1m)
variable j : integer range 0 to 15;
variable flag : integer range 0 to 60;
begin
if rising_edge(clk1m) then
case state is
when s0 => --inicjalizacja
wire_out<='0'; --0 na wyjscie
reset<='1';
state<=s1;
state_out(1)<= '1';
when s1 =>
--state_out<="001";
reset<='0';
if(i=50*500) then --odczekaj 500us
wire_out<='1'; --Z na wyjscie
reset<='1';
state<=s2;
end if;
when s2 =>
--state_out<="010";
reset<='0';
if (i=50*100) then --odczekaj 100us
reset<='1';
state<=s3;
end if;
when s3 =>
--state_out<="011";
if(wire_in='0') then --sprawdz presenc pulse od termometru
pulse<='1';
state<=s4;
elsif(wire_in='1') then --·jesli brak powroc do poczatku
state<=s0;
pulse<='0';
end if;
when s4 =>
--state_out<="100";
reset<='0';
if(i=50*400) then --odczekaj 400 us
reset<='1';
state<=s5;
end if;
when s5 => --wysylanie komendy CCxh skip rom
--state_out<="101";
if (flag = 0 ) then flag:=1;state <=w0;
elsif (flag = 1 ) then flag:=2;state <=w0;
elsif (flag = 2 ) then flag:=3;state <=w2;
elsif (flag = 3 ) then flag:=4;state <=w2;
elsif (flag = 4 ) then flag:=5;state <=w0;
elsif (flag = 5 ) then flag:=6;state <=w0;
elsif (flag = 6 ) then flag:=7;state <=w2;
elsif (flag = 7 ) then flag:=8;state <=w2;
--wysylanie komendy 44xh convert
elsif (flag = 8 ) then flag:=9 ;state <=w0;
elsif (flag = 9 ) then flag:=10;state <=w0;
elsif (flag = 10 ) then flag:=11;state <=w2;
elsif (flag = 11 ) then flag:=12;state <=w0;
elsif (flag = 12 ) then flag:=13;state <=w0;
elsif (flag = 13 ) then flag:=14;state <=w0;
elsif (flag = 14 ) then flag:=15;state <=w2;
elsif (flag = 15 ) then flag:=16;state <=w0;
--s6
elsif (flag = 16 ) then flag:=20;state <=s6;
--wysylanie komendy CCxh skip rom
elsif (flag = 20 ) then flag:=21;state <=w0;
elsif (flag = 21 ) then flag:=22;state <=w0;
elsif (flag = 22 ) then flag:=23;state <=w2;
elsif (flag = 23 ) then flag:=24;state <=w2;
elsif (flag = 24 ) then flag:=25;state <=w0;
elsif (flag = 25 ) then flag:=26;state <=w0;
elsif (flag = 26 ) then flag:=27;state <=w2;
elsif (flag = 27 ) then flag:=28;state <=w2;
--wysylanie komendy BExh read
elsif (flag = 28 ) then flag:=29;state <=w0;
elsif (flag = 29 ) then flag:=30;state <=w2;
elsif (flag = 30 ) then flag:=31;state <=w2;
elsif (flag = 31 ) then flag:=32;state <=w2;
elsif (flag = 32 ) then flag:=33;state <=w2;
elsif (flag = 33 ) then flag:=34;state <=w2;
elsif (flag = 34 ) then flag:=35;state <=w0;
elsif (flag = 35 ) then flag:=36;state <=w2;
--s7
elsif (flag = 36 ) then flag:=40;state <=s7;
end if;
when s6 =>
--state_out<="110";
wire_out<='1'; --wire_out 'Z'
reset<='0';
state_out(1)<= '0';
if (i = 50*750000 ) then --odczekaj 750 ms ///or wire_in='1'
state <= s0;
reset<='1'; --lub na 1 na wejsciu
end if;
when s7 => --odczyt temperatury
--state_out<="111";
if (flag = 40 ) then flag:=41; state<=read0;j:=0;
elsif (flag = 41 ) then flag:=42; state<=read0;j:=1;
elsif (flag = 42 ) then flag:=43; state<=read0;j:=2;
elsif (flag = 43 ) then flag:=44; state<=read0;j:=3;
elsif (flag = 44 ) then flag:=45; state<=read0;j:=4;
elsif (flag = 45 ) then flag:=46; state<=read0;j:=5;
elsif (flag = 46 ) then flag:=47; state<=read0;j:=6;
elsif (flag = 47 ) then flag:=48; state<=read0;j:=7;
elsif (flag = 48 ) then flag:=49; state<=read0;j:=8;
elsif (flag = 49 ) then flag:=50; state<=read0;j:=9;
elsif (flag = 50 ) then flag:=51; state<=read0;j:=10;
elsif (flag = 51 ) then flag:=52; state<=read0;j:=11;
elsif (flag = 52 ) then flag:=53; state<=read0;j:=12;
elsif (flag = 53 ) then flag:=54; state<=read0;j:=13;
elsif (flag = 54 ) then flag:=55; state<=read0;j:=14;
elsif (flag = 55 ) then flag:=60; state<=read0;j:=15;
elsif (flag = 60 ) then flag:=0;state<=s0;
end if;
when s8 =>
--state_out<="010";
state<=s8;
----------------------------------zapis------------------------------
when w0 =>
wire_out<='0'; --wyslij 0
reset<='0';
if (i = 50*80) then --odczekaj 80us
wire_out<='1'; --wyzlij Z
reset<='1';
state<=w1;
end if;
when w1 =>
state<=s5; --powrot po wyslaniu 1
when w2=>
wire_out<='0';
state<=w3; --przejdz do stanu "w1"
when w3 =>
wire_out<='1'; --wyslij 1
reset<='0';
if (i = 50*80) then --odczekaj 80 us
reset<='1';
state<=s5;
end if;
----------------------------------odczyt------------------------------------------
when read0=>
wire_out<='0';
state <= read1; --przejdz do odczytu
when read1=>
--ustaw wejscie na Z
reset<='0';
if (i = 50*10) then --odczekaj 10 us
reset<='1';
state <= read2;
end if;
when read2=>
temp(j)<= wire_in; --zczytaj bit temperatury
state <= read3;
when read3=>
reset<='0';
if (i = 50*55) then --odczekaj 55 us
reset<='1';
state <= s7;
end if;
------------------------------------------------------------------------------
when others =>
state <=s0;
end case;
end if;
end process;
process(clk1m,reset)
begin
if (reset='1')then
i<=0;
elsif rising_edge(clk1m) then
i<=i+1;
end if;
end process;
end Behavioral;
|
Będę wdzięczny za wszelkie uwagi gdzie może być błąd gdyż dostęp do płytki mam bardzo rzadko a z samym IDE ciężko sprawdzać czy to naprawdę działa. Załączam też wykres z simulinka, jeśli ktoś miałby przebieg prawidłowego cyklu odczytu z tego urządzenie byłbym bardzo wdzięczny. [img]http://yfrog.com/bavdhlsimulationj[/img]
|
|
| Back to top |
|
 |
JarekC Poziom 16

Joined: 09 Jan 2003 Posts: 315 Location: "-"
|
|
| Back to top |
|
 |
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#10
14 Apr 2010 22:46 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Tak masz rację, czy to właśnie rozbicie przyczyniło się w jakiś sposób do niedziałania kodu ? W sumie nie mam pewności czy ten był tak naprawdę sprawny.
|
|
| Back to top |
|
 |
Google

|
#
14 Apr 2010 22:46 |
|
|
|
|
|
| Back to top |
|
 |
JarekC Poziom 16

Joined: 09 Jan 2003 Posts: 315 Location: "-"
|
#11
14 Apr 2010 23:06 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Witam,
Finalnie przy połączaniu DS18B20 i tak zwierasz te linie ze sobą, aby otrzymać inout.
Głównym problemem jest to, że zmieniłeś przypisania dla stanu Hi-Z.
(zmieniłeś Z na 1).
| Code: |
| wire_out<='1'; --Z na wyjscie |
takie przypisanie dałyby stan Hi-Z tylko w przypadku gdyby pin był skonfigurowany jako Open-Drain.
Pozdrawiam
JarekC
|
|
| Back to top |
|
 |
Kinder112 Poziom 3

Joined: 03 Mar 2010 Posts: 6
|
#12
14 Apr 2010 23:38 Re: Vhdl + 1Wire czyli Spartan 3e i ds18b20 |
|
|
|
Otóż używam elementu iobuf podłączonego do wire_out ->T, wire_in -> O Gnd -> I i oczywiście jego wyjście podpięte do onwire. W taki sposób polecił zrealizować to prowadzący. Tłumacząc że jeśli na I damy Gnd a na T '1' to uzyskujemy właśnie 'Z' na złączu onwire. I na te złącze nie podaje się tak naprawdę '1' tylko '0' lub 'Z' jako pullup.
Edit 1. Dołączam obrazek z tym jak używam elementu IOBUF aby zilustrować to i uzyskać odpowiedź czy dobrze myślę.
Update.
Po dalszej analizie kodu okazało się że time sloty na read i write nie były zgodne ze specyfikacją. Po poprawce termometr działa już sprawnie więc temat uważam za do zamknięcia
|
|
| Back to top |
|
 |