原创 VHDL实验三:设计UART串行传输模块

2010-12-20 16:50 4801 7 7 分类: FPGA/CPLD

一、  实验原理:


1、  概述


UART的全称是通用异步收发器(Universal Asynchronous Receiver/Transmitter),是实现设备之间低速数据通信的标准协议。“异步”指不需要额外的时钟线进行数据的同步传输,是一种串行总线接口,只需占用两根线就可以完成数据的收发(一根接收数据,一根发送数据),常用的标准通信波特率有9600bps、115200bps等。


2、 通信协议与帧格式


UART一帧由起始位、数据位、校验位和停止位组成。数据逐位传输,示意图如图 1.1所示。



a)  起始位


UART空闲时(没有数据传输),总线为高电平(逻辑1),当需要数据传输时,首先发送一个“起始位”,起始位为一个低电平“逻辑0”。


为什么需要起始位?


因为UART没有控制线,要让接收方知道什么时候开始接收数据,需要一些手段,在UART,数据的传输只有一根线,所以在发送数据之前,先发一位逻辑“0”作为数据发送的起始标志,接收方在空闲时,当检测到有一个低电平,则开始接逐位接收数据。


b)  数据位


如图 1.1的“2.”所示,紧挨着“起始位”的是数据位,它可以是5、6、7或8位,收/发双方在数据开始传输前,需要对双方数据位位数作一致的定义,否则会导致数据的传输错误;数据位的发送采用低位(LSB)先发送。


为什么数据位可变?


因为UART是一种低速总线,每多发一位都占用不少的时间(由传输波特波决定),所以可以传输数据的特点,采用不同位数据的波特率以节约时间。如在Modbus协议中,Modbus-ASCII是以ASCII码传输的,因为ASCII是不会大于0x7F,所以使用7位的数据位,而Modbus-RTU则采用8位的数据位。


c)  校验位


UART的校验位紧挨着数据位,采用奇/偶位校验方式,可有可无,是为了为了验证数据传输的安全性而设置的,在收/发双方进行数据传输前要预设好是否需要校验位,如果需要则是奇校验还是偶校验。如图 1.1的“3.”所示。


为什么需要校验?


UART长距离数据传输时,使用RS-232、RS-485传输,一般使用较长的导线连接收/发设备,其工作现场因存在不同程序的干扰,可能会导致数据的传输错误,加个校验位可作初步的校验,如果校验出错,说明数据是不可靠的,直接丢弃;如果校验通过,则数据有一定的可靠性,可进入下一级的校验,通常加入通信协议,如Modbus-RTU引入了CRC校验。


d)  停止位


UART的帧以停止位作为停止标志,是在数据位(没有校验位)和校验位(有校验位)之后发送1~2位的逻辑“1”。停止为可以为1位、1.5位和2位。当发送完停止位之后,UART总线进入空闲。


e)  空闲


空闲指UART总线上没有数据进行传输,表现为发送方输出逻辑“1”,在空闲时,接收方时刻监视UART总线上电平变化,当发现起始化,则进入数据接收状态,直至接收完一帧数据,如果最后没有检测到停止位,则标志帧错误。


f)  波特率(Baudrate)


由于UART没有同步时钟线,收/发双方如果需要进行正确的数据传输,则要在收/发双方定义一致的位时钟,位时钟可以理解为UART总线一个位所占用的时间,即“波特率”。在定义上,收/发双方的波特率可以是随意的,只需要保持一致,如双方都是1000bps,但是,这不能兼容现有常用的设备,兼容性差。所以在工程应用中,常用一些特定的波特率真,如4800bps、9600bps或115200bps等。


如果波特率是9600bps,则传输速度最大是多少?


波特率的单位是bps(位每秒),是指发送一位所占用的时间。如果UART定义8位数数位、无校验、1位停止位。则一帧数据的位数N如公式(3)所示:


N = 1位起始位+8位数据位+0位校验位+1位停止位=10bits 公式(3)


所以最大数据传输率为:9600bps / N = 960BPS(字节每秒)。


即当波特率为9600rps,UART帧格式为8位数据位、无校验、1位停止位时,最大的数据传输率为0.96KBPS。


g)  常用帧格式


