串口RS485


一、RS485简介

RS-485是双向、半双工通信协议,信号采用差分传输方式,允许多个驱动器和接收器挂接在总线上,其中每个驱动器都能够脱离总线
在这里插入图片描述

二、实验内容

1.实验目标

在这里插入图片描述

2.实验原理图分析

所需模块 :RS485总控模块
在这里插入图片描述
按键消抖模块:
在这里插入图片描述

呼吸灯模块:
在这里插入图片描述

流水灯模块:
在这里插入图片描述

UART_RX模块:
在这里插入图片描述

UART_TX模块 :
在这里插入图片描述

LED_CTRL模块 :
在这里插入图片描述
整体框图:
在这里插入图片描述

3.关于LED_CTRL模块的两种工作模式:

在这里插入图片描述
在这里插入图片描述

4.代码实现

按键消抖模块:

`timescale 1ns / 1ns
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/05 19:58:40
// Design Name: 
// Module Name: key_filter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_filter#(
    parameter       CNT_MAX = 20'd999_999
)
(
    input   wire        sys_clk     ,
    input   wire        rst_n       ,
    input   wire        key_in      ,

    output  reg         key_flag   
);

reg  [19:0]   cnt_20ms      ;


always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        // reset
        cnt_20ms <= 20'd0;
    end
    else if (key_in == 1'b1) begin
        cnt_20ms <= 20'd0;
    end
    else if (cnt_20ms == CNT_MAX) begin
        cnt_20ms <= cnt_20ms;
    end
    else begin
        cnt_20ms <= cnt_20ms + 20'd1;
    end
end



always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        // reset
        key_flag <= 1'b0;
    end
    else if (cnt_20ms == (CNT_MAX - 20'd1)) begin
        key_flag <= 1'b1;
    end
    else begin
        key_flag <=  1'b0;
    end
end
endmodule

流水灯模块:

//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/05 20:36:16
// Design Name: 
// Module Name: water_led
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module water_led#(
parameter   M  =  25'd24999999
)
(clk,rst_n,LED_L);

reg [24:0]  CNT1;
reg [2:0]   CNT2;

input  wire clk;
input  wire rst_n;
output reg  [3:0]   LED_L;

always @(posedge clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        CNT1 <= 25'd0;
    end
    else if (CNT1 == 25'd24999999) begin
        CNT1 <= 25'd0;
    end
    else begin
        CNT1 <= CNT1 + 25'd1;
    end
end

always @(posedge clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        CNT2 <= 3'd0;
    end
    else if ((CNT2 == 3'd4) && (CNT1 == (M-25'd1))) begin
        CNT2 <= 3'd0;
    end
    else if ((CNT1 == (M-1))) begin
        CNT2 <= CNT2 + 3'd1;
    end
    else begin
        CNT2 <= CNT2;
    end
end

always @(posedge clk)
    if (CNT2 == 3'd0) begin
        LED_L <= 4'd0;
    end
    else if (CNT2 == 3'd1) begin
        LED_L <= 4'd1;
    end
    else if (CNT2 == 3'd2) begin
        LED_L <= 4'd2;
    end
    else if (CNT2 == 3'd3) begin
        LED_L <= 4'd4;
    end
    else if (CNT2 == 3'd4) begin
        LED_L <= 4'd8;
    end
    else begin
        LED_L <= LED_L;
    end
endmodule

呼吸灯模块:

`timescale 1ns / 1ns
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/08/24 13:39:06
// Design Name: 
// Module Name: breath_led
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module breath_led#(
    parameter  CNT_1US_MAX = 7'd99,
    parameter  CNT_1MS_MAX = 10'd999,
    parameter  CNT_1S_MAX  = 10'd999
)
(
    input wire    sys_clk,
    input wire    sys_rst_n,

    output reg   led_out
);

reg  [9:0]   cnt_1s;
reg  [9:0]   cnt_1ms;
reg  [6:0]   cnt_1us;
reg          cnt_en; 


