Port RS232
Komunikaci přes tento port lze charakterizovat jak sériovou, asynchronní, duplexní, s volitelným režimem. Napěťové úrovně neodpovídají TTL úrovním. Podrobnosti najde zájemce např. na stránkách http://rs232.hw.cz/ . Pro další výklad zde však musím uvést, že přenos probíhá konstantní rychlostí v tzv. rámcích.
Jak ukazuje obrázek, klidový stav je dán úrovní log1 na datovém vodiči. Přenos pak začíná Start bitem s úrovní log0. Následuje přenos datových bitů v počtu podle nastavení režimu. Přenášená informace pak může být doplněna Paritním bitem. Ukončení přenosu je zasláním Stop bitu, který může být zdvojený. Pak už následuje nový přenos nebo klidový stav.
Protože je přenos asynchronní, musí být nějakým způsobem synchronizována činnost přijímače. Toho je dosaženo vyhodnocením sestupné hrany Start impulzu a samozřejmě musí být předem dohodnuta přenosová rychlost. Ta se udává v bitech za sekundu a jednotkou je Baud.
Protože tento port dává velkou spoustu variací nastavení, je třeba se rozhodnout, zda bude univerzálně nastavitelný, nebo bude mít pevně zvolenu jednu z možností. Pro výukové účely byla vybrána druhá varianta a přenos bude nastaven 8 bitový, bez paritního bitu, s jedním Stop bitem a přenosovou rychlostí 115 200.
Programové řešení
Protože program je určen pro výuku, opět byl celý rozdělen na několik bloků a ty pak byly propojeny ve formě blokového schématu.
Jak je vidět, je celá komunikace rozdělena do dvou částí. Vysílací Tx a přijímací Rx. Už na první pohled je zřejmé, že vysílač je poměrně jednoduchý. Složitost přijímače je dána tím, že musí být detekován Start bit a jeho sestupná hrana, musí být zajištěna synchronizace s přenosovou rychlostí vysílače a v neposlední řadě musí být také vyhodnoceno ukončení přenosu.
baud
Tento blok tvoří časovou základnu pro zvolenou rychlost komunikace, tj. 115 200 Baud. Tato část programu je v souboru baud.vhd.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity baud is
Port ( clk : in STD_LOGIC;
BaudTick : out STD_LOGIC);
end baud;
architecture Behavioral of baud is
signal tim : STD_LOGIC_VECTOR (8 downto 0) := "000000000" ;
begin
process (clk) begin
if clk"event and clk = "1" then
tim <= tim + 1;
if tim = "110110010" then
BaudTick <= "1";
tim <= (others => "0");
else
BaudTick <= "0";
end if;
end if;
end process;
end Behavioral;
PosCount
Je čtyř bitový čítač, který slouží k řízení paralelně sériového převodu přenášených dat. V downloadu je to soubor PosCount.vhd.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity PosCount is
Port ( tim : in STD_LOGIC;
clk : in STD_LOGIC;
pos : out STD_LOGIC_VECTOR (3 downto 0));
end PosCount;
architecture Behavioral of PosCount is
signal count: STD_LOGIC_VECTOR (3 downto 0):= "0000";
begin
process (clk)
begin
if clk="1" and clk"event then
if tim = "1" then
count <= count + 1;
end if;
end if;
end process;
pos <= count;
end Behavioral;
TxModul
Modul představuje srdce celého řešení. K převodu paralelních dat na sériové se používá princip, který zde byl již několikrát použit. Musím se však zmínit o vstupu TxStart, kterým lze řídit odesílání jednotlivých dat. V tomto případě je vstup připojen na log 1 což znamená, že data (ty jsou zadávána z osmice přepínačů) jsou odesílána opakovaně. Příslušný soubor je Tx.vhd
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity TxModul is
Port ( Tx : out STD_LOGIC;
TxStart: in STD_LOGIC;
clk : in STD_LOGIC;
pos : in STD_LOGIC_VECTOR (3 downto 0);
pos1: in STD_LOGIC_VECTOR (7 downto 0));
end TxModul;
architecture Behavioral of TxModul is
signal int : STD_LOGIC;
begin
process (pos, clk, pos1) begin
if clk"event and clk = "1" then
if TxStart = "1" then
case (pos (3 downto 0)) is
when "0010" => int <= "0"; --start
when "0011" => int <= pos1(0); --b0
when "0100" => int <= pos1(1); --b1
when "0101" => int <= pos1(2); --b2
when "0110" => int <= pos1(3); --b3
when "0111" => int <= pos1(4); --b4
when "1000" => int <= pos1(5); --b5
when "1001" => int <= pos1(6); --b6
when "1010" => int <= pos1(7); --b7
when "1011" => int <= "1"; --stop
when others => int <= "1";
end case;
end if;
end if;
end process;
Tx <= int;
end Behavioral;
Baud16Rx
Tento blok vytváří na straně přijímače časovou základnu s 16 násobnou frekvencí než na straně vysílače. To je podmínkou dobré synchronizace s vysílačem Příslušný soubor Baud16Rx.vhd je k dispozici opět v downloadu.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Baud16Rx is
Port ( clk : in STD_LOGIC;
Baud16Tick : out STD_LOGIC);
end Baud16Rx;
architecture Behavioral of Baud16Rx is
signal tim: STD_LOGIC_VECTOR(4 downto 0) := "00000";
begin
process (clk) begin
if clk"event and clk = "1" then
tim <= tim + 1;
if tim = "11011" then
Baud16Tick <= "1";
tim <= (others => "0");
else
Baud16Tick <= "0";
end if;
end if;
end process;
end Behavioral;
Start
Úkolem tohoto bloku je detekovat sestupnou hranu Start bitu, tedy detekovat začátek přenosu. V downloadu je to soubor start.vhd.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity start is
Port ( clk, RxDS, ResS : in STD_LOGIC;
enable : out STD_LOGIC);
end start;
architecture Behavioral of start is
begin
process (clk)
begin
if clk"event and clk="1" then
if ResS="1" then
enable <= "0";
elsif RxDS ="0" then
enable <= "1";
end if;
end if;
end process;
end Behavioral;
RxCount
Tento blok využívá výstupů předchozích dvou a tvoří jej osmi bitový čítač, jehož spuštění je synchronizováno s vysíláním. Odpovídající soubor je v downloadu jako RxCount.vhd.
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 RxCount is
Port ( clk, baud16tick, en, reset : in STD_LOGIC;
CountRx : out STD_LOGIC_VECTOR (7 downto 0));
end RxCount;
architecture Behavioral of RxCount is
signal count: STD_LOGIC_VECTOR (7 downto 0) := "00000000";
begin
process (clk, reset)
begin
if reset="1" then
count <= (others => "0");
elsif clk="1" and clk"event then
if en="1" then
if baud16tick = "1" then
count <= count + 1;
end if;
end if;
end if;
end process;
CountRx <= count;
end Behavioral;
SerPar
Jak již název napovídá, je tento blok určen k převodu sériové informace na vstupu na paralelní informaci na výstupu. I tento princip již zde byl dříve ukázán a soubor SerPar.vhd je rovněž v downloadu.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SerPar is
Port ( PosCount : in STD_LOGIC_VECTOR (7 downto 0);
clk, RxDSer : in STD_LOGIC;
Data : out STD_LOGIC_VECTOR (7 downto 0));
end SerPar;
architecture Behavioral of SerPar is
signal inter : STD_LOGIC_VECTOR (7 downto 0);
signal inter1: STD_LOGIC;
begin
process(clk)
begin
if ( clk"event and clk ="1") then
case PosCount is
when "00011000" => inter(0) <= RxDSer; --b0
when "00101000" => inter(1) <= RxDSer; --b1
when "00111000" => inter(2) <= RxDSer; --b2
when "01001000" => inter(3) <= RxDSer; --b3
when "01011000" => inter(4) <= RxDSer; --b4
when "01101000" => inter(5) <= RxDSer; --b5
when "01111000" => inter(6) <= RxDSer; --b6
when "10001000" => inter(7) <= RxDSer; --b7
when others => inter1 <= RxDSer ;
end case;
end if;
end process;
Data <= inter;
end Behavioral;
reset
Úkolem tohoto obvodu je detekce konce přenosu. Příslušný soubor je reset.vhd
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity reset is
Port ( count152 : in STD_LOGIC_VECTOR (7 downto 0);
RxDRes, clk : in STD_LOGIC;
res , DataReady : out STD_LOGIC);
end reset;
architecture Behavioral of reset is
signal inter : STD_LOGIC_VECTOR (1 downto 0);
begin
process(clk)
begin
if ( clk"event and clk ="1") then
if RxDRes = "1" then
case count152 is
when "10010111" => inter <= "10";
when "10011000" => inter <= "01";
when others => inter <= "00";
end case;
else
case count152 is
when "10010111" => inter <= "00";
when "10011000" => inter <= "01";
when others => inter <= "00";
end case;
end if;
end if;
end process;
res <= inter(0);
DataReady <= inter(1);
end Behavioral;
RxModul
Poslední částí přijímače portu RS 232 je modul, který přebírá uchovává přijatá data. Příslušný soubor se nazývá RxModul.vhd.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity RxModul is
Port ( clk, en : in STD_LOGIC;
Data : in STD_LOGIC_VECTOR (7 downto 0);
DataOut : out STD_LOGIC_VECTOR (7 downto 0));
end RxModul;
architecture Behavioral of RxModul is
begin
process (clk)
begin
if (clk"event and clk="1") then
if en = "1" then
DataOut <= Data;
end if;
end if;
end process;
end Behavioral;
Závěr
Samozřejmě v downloadu, kromě příslušných souborů, najdete také ucf soubor potřebný při fyzické zkoušce programu. Pokud tedy nahrajete program do obvodu a připojíte kit na COM port počítače, můžete pomocí vhodného komunikačního programu vzájemnou komunikaci vyzkoušet. Výborný program najdete na stránkách www.papouch.com/ jako COM Port Monitor.
jiri.kral@ roznovskastredni.cz
Downloads&Odkazy
- První díl seriálu - Hrátky s hradlovými poli - 1
- Druhý díl seriálu - Hrátky s hradlovými poli - 2
- Třetí díl seriálu - Hrátky s hradlovými poli - 3
- Čtvrtý díl seriálu - Hrátky s hradlovými poli - 4
- Soubory ke stažení - Hratky_5.zip
- Domovské stránky http://rs232.hw.cz/
- Domovské stránky Xilinx http://www.xilinx.com/products/spartan3/boards/SP3kitSS.pdf
- Domovské stránky Digilent http://www.digilentinc.com
- Domovské stránky Papouch www.papouch.com/shop/scripts/soft/cpmonter.exe