串口RS485

1.原理

全双工:在同一时刻可以同时进行数据的接收和数据的发送,两者互不影响

半双工:在同一时刻只能进行数据的接收或者数据的发送,两者不能同时进行

差分信号幅值相同,相位相反,有更强的抗干扰能力。

干扰对差分信号的影响都是相同的,所以差分信号的干扰一相减就没有了

RS485的优点,采用差分信号有更强的抗干扰能力;相比RS232能能进行长距离传输(RS485要用到收发器芯片,收发器的灵敏度是很高的,可以检测到低至200mv的电压,表示传输信号在千米之外都可以恢复,最远的通信距离可以达到1200米左右,速度最快10MB/s,速度和距离是成反比的,速度越小,传输距离越长,长距离的通信可以增加RS485的中继器);缺点就是只支持半双工。

RE是低电平有效,表示数据的收,当接收时,RE=0,DE=0;然后芯片将差分信号转换为单端信号。当RE=1,DE=1时,数据发送,将单端信号转换为差分信号。

485和232使用相同的传输协议

2.代码

以上是控制板的波形图

以上是被控板的时序图

2.1 led_ctrl.v

module led_ctrl(
	input wire 			sys_clk		,
	input wire 			sys_rst_n	,
	input wire [3:0]	led_out_w	,//流水灯
	input wire			led_out_b   ,//呼吸灯
	input wire [7:0]	pi_data		,
	input wire 			key_flag_w	,
	input wire 			key_flag_b	,
	
	output reg  [3:0]	led			,
	output wire  [7:0]	po_data		,
	output wire 		po_flag	
);

reg w_en;
reg b_en;


assign po_data={6'b000_000,b_en,w_en};
assign po_flag=key_flag_b||key_flag_w;

always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n==1'b0)
		w_en<=1'b0;
	else if(key_flag_b==1'b1)
		w_en<=1'b0;
	else if(key_flag_w==1'b1)
		w_en<=~w_en;
	else
		w_en<=w_en;
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n==1'b0)
		b_en<=1'b0;
	else if(key_flag_w==1'b1)
		b_en<=1'b0;
	else if(key_flag_b==1'b1)
		b_en<=~b_en;
	else 
		b_en<=b_en;
			
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n==1'b0)
		led<=4'b1111;
	else if(po_data[0]==1'b1)
		led<=led_out_w;
	else if(po_data[1]==1'b1)
		led<=led_out_b;
	else
		led<=4'b1111;
		
endmodule
		
	

2.2 uart_tx.v

闲杂输出的赋值条件不再是bit_flag信号,而是使能信号,rx下降沿延迟work_en一个周期,因为是时序逻辑,而且只延迟一个时钟周期,一个Bit传输有5208个周期。若是想对齐可以把work_en打一拍

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 			work_en			,
	output reg 			tx		
);
 
parameter BAUD_CNT_MAX=CLK_FREQ/UART_BPS;

reg [15:0]	baud_cnt;
reg bit_flag;
reg [3:0]bit_cnt;
 
 
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;
	
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n==1'b0)
		baud_cnt<=16'd0;
	else if((baud_cnt==BAUD_CNT_MAX-1'b1)||(work_en==1'b0))
		baud_cnt<=16'd0;
	else if(work_en==1'b1)
		baud_cnt<=baud_cnt+1'b1;
	else
		baud_cnt<=baud_cnt;
		
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) //因为只有使能信号为高电平时,使能信号才进行计数,使能信号为低电平,波特计数器为0。所以不适合用计数值为0来作为条件
		bit_flag<=1'b1;
	else 
		bit_flag<=1'b0;
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(bit_flag==1'b1)
		bit_cnt<=bit_cnt+1'b1;
	else
		bit_cnt<=bit_cnt;
		
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)
			4'd0: tx<=1'b0;
			4'd1: tx<=pi_data[0];
			4'd2: tx<=pi_data[1];
			4'd3: tx<=pi_data[2];
			4'd4: tx<=pi_data[3];
			4'd5: tx<=pi_data[4];
			4'd6: tx<=pi_data[5];
			4'd7: tx<=pi_data[6];
			4'd8: tx<=pi_data[7];
			4'd9: tx<=1'b1;
			default:tx<=1'b1;
		endcase
endmodule

2.3 rs485.v

module rs485(
	input wire		sys_clk		,
	input wire 		sys_rst_n	,
	input wire	    key_in_w	,
	input wire		key_in_b	,
	input wire 		rx			,
	
	output wire 	tx			,
	output wire 	re			,
	output wire[3:0]led
);

parameter KEY_CNT_MAX=20'd999_999;
parameter WATER_LED_CNT_MAX=25'd24_999_999;

parameter CNT_1US_MAX  =    6'd49	 ,
          CNT_1MS_MAX  =    10'd999  ,
          CNT_1S_MAX   =    10'd999  ;
		
parameter UART_BPS=9600,
          CLK_FREQ=50_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	)		,
	.sys_rst_n	(sys_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	)		,
	.sys_rst_n	(sys_rst_n	)	,
	.key_in		(key_in_b	)	,
	             
	.key_flag	(b_flag	)	
);


water_led
#(
	.CNT_MAX(WATER_LED_CNT_MAX)
)
water_led_inst
(
	.sys_clk	(sys_clk	),
	.sys_rst_n	(sys_rst_n	),
	             
	.led_out	(w_led	)
);


breath_led#(
	.CNT_1US_MAX(CNT_1US_MAX ),
	.CNT_1MS_MAX(CNT_1MS_MAX ),
	.CNT_1S_MAX (CNT_1S_MAX  )

)
breath_led_inst
(
	.sys_clk	(sys_clk	)	,
	.sys_rst_n	(sys_rst_n),
	             
	.led_out    (b_led  )
);
 

uart_rx
#(
	.UART_BPS(UART_BPS),
	.CLK_FREQ( CLK_FREQ )
)
uart_rx_inst
(
 	.sys_clk	(sys_clk	)		,
	.sys_rst_n	(sys_rst_n	)	,
	.rx			(rx			)	,
	             
	.po_data	(rx_data	)		,
	.po_flag    ()
);

led_ctrl led_ctrl_inst(
	.sys_clk	(sys_clk)	,
	.sys_rst_n	(sys_rst_n),
	.led_out_w	(w_led),
	.led_out_b  (b_led),
	.pi_data	(rx_data)	,
	.key_flag_w	(w_flag),
	.key_flag_b	(b_flag),
	
	.led		(led)	,
	.po_data	(po_data)	,
	.po_flag	(po_flag)
);

uart_tx
#(
	.UART_BPS(UART_BPS    	),
	.CLK_FREQ(CLK_FREQ )
 
)
uart_tx_inst
(
	.sys_clk	(sys_clk)		,
	.sys_rst_n	(sys_rst_n)	,
	.pi_data	(po_data)		,
	.pi_flag	(po_flag)		,
	
	.work_en	(re)		,
	.tx		    (tx)
);

