URAT通信原理簡述 & VHDL程序實現


UART

UART (Universal Asynchronous Receiver/Transmitter)代表通用異步接收器/發送器。 這不是像SPI和I2C這樣的通信協議,而是微控制器中的物理電路或獨立IC。 UART的主要目的是發送和接收串行數據。有關UART的最好的事情之一是它只使用兩根線在設備之間傳輸數據。

 

UART通信簡介

在UART通信中,兩個UART直接相互通信。 發送UART將來自CPU等控制設備的並行數據轉換爲串行形式,並將其串行傳輸至接收UART,然後將接收設備的串行數據轉換爲並行數據。 在兩個UART之間只需要兩根線來傳輸數據。 數據從發送UART的Tx引腳流向接收UART的Rx引腳:

UARTs異步傳輸數據,這意味着沒有時鐘信號可將發送UART的位輸出與接收UART的位採樣同步。 發送UART不是時鐘信號,而是將開始位和停止位添加到正在傳輸的數據包。 這些位定義數據包的開始和結束,以便接收UART知道何時開始讀取位。

 

當接收UART檢測到一個起始位時,它開始以稱爲波特率的特定頻率讀入輸入位。 波特率是數據傳輸速度的度量,以每秒位數(bps)表示。 兩個UART必須以大約相同的波特率運行。 發送UART和接收UART之間的波特率在比特的時序變得太遠之前只能相差約10%。

 

兩個UART必須也必須配置爲發送和接收相同的數據包結構。

UART如何工作

要發送數據的UART從數據總線接收數據。 數據總線用於通過CPU,內存或微控制器等其他設備將數據發送到UART。 數據以並行形式從數據總線傳輸到發送UART。 發送UART從數據總線獲得並行數據後,它會添加一個起始位,一個奇偶校驗位和一個停止位,以創建數據包。 接下來,數據包在Tx引腳處逐位串行輸出。 接收UART在其Rx引腳上逐位讀取數據包。 接收UART然後將數據轉換回並行格式並刪除起始位,奇偶校驗位和停止位。 最後,接收UART將數據包並行傳輸到接收端的數據總線上:

 

UART傳輸的數據被組織成數據包。 每個數據包包含1個起始位,5到9個數據位(取決於UART),可選奇偶校驗位以及1或2個停止位:

起始位

不傳輸數據時,UART數據傳輸線通常保持高電平。 爲了開始數據傳輸,發送UART在一個時鐘週期內將傳輸線從高電平拉到低電平。 當接收UART檢測到高電壓至低電壓轉換時,它開始以波特率的頻率讀取數據幀中的位。

 

數據幀

數據幀包含正在傳輸的實際數據。 如果使用奇偶校驗位,它可以是5位長達8位長。 如果不使用奇偶校驗位,則數據幀可以是9位長。 在大多數情況下,數據首先以最低有效位發送。

 

奇偶性

奇偶性描述數字的均勻性或奇異性。 奇偶校驗位是接收UART在傳輸過程中是否有數據發生變化的一種方式。 電磁輻射,不匹配的波特率或長距離數據傳輸可能會改變位。 在接收UART讀取數據幀後,它會計數值爲1的位數,並檢查總數是偶數還是奇數。 如果奇偶校驗位是0(偶校驗),則數據幀中的1位應總計爲偶數。 如果奇偶校驗位是1(奇數奇偶校驗位),則數據幀中的1位應該總數爲奇數。 當奇偶校驗位與數據匹配時,UART知道傳輸沒有錯誤。 但是如果奇偶校驗位是0,總數是奇數; 或奇偶校驗位爲1,且總數爲偶數時,UART知道數據幀中的位已改變。

 

停止位

爲了發信號通知數據包的結束,發送UART將數據傳輸線從低電壓驅動到高電壓持續至少兩個比特持續時間。

 

UART傳輸步驟

 

1.發送UART從數據總線並行接收數據:

