查看: 3691|回复: 0

[评测分享] 【超越者Spartan-6 FPGA开发板】 + 数码管显示接收的串口数据

[复制链接]
  • TA的每日心情
    开心
    2024-10-25 14:50
  • 签到天数: 1071 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2021-5-28 19:18:19 | 显示全部楼层 |阅读模式
    分享到:
            在上篇https://www.cirmall.com/bbs/thread-205909-1-1.html的基础上来学习串口的接收处理,
        实现的功能:将接收的到的串口数据以十进制的方式显示在开发板的数码管上。



        一、硬件部分


        和上篇一样的硬件电路,使用串口COM2接收。


        二、程序部分
       
        2.1、串口接收部分
       
    1. //****************************************Copyright (c)***********************************//
    2. //原子哥在线教学平台:www.yuanzige.com
    3. //技术支持:www.openedv.com
    4. //淘宝店铺:http://openedv.taobao.com
    5. //关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
    6. //版权所有,盗版必究。
    7. //Copyright(C) 正点原子 2018-2028
    8. //All rights reserved                                       
    9. //----------------------------------------------------------------------------------------
    10. // File name:           uart_recv
    11. // Last modified Date:  2019/10/9 9:56:36
    12. // Last Version:        V1.1
    13. // Descriptions:        UART串口接收模块
    14. //----------------------------------------------------------------------------------------
    15. // Created by:          正点原子
    16. // Created date:        2019/10/9 9:56:36
    17. // Version:             V1.0
    18. // Descriptions:        The original version
    19. //
    20. //----------------------------------------------------------------------------------------
    21. //****************************************************************************************//

    22. module uart_recv(
    23.     input                             sys_clk,                  //系统时钟
    24.     input              sys_rst_n,                //系统复位,低电平有效
    25.    
    26.     input              uart_rxd,                 //UART接收端口
    27.     output  reg        uart_done,                //接收一帧数据完成标志
    28.     output  reg        rx_flag,                  //接收过程标志信号
    29.     output  reg [ 3:0] rx_cnt,                  //接收数据计数器
    30.     output  reg [ 7:0] rxdata,
    31.     output  reg [7:0]  uart_data                 //接收的数据
    32.     );
    33.    
    34. //parameter define
    35. parameter   CLK_FREQ = 50000000;                //系统时钟频率
    36. parameter   UART_BPS = 9600;                    //串口波特率
    37. localparam  BPS_CNT  = CLK_FREQ/UART_BPS;       //为得到指定波特率,
    38.                                                 //需要对系统时钟计数BPS_CNT次
    39. //reg define
    40. reg        uart_rxd_d0;
    41. reg        uart_rxd_d1;
    42. reg [15:0] clk_cnt;                              //系统时钟计数器

    43. //wire define
    44. wire       start_flag;

    45. //*****************************************************
    46. //**                    main code
    47. //*****************************************************
    48. //捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
    49. assign  start_flag = uart_rxd_d1 & (~uart_rxd_d0);   

    50. //对UART接收端口的数据延迟两个时钟周期
    51. always @(posedge sys_clk or negedge sys_rst_n)
    52. begin
    53.     if (!sys_rst_n)
    54.                 begin
    55.         uart_rxd_d0 <= 1'b0;
    56.         uart_rxd_d1 <= 1'b0;         
    57.                 end
    58.     else
    59.                 begin
    60.         uart_rxd_d0  <= uart_rxd;                  
    61.         uart_rxd_d1  <= uart_rxd_d0;
    62.     end   
    63. end

    64. //当脉冲信号start_flag到达时,进入接收过程           
    65. always @(posedge sys_clk or negedge sys_rst_n)
    66. begin         
    67.     if (!sys_rst_n)                                 
    68.         rx_flag <= 1'b0;
    69.     else begin
    70.         if(start_flag)                          //检测到起始位
    71.             rx_flag <= 1'b1;                    //进入接收过程,标志位rx_flag拉高
    72.                                                 //计数到停止位中间时,停止接收过程
    73.         else if((rx_cnt == 4'd9) && (clk_cnt == BPS_CNT/2))
    74.             rx_flag <= 1'b0;                    //接收过程结束,标志位rx_flag拉低
    75.         else
    76.             rx_flag <= rx_flag;
    77.     end
    78. end

    79. //进入接收过程后,启动系统时钟计数器
    80. always @(posedge sys_clk or negedge sys_rst_n)
    81. begin         
    82.     if (!sys_rst_n)                             
    83.         clk_cnt <= 16'd0;                                 
    84.     else if ( rx_flag )
    85.                 begin                   //处于接收过程
    86.         if (clk_cnt < BPS_CNT - 1)
    87.             clk_cnt <= clk_cnt + 1'b1;
    88.         else
    89.             clk_cnt <= 16'd0;                       //对系统时钟计数达一个波特率周期后清零
    90.     end
    91.     else                                                             
    92.         clk_cnt <= 16'd0;                                                //接收过程结束,计数器清零
    93. end

    94. //进入接收过程后,启动接收数据计数器
    95. always @(posedge sys_clk or negedge sys_rst_n)
    96. begin         
    97.     if (!sys_rst_n)                             
    98.         rx_cnt  <= 4'd0;
    99.     else if ( rx_flag )
    100.                 begin                   //处于接收过程
    101.         if (clk_cnt == BPS_CNT - 1)                                //对系统时钟计数达一个波特率周期
    102.             rx_cnt <= rx_cnt + 1'b1;                        //此时接收数据计数器加1
    103.         else
    104.             rx_cnt <= rx_cnt;      
    105.                 end
    106.          else
    107.         rx_cnt  <= 4'd0;                                                //接收过程结束,计数器清零
    108. end

    109. //根据接收数据计数器来寄存uart接收端口数据
    110. always @(posedge sys_clk or negedge sys_rst_n)
    111. begin
    112.     if ( !sys_rst_n)  
    113.         rxdata <= 8'd0;                                    
    114.     else if(rx_flag)                            //系统处于接收过程
    115.         if (clk_cnt == BPS_CNT/2)
    116.                         begin         //判断系统时钟计数器计数到数据位中间
    117.             case ( rx_cnt )
    118.              4'd1 : rxdata[0] <= uart_rxd_d1;   //寄存数据位最低位
    119.              4'd2 : rxdata[1] <= uart_rxd_d1;
    120.              4'd3 : rxdata[2] <= uart_rxd_d1;
    121.              4'd4 : rxdata[3] <= uart_rxd_d1;
    122.              4'd5 : rxdata[4] <= uart_rxd_d1;
    123.              4'd6 : rxdata[5] <= uart_rxd_d1;
    124.              4'd7 : rxdata[6] <= uart_rxd_d1;
    125.              4'd8 : rxdata[7] <= uart_rxd_d1;   //寄存数据位最高位
    126.              default:;                                    
    127.             endcase
    128.         end
    129.         else
    130.             rxdata <= rxdata;
    131.     else
    132.         rxdata <= 8'd0;
    133. end

    134. //数据接收完毕后给出标志信号并寄存输出接收到的数据
    135. always @(posedge sys_clk or negedge sys_rst_n)
    136. begin        
    137.     if (!sys_rst_n)
    138.                 begin
    139.         uart_data <= 8'd0;                              
    140.         uart_done <= 1'b0;
    141.                 end
    142.     else if(rx_cnt == 4'd9)
    143.                 begin               //接收数据计数器计数到停止位时           
    144.         uart_data <= rxdata;                    //寄存输出接收到的数据
    145.         uart_done <= 1'b1;                      //并将接收完成标志位拉高
    146.                 end
    147.     else
    148.                 begin
    149.         uart_data <= 8'd0;                                   
    150.         uart_done <= 1'b0;
    151.                 end   
    152. end

    153. endmodule       
    复制代码
         2.2、接收到的数据处理部分
       

    1. module uart_hdl(
    2.         input                   sys_clk,                   //系统时钟
    3.         input            sys_rst_n,                 //系统复位,低电平有效

    4.         input            recv_done,                 //接收一帧数据完成标志
    5.         input      [7:0] recv_data,                 //接收的数据

    6.         input            tx_busy,                   //发送忙状态标志      
    7.         output reg       send_en,                   //发送使能信号
    8.         output reg [7:0] send_data,                  //待发送数据
    9.         output reg [7:0] led_data                  //待发送数据
    10.     );
    11.          
    12.          
    13. //reg define
    14. reg recv_done_d0;
    15. reg recv_done_d1;
    16. reg tx_ready;



    17. //wire define
    18. wire recv_done_flag;

    19. //*****************************************************
    20. //**                    main code
    21. //*****************************************************




    22. //捕获recv_done上升沿,得到一个时钟周期的脉冲信号
    23. assign recv_done_flag = (~recv_done_d1) & recv_done_d0;
    24.                                                 
    25. //对发送使能信号recv_done延迟两个时钟周期
    26. always @(posedge sys_clk or negedge sys_rst_n) begin         
    27.     if (!sys_rst_n) begin
    28.         recv_done_d0 <= 1'b0;                                 
    29.         recv_done_d1 <= 1'b0;
    30.     end                                                      
    31.     else begin                                               
    32.         recv_done_d0 <= recv_done;                              
    33.         recv_done_d1 <= recv_done_d0;                           
    34.     end
    35. end

    36. //判断接收完成信号,并在串口发送模块空闲时给出发送使能信号
    37. always @(posedge sys_clk or negedge sys_rst_n) begin         
    38.     if (!sys_rst_n) begin
    39.         tx_ready  <= 1'b0;
    40.         send_en   <= 1'b0;
    41.         send_data <= 8'd0;
    42.     end                                                      
    43.     else begin                                               
    44.         if(recv_done_flag)begin                 //检测串口接收到数据
    45.             tx_ready  <= 1'b1;                  //准备启动发送过程
    46.             send_en   <= 1'b0;
    47.             send_data <= recv_data;             //寄存串口接收的数据
    48.                                 led_data <= recv_data;
    49.         end
    50.         else if(tx_ready && (~tx_busy)) begin   //检测串口发送模块空闲
    51.             tx_ready <= 1'b0;                   //准备过程结束
    52.             send_en  <= 1'b1;                   //拉高发送使能信号
    53.         end
    54.     end
    55. end


    56. endmodule
    复制代码

        2.3、顶层设计


        将接收的串口数据送到动态数码管


    1. module fpga_test (
    2.         input               sys_clk  ,       // 系统时钟
    3.         input               sys_rst_n,       // 系统复位信号(低有效)
    4.         input                          touch_key,             // 触摸按键

    5.         output    [5:0]     seg_sel  ,       // 数码管位选
    6.         output    [7:0]     seg_led ,        // 数码管段选
    7.         output    [3:0]            led  ,                        //4个LED灯
    8.         output                        beep,
    9.        
    10.         //串口COM2
    11.         input           uart_rxd,           //UART接收端口
    12.         output          uart_txd            //UART发送端口
    13. );

    14. //parameter define
    15. parameter  TIME_SHOW = 25'd25000_000;   // 数码管变化的时间间隔0.5s
    16. parameter  CLK_FREQ = 50000000;         //定义系统时钟频率
    17. parameter  UART_BPS = 115200;           //定义串口波特率
    18. parameter  led_en = 1;
    19. //wire define
    20. wire                 flag;                         // 数码管变化的通知信号
    21. wire     flag_10ms;
    22. wire                 key_val;

    23. //wire define
    24. wire    [19:0]  data;                 // 数码管显示的数值
    25. wire    [ 5:0]  point;                // 数码管小数点的位置
    26. wire            en;                   // 数码管显示使能信号
    27. wire            sign;                 // 数码管显示数据的符号位

    28. wire       uart_recv_done;              //UART接收完成
    29. wire [7:0] uart_recv_data;              //UART接收数据
    30. wire       uart_send_en;                //UART发送使能
    31. wire [7:0] uart_send_data;              //UART发送数据
    32. wire       uart_tx_busy;                //UART发送忙状态标志


    33. //*****************************************************
    34. //**                    main code
    35. //*****************************************************

    36. //动态LED数码管驱动
    37. seg_led_dynamic u_seg_led_dynamic(
    38.         .clk                (sys_clk),
    39.         .rst_n        (sys_rst_n),
    40.        
    41.         .data          (data     ),       // 显示的数值
    42.         .point         (point    ),       // 小数点具体显示的位置,高电平有效
    43.    .en            (led_en),//(en       ),       // 数码管使能信号
    44.    .sign          (sign     ),       // 符号位,高电平显示负号(-)
    45.    
    46.    .seg_sel       (seg_sel  ),       // 位选
    47.    .seg_led       (seg_led  )        // 段选
    48. );



    49. //串口接收模块     
    50. uart_recv #(                          
    51.     .CLK_FREQ       (CLK_FREQ),         //设置系统时钟频率
    52.     .UART_BPS       (UART_BPS))         //设置串口接收波特率
    53. u_uart_recv(                 
    54.     .sys_clk        (sys_clk),
    55.     .sys_rst_n      (sys_rst_n),
    56.    
    57.     .uart_rxd       (uart_rxd),
    58.     .uart_done      (uart_recv_done),
    59.     .uart_data      (uart_recv_data)
    60.     );
    61.          
    62. //串口处理   
    63. uart_hdl u_uart_hdl(
    64.     .sys_clk        (sys_clk),            
    65.     .sys_rst_n      (sys_rst_n),           
    66.    
    67.     .recv_done      (uart_recv_done),   
    68.     .recv_data      (uart_recv_data),   

    69.          .led_data       (data)      
    70. );
    71. endmodule
    复制代码

        三、执行结果

        在串口上发送十六进制数,开发板显示对应的十进制数
        001.png

        003.jpg

        003.jpg


    002.jpg
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-27 00:40 , Processed in 0.122746 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.