首页 > 其他分享 >5. 串口接收数据——基于FPGA的串口发送数据实验

5. 串口接收数据——基于FPGA的串口发送数据实验

时间:2023-09-27 16:55:48浏览次数:48  
标签:Reset Tx Clk Uart Rx 串口 发送数据 接收数据 Data

1. 串口接收原理与思路

1.1 基本原理

  • 采样:每位数据采多次,统计高低电平出现的次数,次数多的就是该位的电平值
  • 起始位检测:边沿检测,使用两个计数器来判断Bps_Clk的下降沿/上升沿(前一个时钟上升沿为高电平/低电平,后一个时钟上升沿为低电平/高电平),两个触发器即可设计得到。
  • 新语法:
    reg [2:0]R_Data[7:0],意为声明8个数的数组,每个数的位数为3位。

1.2 设计

附新语法:reg [2:0]R_Data[9:0],二维数组,每个位宽为3位。

  • 使用的变量

    • Clk 时钟
    • Reset_N 复位
    • Baud_Set 波特率
    • Uart_Rx 接收到的数据
    • Data 显示接收到的数据
    • Rx_Done 接收完成
  1. 两个D触发器检测边沿:[1:0]Uart_Rx_R。用来判断Uart_Rx的上升沿(Pedge_Uart_Rx)和下降沿(Nedge_Uart_Rx)。
    reg [1:0]Uart_Rx_R;
    always@(posedge Clk)begin
        Uart_Rx_R[0] <= Uart_Rx;
        Uart_Rx_R[1] <= Uart_Rx_R[0];
    end
    wire Pedge_Uart_Rx;
    assign Pedge_Uart_Rx = (Uart_Rx_R == 2'b01);
    wire Nedge_Uart_Rx;
    assign Nedge_Uart_Rx = (Uart_Rx_R == 2'b10);
  1. 把每次接收的信号位分成16份(一次性接收10位则有160份),把每份中间的计数电平作为时钟Bps_Clk_16x信号。时钟信号设计:
  • 既然每一个电平信号的中间作为计数时刻,那么需要一个计数器Div_Cnt循环计数Bps_Dr - 1(一个位的计数值),每计数到一半产生一个电平信号。
  • 计数器开始计数,需要一个控制信号Rx_En进行控制,当接收信号的第一个位到来时开始计数。
    wire Bps_Clk_16x;
    assign Bps_Clk_16x = (Div_Cnt == Bps_Dr / 2);
    
    reg Rx_En;
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        Rx_En <= 0;
    else if(Nedge_Uart_Rx)
        Rx_En <= 1'b1;
    else if(Rx_Done || (Sta_Bit >= 4))//发送结束和接收的起始电平异常
        Rx_En <= 0;

    reg [8:0]Div_Cnt;
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        Div_Cnt <= 0;
    else if(Rx_En)begin
        if(Div_Cnt == Bps_Dr - 1)
            Div_Cnt <= 0;
        else
            Div_Cnt <= Div_Cnt + 1'b1;
    end
    else
        Div_Cnt <= 0;
  1. 接收过程的设计
  • 首先设计160的计数器Bps_Cnt,以时钟Bps_Clk_16x为计数时钟(接收的10个位综合考虑)。注:计算160个间隔,需要161个点。因此计数值选择0-160。
reg [8:0]Bps_Cnt;
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        Bps_Cnt <= 0;
    else if(Rx_En)
        if(Bps_Clk_16x)
            if(Bps_Cnt == 160)
                Bps_Cnt <= 0;
            else
                Bps_Cnt <= Bps_Cnt + 1'b1;
        else
            Bps_Cnt <= Bps_Cnt;
    else
        Bps_Cnt <= 0;
  • 在特定计数值处接收数据。累加每个接收位的中间七个间隔的电平,如果计数值大于4则为高电平。
    reg [2:0]R_Data[7:0];
    reg [2:0]Sta_Bit;
    reg [2:0]Sto_Bit;
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)begin
        Sta_Bit <= 0;
        R_Data[0] <= 0;
        R_Data[1] <= 0;
        R_Data[2] <= 0;
        R_Data[3] <= 0;
        R_Data[4] <= 0;
        R_Data[5] <= 0;
        R_Data[6] <= 0;
        R_Data[7] <= 0;
        Sto_Bit <= 0;
    end
    else
        case(Bps_Cnt)
        0: begin
        Sta_Bit <= 0;
        R_Data[0] <= 0;
        R_Data[1] <= 0;
        R_Data[2] <= 0;
        R_Data[3] <= 0;
        R_Data[4] <= 0;
        R_Data[5] <= 0;
        R_Data[6] <= 0;
        R_Data[7] <= 0;
        Sto_Bit <= 0;
        end
        5,6,7,8,9,10,11: Sta_Bit <= Sta_Bit + Uart_Rx;
        21,22,23,24,25,26,27: R_Data[0] <= R_Data[0] + Uart_Rx;
        37,38,39,40,41,42,43: R_Data[1] <= R_Data[1] + Uart_Rx;
        53,54,55,56,57,58,59: R_Data[2] <= R_Data[2] + Uart_Rx;
        69,70,71,72,73,74,75: R_Data[3] <= R_Data[3] + Uart_Rx;
        85,86,87,88,89,90,91: R_Data[4] <= R_Data[4] + Uart_Rx;
        101,102,103,104,105,106,107: R_Data[5] <= R_Data[5] + Uart_Rx;
        117,118,119,120,121,122,123: R_Data[6] <= R_Data[6] + Uart_Rx;
        133,134,135,136,137,138,139: R_Data[7] <= R_Data[7] + Uart_Rx;
        149,150,151,152,153,154,155: Sto_Bit <= Sto_Bit + Uart_Rx;
        default:;
        endcase
    
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        Data <= 0;
    else if(Bps_Clk_16x && (Bps_Cnt == 160))begin
//        Data[0] <= (R_Data[0] >= 4)?1:0;
//        Data[1] <= (R_Data[1] >= 4)?1:0;
//        Data[2] <= (R_Data[2] >= 4)?1:0;
//        Data[3] <= (R_Data[3] >= 4)?1:0;
//        Data[4] <= (R_Data[4] >= 4)?1:0;
//        Data[5] <= (R_Data[5] >= 4)?1:0;
//        Data[6] <= (R_Data[6] >= 4)?1:0;
//        Data[7] <= (R_Data[7] >= 4)?1:0;
        Data[0] <= R_Data[0][2];
        Data[1] <= R_Data[1][2];
        Data[2] <= R_Data[2][2];
        Data[3] <= R_Data[3][2];
        Data[4] <= R_Data[4][2];
        Data[5] <= R_Data[5][2];
        Data[6] <= R_Data[6][2];
        Data[7] <= R_Data[7][2];
    end
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        Rx_Done <= 0;
    else if(Bps_Clk_16x && (Bps_Cnt == 160))
        Rx_Done = 1;
    else
        Rx_Done <= 0;
  1. 仿真文件
  • 新语法
    task Uart_Tx_Byte;//变量名
        input [7:0]Tx_Data;//参数
        begin
            Uart_Rx = 1;
            #20;
            Uart_Rx = 0;
            #8680;
            ···
            Uart_Rx = 1;
            #8680;
        end
    endtask
`timescale 1ns / 1ns
module Uart_Byte_Rx_tb;

    reg Clk;
    reg Reset_N;
    reg Uart_Rx;
    wire [7:0]Data;
    wire Rx_Done;

    Uart_Byte_Rx Uart_Byte_Rx(
        .Clk(Clk),
        .Reset_N(Reset_N),
        .Baud_Set(4),
        .Uart_Rx(Uart_Rx),
        .Data(Data),
        .Rx_Done(Rx_Done)
        );
    
    initial Clk = 1;
    always #10 Clk = ~Clk;
    
    initial begin
        Reset_N = 0;
        Uart_Rx = 1;
        #201;
        Reset_N = 1;
        #200;
        Uart_Tx_Byte(8'h5a);
//        @(posedge Rx_Done);
        #90000;
        Uart_Tx_Byte(8'ha5);
//        @(posedge Rx_Done);
        #90000;
        Uart_Tx_Byte(8'h86);
//        @(posedge Rx_Done);
        #90000;
        $stop;
    end

    task Uart_Tx_Byte;
        input [7:0]Tx_Data;
        begin
            Uart_Rx = 1;
            #20;
            Uart_Rx = 0;
            #8680;
            Uart_Rx = Tx_Data[0];
            #8680;
            Uart_Rx = Tx_Data[1];
            #8680;
            Uart_Rx = Tx_Data[2];
            #8680;
            Uart_Rx = Tx_Data[3];
            #8680;
            Uart_Rx = Tx_Data[4];
            #8680;
            Uart_Rx = Tx_Data[5];
            #8680;
            Uart_Rx = Tx_Data[6];
            #8680;
            Uart_Rx = Tx_Data[7];
            #8680;
            Uart_Rx = 1;
            #8680;
        end
    endtask

endmodule

1.3 仿真结果

  • 仿真中出现的问题
    时间无法匹配,tb文件中不要等到Rx_Done信号到来为结束标志。在仿真文件的接收中,一个位的接收时间为540*16=8640ns,而接收信号Uart_Rx位的持续时间则为8680ns。可能会产生在没有接收完成时,后续Rx_Done信号已经到来的情况。

图1-1接收仿真

标签:Reset,Tx,Clk,Uart,Rx,串口,发送数据,接收数据,Data
From: https://www.cnblogs.com/CppsLi/p/17733109.html

相关文章

  • 【开发/调试工具】【串口工具】不同串口软件如何生成带时间戳的日志
    https://blog.csdn.net/qxhgd/article/details/126152913 Xshell在新建会话属性页面,可配置日志的日期格式:  IPOP可根据需要调整标签间隔时间: ......
  • 4. 使用串口发送5个数据到电脑——基于FPGA的串口发送数据实验
    1.使用串口发送5个数据到电脑对于变化的位数(原8)位进行的设计,5个数据即40位。UART规定发送的数据位只能是6、7、8。1.1设计思路对于12位的数据,发送两个字节,高四位变0即可。例如12'h123,按照8'h23和8'h01发送。两种可能出现的情况:1.空闲状态,还没有开始发送(上一次的发送已......
  • 阿波罗H743开发板串口下载0KB出错,使用STLINK解决方法
    导师那边的博后给了一块正点原子的阿波罗H743(非常不好意思地花了人家600+,我还以为是实验室那边本来就有的开发板给我学习呢,结果给我买了全新的还带一个wifi模块,越发觉得任重道远今天尝试连电脑使用,并按照原子那边的教程用flyMCU下载hex文件,反正就是用它一下载,第一遍烧录可以,第二......
  • FPGA 串口发送
    UART(通用异步收发传输器)1.串口通信模块设计的目的是用来发送数据的,因此需要有一个数据输入端口;2.串口通信,支持不同的波特率,所以需要有一个波特率设置端口;3.串口通信的本质就是将8位的并行数据通过一根信号线,在不同的时刻传输并行数据的不同位,通过多个时刻,最终将8位并行数据全部传出......
  • Android开发笔记[4]-串口控制esp32及使用摄像头
    摘要无需root权限,Android使用串口与esp32通信控制小灯开关;开启Android摄像头预览.平台信息AndroidStudio:ElectricEel|2022.1.1Patch2Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-7.5-bin.zipjvmTarget='1.8'minSdk21targetSdk......
  • 3. 设计数据采集模块——基于FPGA的串口发送数据实验
    1.设计数据采集模块基于Send_en的可控设计。使得使用外部信号Data_done来启动数据发送成为可能。放弃使用Tx_done控制的做法。因此把控制Send_en的逻辑放到内部去完成。这样设计更加符合应用。1.1设计要求把Send_en的控制部分放到模块内部去,使用Send_Go作为输入信号可能......
  • 2. 串口发送数据任务——基于FPGA的串口发送数据实验
    1.串口发送数据任务任务要求:使用上一节课设计的串口发送模块,设计一个数据发送器,每10ms以115200的波特率发送一个比特,每次发送的数据比前一个数据大1(计数器)1.1设计思路模块化设计,使用上一节课设计好的发送模块1.2设计开始设计Uart_Byte_Tx(单字节发送)模块选择使用以......
  • ESP8266串口WiFi模块的四大创新型应用领域分析
    ESP8266串口WiFi模块顾名思义,这是一款基于ESP8266方案的串口WiFi模块,可将用户的物理设备连接到WiFi无线网络上,进行互联网或局域网通信,实现联网功能。ESP8266串口WiFi模块是一种适用性强、应用范围广泛的WiFi模块。 ESP8266串口WiFi模块根据当前物联网市场发展趋势,ESP8266串口WiFi......
  • C#串口开发
    C#串口开发主要使用的是System.IO.Ports.SerialPort类,其中详细成员介绍可参考MSDN文档。由于本机没有串口,需要使用VSPD虚拟串口工具创建2个虚拟串口,如下图中的COM1、COM2 使用winform创建如下界面,发送端COM1发送数据,接收端COM2接收数据,发送端和接收端的波特率、数据位、校验......
  • stm32笔记[9]-串口控制云台
    摘要基于stm32的云台控制程序,使用串口接收云台移动指令对云台进行控制.使用软件实现的PWM波发生方式.平台信息ArduinoIDEstm32f103c8t6接口S3:servo_bottom_pin:PA2S4:servo_top_pin:PA3S5:laser_pin:PB4S21:sl_in_pin:PA8S22:sr_out_pin:PB14S23:sl_out_pin:PB1......