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
個人博客式公衆號
用心每一天