FPGA之旅设计99例之第三例-----UART串口通信

一. 简介

这是FPGA之旅的第三个设计实例了,通过串口协议,就可以和电脑上的串口调试助手进行通信啦。串口一般用来输出程序中的一些信息,用来调试,也可以用来进行信息交互。在stm32中是可以通过串口下载程序的,是不是很nice。本例将实现一个基本的串口模块。

感兴趣的话,欢迎关注微信公众号 FPGA之旅

二. 串口电路

串口电路一般使用的是CH340芯片,将串口协议中的RX和TX数据线,转换成电脑上可以识别的COM口,让电脑知道这个外部设备是串口设备。当然不弄硬件哈,只简单了解一下即可,还是重点学习下面的串口协议。
在这里插入图片描述

三. 串口协议

串口协议的全程为串行异步通信协议,UART。

异步,就说明通信双方需要提前约定好数据传输的速率,即波特率,每秒传输bit的数量。串行,就说明数据是按bit一个一个发送出去的(其他的有可能是2bit,3bit,或者更多)。

串口协议只需要两个数据线,一个用来发送,一个用来接收。具体协议规定如下

  1. 空闲位 :数据线都为高电平。
  2. 起始位:数据线拉低1bit,也就是拉低1bit所占用的时间。
  3. 数据位: 一比特一比特的将数据发送出去,先发送低位,后发送高位,数据位宽可以为5,6,7,8。一般为8bit。
  4. 校验位: 可以设置为奇校验,偶校验和无校验位。一般设置为无校验位,即去掉。
  5. 停止位: 数据线拉高0.5、1、1.5bit。一般设置为1bit。

在这里插入图片描述

以上就是串口协议的全部。

四. 实现思路

按照协议的规定,可以非常轻松得到状态机一共用那几个状态

  1. 空闲态
  2. 起始态
  3. 数据态
  4. 停止态

一共四个状态,每个状态所需要做的事情,在协议中已经明确指出来了。

还有一个问题就波特率怎么计算。FPGA的时钟一般为50Mhz,也就是一个时钟周期为20ns。可以先把波特率换成发送一个bit需要多少ns。最后再除以20,得到发送一个bit需要多少个时钟周期。例如波特率为115200,则时钟周期数计算方法如下

K = ((1 / 115200)* 1000 * 1000 * 1000) /20

这样就可以开始安心写代码啦!!代码一共分为两个部分,分别为TX和RX两个。

五. TX发送模块编写

  1. 先来定义端口信号.

    请求信号来了之后,就开始发送idat数据

module  UART_TX(
    input       sys_clk,       /*系统时钟 50M*/
    input       rst_n,         /*系统复位 低电平有效*/
    
    input       uart_tx_req,   /*串口发送请求*/
    output      uart_tx_done,  /*串口发送完成*/

    input[7:0]  idat,          /*发送数据*/
    output      uarttx         /*uart tx数据线*/
);
  1. 再来定义波特率以及各个状态

    时钟周期这里有一点点小改动,避免出现小数,而产生数值错误。