如图 1.3所示为8位数据位、无校验位、1位停止位的帧格式示意图,一帧共有10位。发送的数据为0xA5。



 


3、  硬件接口


a)RS-232连接器


RS-232的连接器常用的是DB-9,其连接器示意图如图 1.6所示,为九针连接器。对于常用的简单应用,使用到的有三根线:RxD、TxD和GND。串口接口头分公母接头,下面所示为母的接头。



 


实物图如图 1.7所示。



b)              电平转换电路(与计算机连接)


 



二、实验过程


有了上面的理论基础我们就可以开始设计一个UART的串行传输模块了。


1、 系统框图的设计:


系统的传输取决于波特率的大小,所以要设计一个专门产生波特率计数,实质上是对系统时钟频率进行分频。由于是单线发送和接收,实现了全双工传输,实质上是相当于串行序列接收与发生,只不过这个序列是有一定的通信格式而已。下面是两个系统的框图设计:



图2.1接收模块系统框图



图2.2发送模块的系统框图


2、 波特率计数器设计:


我们以9600的波特率,50MHZ的时钟晶振举例说明:由上面的理论知识我们可以知道,9600bps,则表示传输一位的时间需要1/9600s。时钟晶振为50MHZ,则一个时钟脉冲周期为:1/50M s。则串行传输一位的时间长度需要50M/9600=5208个时钟脉冲周期,半周期为2604个时钟脉冲周期。这个波特率时钟脉冲就可以由系统时钟脉冲分频所得。


程序设计:


--工程名:时钟分频器


--功能:实现对时钟脉冲的分频,产生9600波特率时钟脉冲


--时间:2010-12-10


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity speed_select is


   port(clk:in std_logic;--时钟信号


        rst:in std_logic;--复位信号,低电平有效


        bps_start:in std_logic;--信号开始传输信号


        clk_bps:out std_logic);--波特率信号


end entity;


 


 


architecture behav of speed_select is


constant bps_para: integer :=5207;


constant bps_para_2: integer :=2603;


signal cnt:integer range 0 to bps_para:=0;


 


begin


  process(clk)  --计数进程


  begin


  if(rst='0') then


   cnt<=0;


   elsif rising_edge(clk) then


    clk_bps<='1';             --后半周期置1


   if (cnt<bps_para_2) then   --前半周期置0


    clk_bps<='0';


    cnt<=cnt+1;                --不断自加计数


     elsif cnt<bps_para then


       cnt<=cnt+1;


       else cnt<=0;           --计数完成对cnt进行清零


    end if;


    if(bps_start='0') then    ---数据开始传输对cnt进行清零


       cnt<=0;


     end if; 


   end if;


   end process;


 end behav;


 


仿真结果如下:



3、 串行数据接收器设计:


串行数据是在波特率时钟脉冲下传输的。根据UART的常用串行传输协议(1位低电平起始位,8位数据位,无检验位,1位停止位),我们可以设计出如下的状态机:



程序设计如下:


 


--工程名:UART串行接收器


--功能:实现对RXD串行数据接收,转换成8位数据并行输出


--时间:2010-12-10


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity uart_rx is 


   port(


        rst:in std_logic;  --复位信号,低电平有效


        rx:in std_logic;--RXD串行数据输入


        clk_bps:in std_logic;--波特率信号


        rx_data:out std_logic_vector(7 downto 0);  --8位并行数据输出


        rx_int:out std_logic;--中断传输信号


        bps_start:out std_logic--信号开始传输信号


        );


end entity; 


 


architecture asm of uart_rx is


signal shifter:std_logic_vector(7 downto 0);


signal bitstate:integer range 0 to 10:=0;


begin


  process(clk_bps,rst,rx)   --接收进程


   begin


   if(rst='0') then    --复位信号


      bitstate<=0;


      shifter<="ZZZZZZZZ";


      elsif(rising_edge(clk_bps)) then 


       if(bitstate=0) then       --状态0 判断有没有数据输入


         if(rx='0') then


             bitstate<=bitstate+1;


             bps_start<='1';


          end if;


           elsif(bitstate=9) then    --状态9 数据接收完成


                 bitstate<=0;


                 bps_start<='0';       


             else                   --其他状态接收1-8为数据,停止位不检查


                 shifter(0)<=rx;


                 shifter(7 downto 1)<=shifter(6 downto 0);


                 bps_start<='0';


                 bitstate<=bitstate+1;


            end if;


           end if; 


    end process;


   


    process(clk_bps,rst)   --输出进程


     begin


     if(rst='0') then


         rx_data<="00000000";


         rx_int<='0';


      elsif(bitstate=9) then   


          rx_data<=shifter;  --数据输出


          rx_int<='1';


          else


         rx_int<='0';


         rx_data<="ZZZZZZZZ";


       end if; 


     end process;    