endmodule

2.4 tb_rs485.v

`timescale 1ns/1ns

module tb_rs485();

reg sys_clk;
reg sys_rst_n;
reg key_in_w	;
reg key_in_b	;
reg rx			;
wire tx;
wire re;
wire [3:0]led;

initial 
	begin
		sys_clk=1'b1;
		sys_rst_n<=1'b0;
		key_in_b<=1'b1;
		key_in_w<=1'b1;
		#20
		sys_rst_n<=1'b1;
		//流水灯
		#2000000  key_in_w<=1'b0; //按下流水灯的按键
		#20 	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1; //模拟前抖动
		#20 	  key_in_w<=1'b0; //模拟稳定状态
		#200  	  key_in_w<=1'b1; //模拟后抖动
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
		//呼吸灯
		#2000000  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#200  	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		//呼吸灯
		#2000000  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#200  	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		#20 	  key_in_b<=1'b0;
		#20 	  key_in_b<=1'b1;
		//流水灯
		#2000000  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#200  	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
		#20 	  key_in_w<=1'b0;
		#20 	  key_in_w<=1'b1;
	
	end
	
always #10 sys_clk=~sys_clk;

defparam rs485_inst0.KEY_CNT_MAX=5;
defparam rs485_inst0.WATER_LED_CNT_MAX=4000;
defparam rs485_inst1.WATER_LED_CNT_MAX=4000;
defparam rs485_inst0.CNT_1US_MAX=4;
defparam rs485_inst1.CNT_1US_MAX=4;
defparam rs485_inst0.CNT_1MS_MAX=9;
defparam rs485_inst1.CNT_1MS_MAX=9;
defparam rs485_inst0.CNT_1S_MAX=9;
defparam rs485_inst1.CNT_1S_MAX=9;
defparam rs485_inst0.UART_BPS=1000_000;
defparam rs485_inst1.UART_BPS=1000_000;//越大越快

	
//控制板不用rx信号
rs485 rs485_inst0(
	.sys_clk	(sys_clk)	,
	.sys_rst_n	(sys_rst_n),
	.key_in_w	(key_in_w	),
	.key_in_b	(key_in_b	),
	.rx			(),//对于控制板来说,rx是无效的,因为我们只需要两路按键
	
	.tx			(tx),
	.re			(re),
	.led        ()//控制板的led灯一直是熄灭状态不需要引出来
);

//被控板
rs485 rs485_inst1(
	.sys_clk	(sys_clk)	,
	.sys_rst_n	(sys_rst_n),
	.key_in_w	(	),//对于被控板来说,按键信号是无效的
	.key_in_b	(	),
	.rx			(tx),
	
	.tx			(),//tx和re没有用到不需要引出
	.re			(),
	.led        (led)
);


endmodule

看控制模块

看被控模块

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/544652.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】N子棋小游戏♔

目录 前言 一、何为N子棋游戏&#xff1f; 二、游戏思路 三、游戏实现 3.1 模块化 3.2 游戏棋盘 3.3 下棋操作 3.3.1 玩家下棋 3.3.2 电脑下棋 3.4 判断输赢 总结 前言 三子棋小游戏相信大家都玩过吧&#xff0c;类似的5子琪等等&#xff0c;这篇文章将带着大家从0到…

【leetcode面试经典150题】28.盛最多水的容器(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

分享一些有趣的 Linux 命令

1、sl 会显示一辆火车穿过你的终端屏幕 2、cmatrix 在终端中显示类似于《黑客帝国》电影中的绿色数字雨效果 3、fortune 显示一个随机的名人名言或者笑话 4、cowsay 让一头牛说出你输入的话 5、toilet 在终端中将输入的文本以艺术字体的形式呈现 6、figlet 类似于 toile…

回溯算法初识

文章目录 回溯算法初识什么是回溯算法回溯算法的步骤回溯算模版例题 回溯算法初识 什么是回溯算法 ​ 回溯算法是一种通过不断尝试可能的解决方案来解决问题的算法。它通常用于解决组合优化问题&#xff0c;如排列组合问题、子集和问题等。该算法通过尝试所有可能的候选解&am…

【热门话题】常见分类算法解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 常见分类算法解析1. 逻辑回归&#xff08;Logistic Regression&#xff09;2. 朴…

【设计模式】聊聊观察者设计模式原理及应用

原理 观察者模式属于行为模式&#xff0c;行为模式主要解决类和对象之间交互问题。 含义&#xff1a;在对象之间定义一个一对多的依赖&#xff0c;当一个对象状态改变时&#xff0c;所有依赖的对象会自动通知。 被依赖的对象被观察者(Observable) &#xff0c;依赖的对象观察…

移动Web学习06-移动端适配Less预处理器项目案例

项目目标&#xff1a;实现在不同宽度设备中等比缩放的网页效果 Less代码 import ./base; import ./normalize;// 变量: 存储37.5 rootSize: 37.5rem; *{margin: 0;padding: 0; } body {background-color: #F0F0F0; }// 主体内容 .main {// padding-bottom: (50 / 37.5rem);pa…

缺失msvcr110.dll要怎么处理?快捷的修复msvcr110.dll方法

当你在使用电脑进行工作或娱乐时&#xff0c;可能会突然遇到一个错误提示&#xff1a;“程序无法启动&#xff0c;因为电脑中缺失msvcr110.dll”。这样的情况不仅会打断你的活动&#xff0c;还可能带来一定程度的不便。面对这个在Windows操作系统中相对常见的问题&#xff0c;其…

IDEA2023 开发环境配置

目录 1. 关闭IDEA自动更新1.2 IDEA 新版样式切换 2. Maven配置2.1本地仓库优先加载2.2 maven.config配置文件中 3. 全局配置JDK4. 配置文件编码:UTF-85. 开启自动编译&#xff08;全局配置&#xff09;6. 开启自动导包7. 开启鼠标悬浮&#xff08;提示文档信息&#xff09;8. 设…

7 个适用于 Windows 的最佳电脑分区数据恢复软件

磁盘分区对于正确存储数据以便从硬盘驱动器快速轻松地访问非常有帮助。但是&#xff0c;如果分区损坏&#xff0c;存储在其中的所有数据都会突然变得无法访问。磁盘分区损坏的原因可能有很多&#xff0c;其中最突出的是病毒攻击、突然断电、物理损坏或由于创建坏扇区。 但是&a…

gzip,bzip2,xz,tar-读书笔记(九)

gzip 将文件进行压缩 在Linux系统中&#xff0c;gzip 是一个压缩和解压文件的命令工具。它使用LZ77压缩算法及霍夫曼编码&#xff08;Huffman Coding&#xff09;来压缩文件&#xff0c;通常用来减少文件的大小&#xff0c;以节约磁盘空间或减少网络传输的时间。 gzip 命令的…

Linux gcc 6

本章开始学习工具 什么是工具&#xff1f; 本质也是指令 yum 命令 小火车 sudo yum install sl&#xff08;安装sl&#xff09; sudo yum install -y sl //直接yes就不提示了 yum list //将yum源上的软件都穷举出来 yum search sl //结果不友好&#xff0c;不推荐 yum lis…

Python-GEE遥感云大数据分析、管理与可视化及多领域案例实践应用

随着航空、航天、近地空间遥感平台的持续发展&#xff0c;遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升&#xff0c;呈现出大数据特征。这为相关研究带来了新机遇&#xff0c;但同时也带来巨大挑战。传统的工作站和服务器已无法满足大区域…

【数据结构】泛型(分享重点)

什么是泛型&#xff1f; 泛型就是适用于许多许多类型&#xff0c;对类型参数化。 怎么创建一个泛型呢 class 泛型类名称<类型形参列表> { // 这里可以使用类型参数 } class ClassName<T1, T2, ..., Tn> { } class 泛型类名称<类型形参列表> extends 继承类…

Hadoop 3.1.3

第1章 Hadoop概述 1.1 Hadoop是什么 1.2 Hadoop发展历史&#xff08;了解&#xff09; 1.3 Hadoop三大发行版本&#xff08;了解&#xff09; Hadoop三大发行版本&#xff1a;Apache、Cloudera、Hortonworks。 Apache版本最原始&#xff08;最基础&#xff09;的版本&#x…

AI大模型探索之路-提升篇2:一文掌握AI大模型的核心-注意力机制

目录 前言 一、注意力机制简介 二、注意力机制的工作原理 三、注意力机制的变体 1、自注意力&#xff08;Self-Attention&#xff09; 2、双向注意力&#xff08;Bidirectional Attention&#xff09; 3、多头注意力&#xff08;Multi-Head Attention&#xff09; ​4、…

卫星影像联合无人机实现农业保险全生命周期监管监测

随着科技的进步&#xff0c;农业保险监管系统的发展日新月异。特别是近年来&#xff0c;随着卫星技术与无人机技术的结合&#xff0c;为农业保险监管系统带来了前所未有的革新。本文将深入探讨如何利用卫星与无人机方案构建高效的农业保险监管系统&#xff0c;并结合实例进行说…

网络篇06 | 应用层 自定义协议

网络篇06 | 应用层 自定义协议 01 固定协议设计&#xff08;简化版&#xff09;1&#xff09;总体设计2&#xff09;值设计 02 可变协议设计&#xff08;进阶版&#xff09;1&#xff09;固定头&#xff08;Fixed Header&#xff09;2&#xff09;可变头&#xff08;Variable H…

51单片机-ADC模数转换实验-电压值

一 主要知识点及分析: 1.这里是用到的XPT2046芯片,芯片详细说明自行查阅; 2.这里有两种模式,一般外设的转换用的是单端模式,在使用触摸屏的时候我们选择差分模式; 3.这张图有就是时序图,读写都需要在这上面进行编写代码, 3.1 写8位代码:主要是将传入的控制命令进行写入; 3.2 读…

C# Solidworks二次开发:相机访问相关API详解

大家好&#xff0c;今天要介绍的API为相机相关的API&#xff0c;这篇文章比较适合女孩子&#xff0c;学会了相机就会拍照了&#xff0c;哈哈。 下面是要介绍的API: &#xff08;1&#xff09;第一个为GetFocalDistance&#xff0c;这个API的含义为获取相机的焦距&#xff0c;…