2.發送UART將起始位,奇偶校驗位和停止位添加到數據幀中:

3.整個數據包從發送UART串行發送到接收UART。 接收UART以預配置的波特率對數據線進行採樣:

4.接收UART丟棄數據幀中的起始位,奇偶校驗位和停止位:

5.接收UART將串行數據轉換爲並行數據並將其傳送到接收端的數據總線:

UARTS的優勢和劣勢

沒有通信協議是完美的,但UART在他們所做的事情上相當出色。以下是一些優點和缺點,可幫助決定是否符合項目需求:

優點

只使用兩根電線

沒有時鐘信號是必要的

有一個奇偶校驗位允許進行錯誤檢查

只要雙方都建立起來,數據包的結構就可以改變

有據可查的和廣泛使用的方法

劣勢

數據幀的大小限制爲最多9位

不支持多個從屬或多個主系統

每個UART的波特率必須在彼此的10%以內

URAT VHDL程序

1. 頂層程序

--功能:頂層映射。

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity top is

    Port (clk32mhz,reset,rxd,xmit_cmd_p_in:in std_logic;--總的輸入輸出信號的定義

     rec_ready,txd_out,txd_done_out:out std_logic;

txdbuf_in:in std_logic_vector(7 downto 0);--待發送數據輸入

    rec_buf:out std_logic_vector(7 downto 0))--接收數據緩衝

end top;

 

architecture Behavioral of top is

 

component transfer --發送器組件

    Port (bclkt,resett,xmit_cmd_p:in std_logic;

     txdbuf:in std_logic_vector(7 downto 0);

 txd:out std_logic;

 txd_done:out std_logic);

end component;

 

component reciever --接收器組件

    Port (bclkr,resetr,rxdr:in std_logic;

     r_ready:out std_logic;

 rbuf:out std_logic_vector(7 downto 0));

end component;

 

component baud

    Port (clk,resetb:in std_logic;

     bclk:out std_logic);

end component;

 

signal b:std_logic;

begin

u1:baud port map(clk=>clk32mhz,resetb=>reset,bclk=>b); --頂層映射

u2:reciever port map(bclkr=>b,resetr=>reset,rxdr=>rxd,r_ready=>rec_ready,rbuf=>rec_buf);

u3:transfer port map(bclkt=>b,resett=>reset,xmit_cmd_p=>xmit_cmd_p_in,txdbuf=>txdbuf_in,txd=>txd_out,txd_done=>txd_done_out);

end Behavioral;

2.波特率發生器程序

--功能:將外部輸入的32MHz的信號分成頻率爲153600Hz的信號。

--計算過程:(32*10^6)/(1.536*10^5)=208.333……

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity baud is

    Port (clk,resetb:in std_logic;

     bclk:out std_logic);

end baud;

 

architecture Behavioral of baud is

begin

process(clk,resetb)

variable cnt:integer;

begin

  if resetb='1' then cnt:=0; bclk<='0'; --復位

  elsif rising_edge(clk) then

     if cnt>=208 then cnt:=0; bclk<='1'; --設置分頻係數

 else cnt:=cnt+1; bclk<='0';

 end if;

  end if;

end process;

end Behavioral;

3. UART發送器程序

--功能:UART發送器。

--說明:系統由五個狀態(x_idle,x_start,x_wait,x_shift,x_stop)和一個進程構成。

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity transfer is

    generic(framlent:integer:=8);

    Port (bclkt,resett,xmit_cmd_p:in std_logic; --定義輸入輸出信號

     txdbuf:in std_logic_vector(7 downto 0):="11001010";

 txd:out std_logic;

 txd_done:out std_logic);

end transfer;

 

architecture Behavioral of transfer is

type states is (x_idle,x_start,x_wait,x_shift,x_stop); --定義個子狀態

signal state:states:=x_idle;

signal tcnt:integer:=0;

begin

process(bclkt,resett,xmit_cmd_p,txdbuf) --主控時序、組合進程