end asm;  


          


        


仿真结果如下:



 


4、 串行数据发送器设计:


--工程名:UART串行发送器


--功能:实现对8位并行输入数据,转换成TXD串行数据发送


--时间:2010-12-10


library ieee;


use ieee.std_logic_1164.all;


use ieee.std_logic_unsigned.all;


use ieee.std_logic_arith.all;


 


entity uart_tx is 


   port(


        rst:in std_logic;  --复位信号,低电平有效


        rx_data:in std_logic_vector(7 downto 0);  --8位并行数据输入


        rx_int:in std_logic;--中断传输信号


        clk_bps:in std_logic;--波特率信号


        tx:out std_logic;--TXD串行数据输出


        bps_start:out std_logic--信号开始传输信号


        );


end entity; 


 


architecture asm of uart_tx is


signal shifter:std_logic_vector(7 downto 0);


type state is(s0,s1,s2,s3);


begin


  process(clk_bps,rst)


  variable cnt:integer range 0 to 8;


  variable present_state:state;


    begin


    if(rst='0') then


       tx<='1';


       bps_start<='0';


       elsif(rising_edge(clk_bps)) then


             case present_state is


              when s0=>  --判定有没有并行数据输入


                   if(rx_int='1') then


                    shifter<=rx_data;


                    bps_start<='1';


                    tx<='1';


                    present_state:=s1;


                    else


                    tx<='1';


                    present_state:=s0;


                    end if;


              when s1=>  --状态1,低电平起始位输出


                    tx<='0';


                    bps_start<='0';


                    present_state:=s2;


              when s2=>  --状态2,8位数据移位输出


                     if(cnt<8) then


                      tx<=shifter(cnt);


                      bps_start<='0';


                      cnt:=cnt+1;


                      present_state:=s2;


                      else


                      cnt:=0;


                      bps_start<='0';


                      present_state:=s3;


                      end if;


               when s3=>  --状态3,高电平停止位输出


                      tx<='1';


                      bps_start<='0';


                      present_state:=s0;


            end case;


         end if;


    end process;


 end asm;


       


仿真结果如下:



图形化设计:


 



利用Quartus集成的仿真软件,比较难检验生成的总体图形文件,这里就不做仿真了。


每个模块都是经过仿真测试的。估计没有什么问题了。


 


 


 


 


 


 


实验总结:通过本次实验进一步熟悉了对FPGA的开发流程。之前一直用这个UART通信,但是由于单片机将这个模块集成化了,也只是在用,没有深入去了解,通过本次实验对这个串口通信协议有了刨根式的了解。通过本次实验,我也深刻的体会到一个项目的开展过程,首先要对项目的理论知识深入理解,才能很好的开展项目,同时在遇到从来没有遇到过的问题时,要将这个问题化解成自己熟悉的模块,一步一步的实现,不能操之过急。在这个工程中,我们将可以将这个系统化解成三个模块进行开展:波特率发生器(分频器),串行数据接收器(序列接收器),串行数据发送器(序列发生器)。这样的话,不但目标明确,而且将项目分工,加快了项目的进度。这是最后一次实验了,期待着课程设计了,希望这个课程在以后能派上大用场。


 


主要遇到的问题:


1, 对UART通信协议的理论知识理解:虽然一直在用这个模块,但是却对其如何实现没有真正的了解过,通过本次实验恶补这方面的知识了


2, 项目的构架,对这个工程如何构架,如何将分割成自己熟悉的模块。这个开展这个工程所首要解决的,同时也要花中功夫下去,因为这一步直接关系到下一步开展的。


3, 已经开始熟练VHDL编程了,在语法上面,没有什么好纠结的了,经过上两次的实验后,这次实验还是挺顺利的,慢慢在成长着。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条