当前位置: 首页 > news >正文

基于RS-485接口的芯片的FPGA驱动程序

1.简介

        ADM3485E 是一款 3.3V 低功耗数据收发器,具有 ±15kV 的 ESD(静电放电) 保护,专为多点总线传输线上的半双工通信设计。它支持平衡数据传输,符合 TIA/EIA 标准 RS-485 和 RS-422 的要求。作为一款半双工收发器,ADM3485E 采用共享差分线路设计,提供独立的驱动器和接收器启用输入,确保高效的数据传输与接收控制。这款收发器在高噪声环境下具有出色的抗干扰性能,非常适合工业自动化、通信设备及其他需要可靠数据传输的应用场景。其框架如下所示:

图1 ADM3485E框架
图1 ADM3485E框架

       根据这个架构,可以推测出 ADM3485E 的工作原理。其由接收器(R)和发射器(D)两部分组成,A 和 B 是差分信号。在接收信号时,差分信号(A、B)首先进入差分放大器,放大器通过比较 A 和 B 的电压差,判断信号是高电平还是低电平。在此过程中,RE_n 是接收端差分放大器的使能信号,用于控制接收功能的启用与禁用。发射器部分的工作原理类似,数据输入到差分驱动器后,驱动器根据控制信号生成差分信号 A 和 B,从而实现信号的发送。在此过程中,DE是发送端差分放大器的使能信号,用于控制发送功能的启用与禁用。常见器件连接方式如下:

2.引脚说明

        ADM3485引脚如图2所示。

图2 ADM3485引脚图
图2 ADM3485引脚图

下面是引脚说明:

IO类型功能
RO输出-数字引脚接收器输出端,根据差分信号A,B来输入高低电平
RE_n输出-数字引脚接收器输出使能,低电平有效
DE输出-数字引脚发送器输出使能,高电平有效
DI输入-数字引脚发送器的数据输入端
GND模拟引脚
A模拟引脚差分传输线+(正向)
B模拟引脚差分传输线-(反向)
VCC模拟引脚供电电源

        在电路设计中,通常会将RE_n,DE这两个使能信号短接作为一个引脚RT,低电平代表接收使能,高电平是发送使能,如图3所示。这样既可以实现控制通信的功能,也可以减少IO引脚的使用。

图3  原理图示例
图3  原理图示例

3.RS485协议

      由于RS485协议的时序较为常见,因此ADM3485E器件手册中并未专门列出时序图。起初,我以为RS485会有独特的时序,但在查阅相关资料后,我发现RS485的时序与UART协议的时序实际上是相同的。这是因为UART协议本身并不定义具体的电气特性,它仅规定了数据传输的时序格式(如起始位、数据位、校验位和停止位)。换句话说,UART负责将并行数据转换为串行数据,而信号的实际传输则是由外部驱动电路来实现。
电信号的传输过程遵循不同的电平标准和接口规范。对于异步串行通信,常见的接口标准包括RS232、RS422和RS485等,它们定义了各自的电气特性。例如,RS232是单端信号传输,而RS422/485则采用差分信号传输。
总结来说,UART是一种协议标准,主要负责数据的串并转换;而RS485则是一种物理接口标准,专注于信号的传输方式和电气特性。虽然RS485和UART的时序相同,但它们分别代表了不同层次的协议:UART作为数据格式的定义,RS485作为接口规范。
UART 在发送或接收过程中的一帧数据由 4 部分组成,起始位、数据位、奇偶校验位和停止位,如图4所示。

图4  UART协议帧
图4  UART协议帧

        各组成成分的详细信息如下表所示。

字段描述大小备注
起始位 (Start Bit)用于标识数据帧的开始。1位一般为逻辑低电平 (0),表示数据的开始。因为空闲时是高电平,所以有低电平时可以识别出来。
数据位 (Data Bits)传输的有效数据。5-9位(常见为8位)数据位数量可配置,常用的是8位数据。
校验位 (Parity Bit)用于错误检测,可以选择偶校验、奇校验或无校验。1位(可选)校验位帮助检测数据传输中的错误。
停止位 (Stop Bit)标识数据帧的结束。1位、1.5位或2位停止位可选,常见的是1位或2位。
空闲位 (Idle Bit)在没有数据传输时,线路处于的状态。当UART线路空闲时,它处于逻辑高电平 (1)。