variable xcnt16:std_logic_vector(4 downto 0):="00000"; --定義中間變量

variable xbitcnt:integer:=0;

variable txds:std_logic;

begin  

  if resett='1' then state<=x_idle; txd_done<='0'; txds:='1';--復位

  elsif rising_edge(bclkt) then

     case state is

   when x_idle=> --狀態1,等待數據幀發送命令

if xmit_cmd_p='1' then state<=x_start;txd_done<='0';

else state<=x_idle;               

end if;

when x_start=> --狀態2,發送信號至起始位

if xcnt16>="01111" then state<=x_wait; xcnt16:="00000";

else xcnt16:=xcnt16+1; txds:='0'; state<=x_start;

end if;                          

when x_wait=> --狀態3,等待狀態

if xcnt16>="01110" then

       if xbitcnt=framlent then state<=x_stop; xbitcnt:=0;

   else state<=x_shift;

   end if;

   xcnt16:="00000";

     else xcnt16:=xcnt16+1; state<=x_wait;

 end if;                    

       when x_shift=>txds:=txdbuf(xbitcnt); xbitcnt:=xbitcnt+1; state<=x_wait; --狀態4,將待發數據進行並串轉換

when x_stop=> --狀態5,停止位發送狀態

if xcnt16>="01111" then

  if xmit_cmd_p='0' then state<=x_idle; xcnt16:="00000";

   else xcnt16:=xcnt16; state<=x_stop;

   end if; txd_done<='1';

else xcnt16:=xcnt16+1; txds:='1'; state<=x_stop;

    end if;                      

   when others=>state<=x_idle;

     end case;

  end if;

  txd<=txds;

end process;

end Behavioral;

4. UART接收器程序

--功能:UART接受器。

--說明:系統由五個狀態(r_start,r_center,r_wait,r_sample,r_stop)和兩個進程構成

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity reciever is

generic(framlenr:integer:=8);         

    Port (bclkr,resetr,rxdr:in std_logic; --定義輸入輸出信號

     r_ready:out std_logic;

 rbuf:out std_logic_vector(7 downto 0));

end reciever;

 

architecture Behavioral of reciever is

type states is (r_start,r_center,r_wait,r_sample,r_stop);--定義各子狀態

signal state:states:=r_start;

signal rxd_sync:std_logic;

begin

pro1:process(rxdr)

begin

  if rxdr='0' then rxd_sync<='0';

  else rxd_sync<='1';

  end if;

end process;

 

pro2:process(bclkr,resetr,rxd_sync) --主控時序、組合進程

variable count:std_logic_vector(3 downto 0); --定義中間變量

variable rcnt:integer:=0;

variable rbufs:std_logic_vector(7 downto 0);

begin

  if resetr='1' then state<=r_start; count:="0000"; --復位

  elsif rising_edge(bclkr) then

     case state is

   when r_start=> --狀態1,等待起始位

if rxd_sync='0' then state<=r_center; r_ready<='0'; rcnt:=0;

else state<=r_start; r_ready<='0';

end if;                              

when r_center=> --狀態2,求出每位的中點

if rxd_sync='0' then

    if count="0100" then state<=r_wait; count:="0000";

else count:=count+1; state<=r_center;

end if;

else state<=r_start;

end if;                            

when r_wait=> --狀態3,等待狀態

if count>="1110" then

if rcnt=framlenr then state<=r_stop;

    else state<=r_sample;

    end if;

count:="0000";                    

    else count:=count+1; state<=r_wait;

end if;

when r_sample=>rbufs(rcnt):=rxd_sync; rcnt:=rcnt+1;state<=r_wait; --狀態4,數據位採樣檢測

       when r_stop=>r_ready<='1'; rbuf<=rbufs; state<=r_start; --狀態4,輸出幀接收完畢信號

       when others=>state<=r_start;

     end case;

  end if;

end process;

end Behavioral;

NUM464

個人博客式公衆號

用心每一天

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章