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

个人博客式公众号

用心每一天

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