4.verilog代码

        根据ADM3485E工作的原理可知,要想实现对ADM3485E的通信控制,主要是实现UART协议帧的发送和接收。 通过根据UART协议帧的结构,并配合接收和发送使能信号,即可实现对ADM3485E的通信控制。需要发送的时候开启发送使能,不发送的时候关闭发送使能。所以先实现uart发送和接收,再在外层加个控制逻辑就可以了。

uart_tx的verilog代码:

/* * file			: uart_tx.v* author		: yuluo_lhw* date			: 2025-09-01* version		: v1.0* description	: uart tx :8bit data  无校验位 1位停止位*/
module uart_tx(
input	wire			clk,				//采样时钟
input	wire			rst_n,
input	wire	[7:0]	data,
input	wire			tx_en,			//上升沿有效output	reg				tx,
output	reg				tx_done);
parameter	CLK_FREQ	= 100_000_000; //时钟频率
parameter   BAUDRATE    = 115200 ;
localparam  BAUD_CNT    = CLK_FREQ/BAUDRATE; //为得到指定波特率,对系统时钟计数 BPS_CNT 次,也就是BPS_CNT个CLK发送一个bit.  868.0wire  tx_en_pos ;
reg   tx_en_do ;
reg   tx_en_d1 ;
reg   [9:0] baud_cnt ;
reg   [3:0] bit_cnt ;
reg   tx_busy ; //1:进入发送bit阶段  0:空闲
//tx_en
assign  tx_en_pos = ~tx_en_d1& tx_en_do ;
always@(posedge clk or negedge rst_n)beginif(~rst_n)begintx_en_do <= 0 ;tx_en_d1 <= 0 ;endelse begintx_en_do <= tx_en ;tx_en_d1 <= tx_en_do ;end
end//tx_busy
always@(posedge clk or negedge rst_n)beginif(~rst_n)begintx_busy <= 0 ;endelse beginif(tx_en_pos) begin tx_busy <=  1 ;endelse if(bit_cnt>=9 && (baud_cnt>=BAUD_CNT-1) ) tx_busy <=  0 ; //发送玩停止位结束else tx_busy <=  tx_busy ;end
end//baud_cnt
always@(posedge clk or negedge rst_n)beginif(~rst_n)beginbaud_cnt <= 0 ;endelse beginif(tx_busy) begin if(baud_cnt>=BAUD_CNT-1) baud_cnt <= 0 ;else baud_cnt <= baud_cnt + 1 ;endelse baud_cnt <= 0 ;end
end//bit_cnt 
always@(posedge clk or negedge rst_n)beginif(~rst_n)beginbit_cnt <= 0 ;endelse beginif(tx_busy) begin if(baud_cnt==BAUD_CNT-1) bit_cnt <= bit_cnt + 1 ;else bit_cnt <= bit_cnt ;endelse bit_cnt <= 0 ;end
end//tx 
always@(posedge clk or negedge rst_n)beginif(~rst_n)begintx <= 1 ;endelse beginif(tx_busy) begin case(bit_cnt)4'd0: tx <= 0 ;  //停止位4'd1: tx <= data[0] ; //小端传送4'd2: tx <= data[1] ; 4'd3: tx <= data[2] ; 4'd4: tx <= data[3] ; 4'd5: tx <= data[4] ; 4'd6: tx <= data[5] ; 4'd7: tx <= data[6] ; 4'd8: tx <= data[7] ; 4'd9: tx <= 1		; //停止位default : tx <= 1 ;endcaseend else tx <= 1 ;end
end
//tx_done
always@(posedge clk or negedge rst_n)beginif(~rst_n)begintx_done <= 1 ;endelse beginif(tx_busy) begin tx_done <= 0 ;endelse tx_done <= 1 ;end
end
endmodule 

