串口RS485
实验目的:
两块开发板互连,实现led灯的相互控制,显示呼吸灯或者流水灯
控制板:消抖后的两路按键信息传入led_ctrl,将它打包成数据帧,产生po_flag标志信号,然后传给tx模块按照UART异步串口通信协议串行发送给被控板
被控板:rx模块接收串行数据帧进行串并转换,之后发送给led_ctrl进行解码,解码后的控制信息控制自身led的显示
1. 串口简介
RS232属于UART串口的一种常用的通信协议,RS485也是
RS485是
双向
、
半双工
通信协议,信号采用差分传输方式,允许多个驱动器和接收器挂在总线上,其中每个驱动器都能够脱离总线
差分信号,赋值相同,相位相反
根据电压差值的大小判断逻辑1/0
差分信号有更好的抗干扰能力,如果碰到了干扰信号,对两路差分信号的影响是相同的,根据电位差,判断干扰部分的逻辑值为0
RS232支持全双工,RS485支持半双工
RS485和232使用相同的通信协议,数据帧结构相同(起始位+数据位+停止位,共10bit)
2. 实验目的
两块开发板互连,实现led灯的相互控制,显示呼吸灯或者流水灯
控制板:消抖后的两路按键信息传入led_ctrl,将它打包成数据帧,产生po_flag标志信号,然后传给tx模块按照UART异步串口通信协议串行发送给被控板
被控板:rx模块接收串行数据帧进行串并转换,之后发送给led_ctrl进行解码,解码后的控制信息控制自身led的显示
3. 代码实现
按键消抖key_filter
复用
对按键信号进行消抖处理
流水灯water_led
复用
呼吸灯breath_led
复用
串口接收模块uart_rx
复用RS232的接收模块
作为
被控板
,接收控制板tx模块传来的串行数据信号,接收完了之后发送给自身的led控制模块
灯控模块led_ctrl
作为
控制板
,接收消抖后的按键信号打包进串口数据帧po_data中,生成po_flag一起发送给自己的tx发送模块
作为
被控板
,接收rx传来的串并转换数据,根据数据帧中的两种灯型的控制信号,控制自身的led显示流水灯还是呼吸灯
串口发送模块uart_tx
在原先RS232的基础上,修改一下
因为要多输出一个收发器使能信号re,当开发板接收的时候,输出0,当开发板发送的时候,输出1,这样就可以参考RS232中tx模块的work_en信号
work_en是只在起始位和8bit数据位的时候拉高,需要对它拉长一下使能时间
module uart_tx
#(
parameter UART_BPS = 'd9600 ,
parameter CLK_FREQ = 'd50_000_000
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [ 7: 0] pi_data ,
input wire pi_flag ,
output reg tx ,
output reg work_en
);
localparam BAUD_CNT_MAX = CLK_FREQ / UART_BPS;
reg [15: 0] baud_cnt ;
reg bit_flag ;
reg [ 3: 0] bit_cnt ;
// work_en
always @ (posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
work_en <= 1'b0;
else if ((bit_cnt == 4'd9) && (bit_flag == 1'b1))
work_en <= 1'b0;
else if (pi_flag == 1'b1)
work_en <= 1'b1;
else
work_en <= work_en;
// baud_cnt
always @ (posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
baud_cnt <= 16'd0;
else if ((work_en == 1'b0) || (baud_cnt == BAUD_CNT_MAX - 1'b1))
baud_cnt <= 16'd0;
else if (work_en == 1'b1)
baud_cnt <= baud_cnt + 1'b1;
// bit_flag
always @ (posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
bit_flag <= 1'b0;
else if (baud_cnt == BAUD_CNT_MAX - 1'b1)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
// bit_cnt
always @ (posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
bit_cnt <= 4'd0;
else if ((bit_cnt == 4'd9) && (bit_flag == 1'b1))
bit_cnt <= 4'd0;
else if ((work_en == 1'b1) && (bit_flag == 1'b1))
bit_cnt <= bit_cnt + 1'b1;
else
bit_cnt <= bit_cnt;
// tx
always @ (posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
tx <= 1'b1;
else if (work_en == 1'b1)
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
endmodule
顶层模块
4. 仿真验证
模拟按下流水灯控制按键、按下呼吸灯控制按键、按下呼吸灯控制按键、按下流水灯控制按键、按下流水灯控制按键
5. 下板验证
用跳线连接两块板子,实现通过串口的交叉互联