串口RS485

  • 1. 串口简介
  • 2. 实验目的
  • 3. 代码实现
  • 按键消抖key_filter
  • 流水灯water_led
  • 呼吸灯breath_led
  • 串口接收模块uart_rx
  • 灯控模块led_ctrl
  • 串口发送模块uart_tx
  • 顶层模块
  • 4. 仿真验证
  • 5. 下板验证


实验目的:

两块开发板互连,实现led灯的相互控制,显示呼吸灯或者流水灯

android RS485 串行通信协议 rs485串口是什么_数据帧

控制板:消抖后的两路按键信息传入led_ctrl,将它打包成数据帧,产生po_flag标志信号,然后传给tx模块按照UART异步串口通信协议串行发送给被控板

被控板:rx模块接收串行数据帧进行串并转换,之后发送给led_ctrl进行解码,解码后的控制信息控制自身led的显示

1. 串口简介

RS232属于UART串口的一种常用的通信协议,RS485也是
RS485是双向半双工通信协议,信号采用差分传输方式,允许多个驱动器和接收器挂在总线上,其中每个驱动器都能够脱离总线

差分信号,赋值相同,相位相反
根据电压差值的大小判断逻辑1/0

差分信号有更好的抗干扰能力,如果碰到了干扰信号,对两路差分信号的影响是相同的,根据电位差,判断干扰部分的逻辑值为0

android RS485 串行通信协议 rs485串口是什么_stm32_02


RS232支持全双工,RS485支持半双工

RS485和232使用相同的通信协议,数据帧结构相同(起始位+数据位+停止位,共10bit)

2. 实验目的

两块开发板互连,实现led灯的相互控制,显示呼吸灯或者流水灯

android RS485 串行通信协议 rs485串口是什么_数据帧

控制板:消抖后的两路按键信息传入led_ctrl,将它打包成数据帧,产生po_flag标志信号,然后传给tx模块按照UART异步串口通信协议串行发送给被控板

被控板:rx模块接收串行数据帧进行串并转换,之后发送给led_ctrl进行解码,解码后的控制信息控制自身led的显示

android RS485 串行通信协议 rs485串口是什么_stm32_04

3. 代码实现

按键消抖key_filter

复用

对按键信号进行消抖处理

android RS485 串行通信协议 rs485串口是什么_数据帧_05

流水灯water_led

复用

android RS485 串行通信协议 rs485串口是什么_sed_06

呼吸灯breath_led

复用

android RS485 串行通信协议 rs485串口是什么_sed_07

串口接收模块uart_rx

复用RS232的接收模块

作为被控板,接收控制板tx模块传来的串行数据信号,接收完了之后发送给自身的led控制模块

android RS485 串行通信协议 rs485串口是什么_stm32_08

灯控模块led_ctrl

作为控制板,接收消抖后的按键信号打包进串口数据帧po_data中,生成po_flag一起发送给自己的tx发送模块

作为被控板,接收rx传来的串并转换数据,根据数据帧中的两种灯型的控制信号,控制自身的led显示流水灯还是呼吸灯

android RS485 串行通信协议 rs485串口是什么_数据帧_09


android RS485 串行通信协议 rs485串口是什么_数据帧_10


android RS485 串行通信协议 rs485串口是什么_stm32_11

串口发送模块uart_tx

在原先RS232的基础上,修改一下

因为要多输出一个收发器使能信号re,当开发板接收的时候,输出0,当开发板发送的时候,输出1,这样就可以参考RS232中tx模块的work_en信号

work_en是只在起始位和8bit数据位的时候拉高,需要对它拉长一下使能时间

android RS485 串行通信协议 rs485串口是什么_sed_12


android RS485 串行通信协议 rs485串口是什么_串口_13

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

顶层模块

android RS485 串行通信协议 rs485串口是什么_数据帧_14

4. 仿真验证

模拟按下流水灯控制按键、按下呼吸灯控制按键、按下呼吸灯控制按键、按下流水灯控制按键、按下流水灯控制按键

android RS485 串行通信协议 rs485串口是什么_sed_15

5. 下板验证

用跳线连接两块板子,实现通过串口的交叉互联

android RS485 串行通信协议 rs485串口是什么_数据帧_16