parameter   UARTBaud   = 'd115200;     /*波特率*/
localparam  UARTCLKPer =  (('d1000_000_000 / UARTBaud) /20) -1;   /*每Bit所占的时钟周期*/
localparam  UART_Idle       =   4'b0001;    /*空闲态*/
localparam  UART_Start      =   4'b0010;    /*起始态*/
localparam  UART_Data       =   4'b0100;    /*数据态*/
localparam  UART_Stop       =   4'b1000;    /*停止态*/

六. RX接收模块编写

  1. 定义端口信号。
module UART_RX(
    input          sys_clk,        /*系统时钟 50M*/
    input          rst_n,          /*系统复位*/
    output         uart_rx_done,   /*串口接收完成*/
    output[7:0]    odat,           /*接收数据*/
    input          uartrx         /*uart rx数据线*/
);
  1. 边沿检测。在接收数据的时候,需要判断数据的边沿,用来确定起始信号。通过缓存前两个时钟周期获取到的数据信号。然后通过取反再与的操作,是否发生了跳变,也就是上升沿和下降沿。
/*缓存rx数据*/
reg uartrxd0,uartrxd1,uartrxd2;
/*检测rx 上下边沿*/
wire  uartrxPosedge , uartrxNegedge;

assign uartrxPosedge = (uartrxd1) & ( ~uartrxd2);
assign uartrxNegedge = (~uartrxd1) & ( uartrxd2);

由于两个模块的总代码量一共有300行左右,就不全部粘贴出来了,需要的自行在微信公众号中获取,私聊即可。

七. testbeach编写

代码编写好了,怎么能不去仿真,验一验呢!万一有bug呢?

`timescale 1ns/1ps
/*仿真文件编写*/
module testbeach();
    reg clk;
    reg rst_n;
    wire       uart_rx_done;
    wire[7:0]  uart_rx_data;
    wire       uart;
    reg[7:0]    data;
    reg         uart_tx_req;
    wire        uart_tx_done;
    always #50 clk <= ~clk;
    initial begin
        clk = 1'b0;
        rst_n = 1'b1;
        data = 'd23;
        uart_tx_req = 1'b0;
        #100     /*手动复位一下,不然仿真会有高阻态*/
        rst_n = 1'b0;
        #100
        rst_n = 1'b1;
        #100 
        uart_tx_req = 1'b1;
    end
    /*数据发送完成后,左一位,进行发送*/
    always@(posedge clk)
    begin
        if(uart_rx_done == 1'b1)
            data <= data << 1;
    end
UART_RX UART_RX_HP(
    .sys_clk        (clk),        /*系统时钟 50M*/
    .rst_n          (rst_n),          /*系统复位*/
    .uart_rx_done   (uart_rx_done),   /*串口接收完成*/
    .odat           (uart_rx_data),             /*接收数据*/
    .uartrx         (uart)         /*uart rx数据线*/
);
UART_TX UART_TX_HP(
    .sys_clk        (clk),        /*系统时钟 50M*/
    .rst_n          (rst_n),          /*系统复位*/
    .uart_tx_req    (uart_tx_req),   /*串口发送请求*/
    .uart_tx_done   (uart_tx_done),  /*串口发送完成*/
    .idat           (data),          /*发送数据*/
    .uarttx         (uart)       /*uart tx数据线*/
);
endmodule

通过仿真可以看到,代码正确的运行了,下面就是上板测试了,如果有条件的话。

在这里插入图片描述

不会以为串口就这样完了吧,怎么可能,这才仅仅实现了最基本的功能。更多高级东西还在后头呢!

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
串口通信是一种常见的电子设备之间数据传输的方式,常用于计算机和外部设备之间的数据传递。串口通信涉及到几个重要的概念,包括UART、RS232、RS422和RS485。 UART代表通用异步收发器(Universal Asynchronous Receiver/Transmitter),它是指一种硬件电路,用于实现串行数据传输。UART负责将并行数据转换为串行数据并进行传输,同时将接收到的串行数据转换为并行数据供主设备使用。UART通常使用两条线进行传输,一条用于发送数据,一条用于接收数据。 RS232是一种串口通信标准,常用于计算机和外部设备之间的数据传输。它使用串口连接并使用DB-9或DB-25连接器。RS232定义了传输数据的电气特性和信号电平,以及传输的协议。RS232支持全双工通信,即可以同时传输和接收数据。 RS422是一种更为先进的串口通信标准,用于在长距离和高速传输的环境下进行数据传输。RS422可以同时传输数据和接收数据,并使用四线电缆进行传输。RS422使用差分信号来提高传输的抗干扰能力和传输距离。 RS485是另一种串口通信标准,也适用于长距离和高速传输环境。RS485可以连接多个设备,允许多个设备之间进行数据传输。RS485也使用差分信号进行传输,提供了更高的传输距离和抗干扰能力。 在实际应用中,如果需要通过串口进行数据传输,首先需要确定要使用的串口标准。如果是较短距离和低速传输,可以选择RS232;如果是较长距离和高速传输,RS422或RS485可能更适合。然后,需要配置对应的硬件设备和软件驱动程序来实现串口通信。在数据传输过程中,发送端将数据转换成串行数据,并通过所选的串口标准进行传输,然后接收端将串行数据转换为并行数据进行处理。 总之,串口通信是一种常见的数据传输方式,需要了解UART、RS232、RS422和RS485等概念。选择合适的串口标准来进行数据传输,并配置相应的硬件设备和软件驱动程序来实现串口通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值