仿真代码:

`timescale 1ns / 1psmodule tb_uart_tx;reg clk;
reg rst_n;
reg [7:0] data;
reg tx_en;wire tx;
wire tx_done;uart_tx  #(
.CLK_FREQ (100_000_000),
.BAUDRATE (115200     )
) u_uart_tx(.clk(clk),.rst_n(rst_n),.data(data),.tx_en(tx_en),.tx(tx),.tx_done(tx_done)
);always #5 clk = ~clk ;initial beginclk = 0 ;rst_n = 0;tx_en = 0;//data1data = 8'b01010101;  #20 rst_n = 1;  #10 tx_en = 1;#10 tx_en = 0;@(posedge tx_done);  //等待上升沿//wait(tx_done == 1);//data2#10 data = 8'b11000011;  #10 tx_en = 1;#10 tx_en = 0;@(posedge tx_done);  //等待上升沿#50;$finish;
end// Monitor signals
initial begin$monitor("At time %t, tx = %b, tx_done = %b, data = %b", $time, tx, tx_done, data);
endendmodule

        从以下两图数据可以看出,每个比特的传输需要 868 个时钟周期。因此,在 100MHz 时钟频率下,每秒可传输的数据量为 100,000,000/868 ≈ 115,200 比特,该结果与预期相符。

        如下图所示,数据帧的发送格式符合预期:起始位为0,随后是8位数据位(采用小端传输,先发送低位),接着是1位停止位1,最后恢复为空闲状态。

        接收端的代码也按照UART协议帧来写就可以了,只要检测到rx的下降沿就开始接收数据,不过rx最好进行打拍,避免出现亚稳态。这里就不粘贴了。

5.参考资料

        ADI-ADM3485E.pdf

     以上就是本次学习的记录。欢迎加我为好友(QQ:235840795),一起交流与学习!

http://www.dtcms.com/a/361211.html

相关文章:

  • 吴恩达机器学习作业十二:协同过滤(电影推荐系统)
  • 广电手机卡到底好不好?
  • Git基础使用和PR贡献
  • .Net程序员就业现状以及学习路线图(二)
  • Android面试指南(六)
  • 大模型落地全流程实践:从技术选型到企业级部署
  • 音视频开发入门:FFmpeg vs GStreamer,新手该如何选择?
  • 松灵斯坦福Mobile ALOHA同款 | 通过低成本全身远程操作实现双手机器人移动操控学习
  • 01数据结构-红黑树
  • 永磁同步电机无速度算法--高频脉振方波注入法(测量轴系转子位置误差信号解耦处理)
  • Spark引擎中RDD的性质
  • 【牛客JZ31】—栈的压入弹出序列判断算法详解
  • 【73页PPT】MES应用介绍(附下载方式)
  • SpringBoot @RefreshScope 注解的极致玩法
  • SpringCloud-服务注册-服务发现
  • AI瘦身狂魔!微软推出原生1-bit大模型,性能不减,内存仅需同行零头!
  • 博0进化版
  • 9月校招难题怎么解?AI面试精准匹配人才
  • 系统架构设计师备考第12天——计算机语言-建模形式化语言
  • Windows 命令行:cd 命令1,cd 命令的简单使用
  • 数据结构:单链表的应用(力扣算法题)第二章
  • APP性能测试,你需要关注哪些指标?
  • React 学习笔记3 生命周期 受控/非受控组件
  • 阿里云代理商:轻量应用服务是什么?怎么用轻量应用服务器搭建个人博客?
  • 大模型落地:从微调到部署的全景式实战指南
  • MFC应用防止多开
  • Prometheus Alertmanager 告警组件学习
  • Linux 正则表达式与grep命令
  • 车载卫星通信:让自动驾驶“永不掉线”?
  • Kafka面试精讲 Day 4:Consumer消费者模型与消费组