always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        cnt_1us <= 7'd0;     
    end
    else if (cnt_1us == CNT_1US_MAX) begin
        cnt_1us <= 7'd0;
    end
    else begin
        cnt_1us <= cnt_1us + 7'd1;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        cnt_1ms <= 10'd0;        
    end
    else if ((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
        cnt_1ms <= 10'd0;
    end
    else if (cnt_1us == CNT_1US_MAX) begin
        cnt_1ms <= cnt_1ms + 10'd1;
    end
    else begin
        cnt_1ms <= cnt_1ms;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        cnt_1s <= 10'd0;
    end
    else if ((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
        cnt_1s <= 10'd0;
    end
    else if ((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
        cnt_1s <= cnt_1s + 10'd1;
    end
    else begin
        cnt_1s <= cnt_1s;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        cnt_en <= 1'b0;
    end
    else if ((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
        cnt_en <= ~cnt_en;
    end
    else begin
        cnt_en <= cnt_en;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        led_out <= 1'b0;
    end
    else if (((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s)) || ((cnt_en == 1'b1) && (cnt_1ms >= cnt_1s))) begin
        led_out <= 1'b1;
    end
    else begin
        led_out <= 1'b0;
    end 
end
endmodule

UART_RX模块:

`timescale 1ns / 1ns
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/03 12:36:32
// Design Name: 
// Module Name: uart_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module uart_rx
#(
    parameter       UART_BPS       =   'd9600,
    parameter       CLK_FREQ         =   'd100_000_000
)
(
    input   wire                sys_clk     ,
    input   wire                rst_n       ,
    input   wire                rx          ,

    output  reg       [7:0]     Po_data     ,
    output  reg                 Po_flag
);

parameter  BAUD_CNT_MAX     =       CLK_FREQ/UART_BPS;

reg             rx_reg1;        // 同步到系统时钟下
reg             rx_reg2;     
reg             rx_reg3;        // 打两拍,减小亚稳态危�
reg             Start_flag;     // å¼?å§‹ä¸€ä¸ªæ•°æ®å¸§çš„ä¼ è¾“æ ‡å¿—ä¿¡å?
reg             Work_en;        // æ ‡è¯†æ•°æ®é‡‡é›†èŒƒå›´ï¼ŒæŽ¥æ”¶æ•°æ®å·¥ä½œä½¿èƒ½ä¿¡å?
reg     [15:0]  baud_cnt;       // 计数1ç å…ƒæ‰?éœ?要的时钟周期æ•?(在本实验中,1ç å…ƒ=1bit)
reg             Bit_flag;       // 每bit数据稳定点拉高一� 
reg     [3:0]   Bit_cnt;        // bit计数�
reg     [7:0]   rx_data;
reg             rx_flag;


always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        // reset
        rx_reg1 <= 1'b1;
        rx_reg2 <= 1'b1;
        rx_reg3 <= 1'b1;
    end
    else begin
        rx_reg1 <= rx;
        rx_reg2 <= rx_reg1;
        rx_reg3 <= rx_reg2;
    end
end




always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Start_flag <= 1'b0;
    end
    else if ((rx_reg3 == 1'b1) && (rx_reg2 == 1'b0) && (Work_en == 1'b0)) begin
        Start_flag <= 1'b1;
    end
    else begin
        Start_flag <= 1'b0;
    end
end


always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Work_en <= 1'b0;
    end
    else if (Start_flag == 1'b1) begin
        Work_en <= 1'b1;
    end
    else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
        Work_en <= 1'b0;
    end
    else begin
        Work_en <=  Work_en;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        baud_cnt <=  16'd0;
    end
    else if ((baud_cnt == BAUD_CNT_MAX - 1) || (~Work_en)) begin
        baud_cnt <= 16'd0;
    end
    else begin
        baud_cnt <= baud_cnt + 1'b1;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Bit_flag <=  1'b0;
    end
    else if (baud_cnt == BAUD_CNT_MAX / 2 - 1) begin
        Bit_flag <= 1'b1;
    end
    else begin
        Bit_flag<= 1'b0;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Bit_cnt <=  1'b0;
    end
    else if ((Bit_flag) && (Bit_cnt == 4'd8)) begin
        Bit_cnt <=  1'b0;
    end
    else if (Bit_flag) begin
        Bit_cnt <= Bit_cnt + 1'b1;
    end
    else begin
        Bit_cnt <=  Bit_cnt;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        rx_data <=  8'd0;
    end
    else if (((Bit_cnt >= 4'd1) && (Bit_cnt <= 4'd8)) && (Bit_flag == 1'b1))begin
        rx_data <= {rx_reg3,rx_data[7:1]};
    end
    else begin
        rx_data <= rx_data;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        rx_flag <=  1'b0;
    end
    else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
        rx_flag <= 1'b1;
    end
    else
        rx_flag <= 1'b0;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Po_data <=  8'd0;
    end
    else if (rx_flag == 1'b1) begin
        Po_data <= rx_data;
    end
    else begin
        Po_data <= Po_data;
    end
end


always @(posedge sys_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        Po_flag <=  1'd0;
    end
    else begin
        Po_flag <=  rx_flag;
    end
end



endmodule

UART_TX模块 :

//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/04 19:36:40
// Design Name: 
// Module Name: uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module uart_tx
#(
    parameter       UART_BPS         =   'd9600,
    parameter       CLK_FREQ         =   'd100_000_000
)
(
    input  wire          sys_clk         ,
    input  wire          rst_n           ,
    input  wire  [7:0]   Pi_data         ,
    input  wire          Pi_flag         ,

    output reg           tx,
    output reg           Work_en
);


parameter  BAUD_CNT_MAX     =       CLK_FREQ/UART_BPS;

reg    [15:0]   baud_cnt    ;
reg    [3:0]    Bit_cnt    ;
reg             Bit_flag     ;





always @(posedge sys_clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        Work_en <= 1'b0;
    end
    else if (Pi_flag == 1'b1) begin
        Work_en <= 1'b1;
    end
    else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
        Work_en <= 1'b0;
    end
    else begin
        Work_en <= Work_en;
    end
end


always @(posedge sys_clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        baud_cnt <= 16'd0;
    end
    else if ((baud_cnt == BAUD_CNT_MAX - 1'b1)  || (~Work_en)) begin
        baud_cnt <= 16'd0;
    end
    else begin
        baud_cnt <= baud_cnt + 1'b1;
    end
end


always @(posedge sys_clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        Bit_flag <= 1'b0;
    end
    else if (baud_cnt == (BAUD_CNT_MAX - 1'b1)) begin
        Bit_flag <= 1'b1;
    end
    else begin
        Bit_flag <= 1'b0;
    end
end

always @(posedge sys_clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        Bit_cnt <= 1'b0;
    end
    else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
        Bit_cnt <= 4'd0;
    end
    else if ((Bit_flag == 1'b1) && (Work_en == 1'b1)) begin
        Bit_cnt <= Bit_cnt + 1'b1;
    end
    else begin
        Bit_cnt <= Bit_cnt;
    end
end


always @(posedge sys_clk or negedge rst_n)begin
    if (rst_n == 1'b0) begin
        tx  <= 1'b1;
    end
    else if (Work_en == 1'b1) begin
        case(Bit_cnt)
            0   : tx <= 1'b0;
            1   : tx <= Pi_data[0];
            2   : tx <= Pi_data[1];
            3   : tx <= Pi_data[2];
            4   : tx <= Pi_data[3];
            5   : tx <= Pi_data[4];
            6   : tx <= Pi_data[5];
            7   : tx <= Pi_data[6];
            8   : tx <= Pi_data[7];
            9   : tx <= 1'b1;
            default:tx<=1'b1;
        endcase
    end
end

endmodule

LED_CTRL模块 :

//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/05 21:27:03
// Design Name: 
// Module Name: led_ctrl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module led_ctrl(
    input   wire            sys_clk     ,
    input   wire            rst_n       ,
    input   wire            key_flag_w  ,
    input   wire            key_flag_b  ,
    input   wire    [7:0]   pi_data     ,
    input   wire    [3:0]   led_out_w   ,
    input   wire            led_out_b   ,

    output  reg     [3:0]   led         ,
    output  wire    [7:0]   po_data     ,
    output  wire            po_flag
);


reg         w_en    ;
reg         b_en    ;


always @(posedge sys_clk or negedge rst_n)
    if (~rst_n) begin
        w_en <= 1'b0;
    end
    else if (key_flag_b == 1'b1) begin
        w_en <= 1'b0;
    end
    else if (key_flag_w == 1'b1) begin
        w_en  <= ~w_en;
    end
    else begin
        w_en <= w_en;
    end

always @(posedge sys_clk or negedge rst_n)
    if (~rst_n) begin
        b_en <= 1'b0;
    end
    else if (key_flag_w == 1'b1) begin
        b_en <= 1'b0;
    end
    else if (key_flag_b == 1'b1) begin
        b_en  <= ~b_en;
    end
    else begin
        b_en <= b_en;
    end

always @(posedge sys_clk or negedge rst_n)
    if (~rst_n) begin
        led <= 4'b0000;
    end
    else if (pi_data[0] == 1'b1) begin
        led <= led_out_w;
    end
    else if (pi_data[1] == 1'b1) begin
        led <= {led_out_b,led_out_b,led_out_b,led_out_b};
    end
    else begin
        led <= 4'b0000;
    end


assign po_data = {6'b000_000,b_en,w_en};

assign po_flag = {key_flag_w || key_flag_b};



endmodule

RS485总控模块

`timescale 1ns / 1ns
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/05 21:52:41
// Design Name: 
// Module Name: rs485
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rs485(
    input   wire            sys_clk     ,
    input   wire            rst_n       ,
    input   wire            key_in_w    ,
    input   wire            key_in_b    ,
    input   wire            rx          ,


    output  wire            tx          ,
    output  wire    [3:0]   led         ,
    output  wire            re
);

parameter   KEY_CNT_MAX = 20'd999_999;
parameter   WATER_LED_CNT_MAX = 25'd24999999;
parameter   B_CNT_1US_MAX = 7'd99,
            B_CNT_1MS_MAX = 10'd999,
            B_CNT_1S_MAX  = 10'd999;

parameter   UART_BPS = 9600        ,
            CLK_FREQ = 100_000_000 ;

wire           w_flag      ;
wire           b_flag      ;
wire  [3:0]    w_led       ;
wire           b_led       ;
wire  [7:0]    rx_data     ;
wire  [7:0]    po_data     ;
wire           po_flag     ;



key_filter#(
    .CNT_MAX(KEY_CNT_MAX)
)key_filter_inst_w
(
    .sys_clk (sys_clk),
    .rst_n   (rst_n),
    .key_in  (key_in_w),

    .key_flag(w_flag)
);

key_filter#(
    .CNT_MAX(KEY_CNT_MAX)
)key_filter_inst_b
(
    .sys_clk (sys_clk),
    .rst_n   (rst_n),
    .key_in  (key_in_b),

    .key_flag(b_flag)
);

water_led
#(
    .M(WATER_LED_CNT_MAX)
)water_led_inst
(
    .clk (sys_clk),
    .rst_n(rst_n),

    .LED_L(w_led)
);


breath_led#(
    .CNT_1US_MAX(B_CNT_1US_MAX),
    .CNT_1MS_MAX(B_CNT_1MS_MAX),
    .CNT_1S_MAX (B_CNT_1S_MAX )
)breath_led_inst
(
    .sys_clk(sys_clk),
    .sys_rst_n(rst_n),

    .led_out(b_led)
);




uart_tx
#(
    .UART_BPS (UART_BPS),
    .CLK_FREQ (CLK_FREQ)
)uart_tx_inst
(
    .sys_clk(sys_clk),
    .rst_n  (rst_n),
    .Pi_data(po_data),
    .Pi_flag(po_flag),

    .tx     (tx),
    .Work_en(re)
);

uart_rx
#(
    .UART_BPS (UART_BPS),
    .CLK_FREQ (CLK_FREQ)
)uart_rx_inst
(
    .sys_clk(sys_clk),
    .rst_n  (rst_n),
    .rx     (rx),

    .Po_data(rx_data),
    .Po_flag()
);

led_ctrl led_ctrl_inst(
    .sys_clk     (sys_clk),
    .rst_n       (rst_n),
    .key_flag_w  (w_flag),
    .key_flag_b  (b_flag),
    .pi_data     (rx_data),
    .led_out_w   (w_led),
    .led_out_b   (b_led),

    .led         (led),
    .po_data     (po_data),
    .po_flag     (po_flag)
);


endmodule

三、下板实验

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值