在工业应用中传输信息可能具有挑战性。在这个项目中,让我们看看我们如何使用FPGA和RS485做到这一点。
项目背景:
许多FPGA部署在工业环境中,用于控制流程、驱动器、执行器和传感器。
用于与这些传感器、执行器和驱动器接口的协议非常多样化,尽管时间敏感网络正在改变这一点。虽然有许多不同的协议,例如Modbus、Profibus和EtherCat。其中许多协议都基于常见的物理层,例如EIA/RS485、EIA/RS422和以太网。
许多接口的关键要求之一是能够在嘈杂的工业环境中以物理层中的低链路误码率运行。EIA/RS485和EIA/RS422都是差分物理层,它们提供强大的多点接口,能够进行双向(EIA/RS485)或单向(EIA/RS422)通信。
有许多应用层协议可以使用这些物理层来实现。在这个项目中,我们将研究使用RS485Pmod和定制的应用层协议将两个MiniZed连接在一起。
硬件部件
安富利MiniZed×1
DigilentPmodRS485×2
软件应用程序和在线服务
AMD-XilinxVitis统一软件平台
应用层
实现的自定义通信协议将使主MiniZed能够从从MiniZed内的16位地址空间读取或写入32位字。对于这个项目,我们将从从站中的BRAM读取和写入。然而,这个BRAM可能被从MiniZed上收集数据的传感器填充。
数据将使用UART通过RS485链路发送,数据包包含多个UART传输
写入的格式是
《STX》《ADDRMSB》《ADDRLSB》《DataMSB》《Data》《Data》《DataLSB》
从机将以单字节ACK或NACK响应写入
读取的格式是
《ENQ》《ADDRMSB》《ADDRLSB》
MiniZed从站的读取响应将是
《SOH》《ADDRMSB》《ADDRLSB》《DataMSB》《Data》《Data》《DataLSB》
SOH、STX、ENQ、ACK和NACK在ASCII表中定义
当然,这个协议可以在像ZYNQ这样的处理器中使用UART来实现,以使协议具有可扩展性。我为UART、ProtocolMaster和ProtocolSlave创建了自定义RTL模块。
由于RS485在同一双绞线上是定向的,因此协议必须仅在准备好发送时启用RS485发送器,以减少多个发送器尝试同时发送时总线上的争用可能性。
MiniZedMaster
MiniZedMaster设计将使用PS内核通过RS485接口发送和接收数据。这将使链路能够被测试,因为数据应该能够通过链路写入,然后以不同的顺序从MiniZed从站中的块RAM中读回。
该设计使用连接到协议主模块的AXIGPIO模块来驱动协议主模块的接口要求。这包括地址、数据和读或写操作。结果提供了从中读取的地址和读取的数据。
为了能够调试应用程序,我还包括了几个ILA,帮助理解系统行为。
在MinizedMaster上运行的软件应用程序是
#include
#include "platform.h"
#include "xil_printf.h"
#include "xgpio.h"
#define DATA_ADDR XPAR_GPIO_0_DEVICE_ID
#define VALID_RW XPAR_GPIO_1_DEVICE_ID
#define DATA_BCK XPAR_GPIO_2_DEVICE_ID
#define DATA_VALID_CH 1
#define ADDR_RW_CH 2
XGpio Gpio1;
XGpio Gpio2;
XGpio Gpio3;
int count = 0;
int main()
{
init_platform();
XGpio_Initialize(&Gpio1, DATA_ADDR);
XGpio_Initialize(&Gpio2, VALID_RW);
XGpio_Initialize(&Gpio3, VALID_RW);
while(1){
u32 rd_data, rd_addr;
//write
XGpio_DiscreteWrite(&Gpio1, DATA_VALID_CH, count );
XGpio_DiscreteWrite(&Gpio1, ADDR_RW_CH, 0x5001);
XGpio_DiscreteWrite(&Gpio2, ADDR_RW_CH, 0x0);
XGpio_DiscreteWrite(&Gpio2, DATA_VALID_CH, 0x1);
XGpio_DiscreteWrite(&Gpio2, DATA_VALID_CH, 0x0);
usleep(1000);
//read
XGpio_DiscreteWrite(&Gpio1, ADDR_RW_CH, 0x5001);
XGpio_DiscreteWrite(&Gpio2, ADDR_RW_CH, 0x1);
XGpio_DiscreteWrite(&Gpio2, DATA_VALID_CH, 0x1);
XGpio_DiscreteWrite(&Gpio2, DATA_VALID_CH, 0x0);
usleep(10000);
rd_data = XGpio_GetDataDirection(&Gpio3, 1);
rd_data = XGpio_DiscreteRead(&Gpio3, 1);
rd_addr = XGpio_DiscreteRead(&Gpio3, 2);
if(rd_data != count){
printf("read back not correct %d, %d \n\r", rd_data, count);
}
usleep(1000000);
count++;
}
cleanup_platform();
return 0;
}
MiniZedSlave
MiniZedSlave使用PS模块为逻辑设计提供时钟。协议从站连接一个BRAM,该BRAM存储通过通信链路提供的数据。
MiniZedSlave的这个实现不需要软件,只需要ProtocolSlave、UART和BRAM。与MiniZedMaster一样,PS为模块提供时钟。
普通XDC
MiniZedMaster和Slave都使用MiniZed上的Pmod1连接到RS485Pmod。因此,两者的XDC文件是相同的。
set_property IOSTANDARD LVCMOS33 [get_ports {re[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports de]
set_property IOSTANDARD LVCMOS33 [get_ports rx]
set_property IOSTANDARD LVCMOS33 [get_ports tx]
set_property PACKAGE_PIN L15 [get_ports {re[0]}]
set_property PACKAGE_PIN M14 [get_ports de]
set_property PACKAGE_PIN L14 [get_ports rx]
set_property PACKAGE_PIN M15 [get_ports tx]
为RS485总线接线
RS484总线非常简单,但我们确实需要正确连接Pmod,如DigilentPmodRS485参考指南中所示。
RS485端子的两端需要用一个电阻端接,在PmodRS485上可以使用跳线安装或不安装。对于此应用,需要安装两个电阻器。
接线时,请小心为Pmod上的接收器连接回路。
硬件测试
使用在MiniZed主机上运行的软件应用程序,我们可以读取和写入MiniZed从机中的BRAM内存。然而,要了解它是如何工作的,我们最好通过查看总线上的波形来学习
逻辑TX引脚上来自主机的写入传输如下所示
相应的总线端如下所示-请注意末尾的0x06是确认。
主机上的逻辑RX信号上的RX引脚显示写入和写入确认。MiniZedMaster和Slave的设计都永久启用了RX
从MiniZedSlave读取的数据如下所示,其中数据表示由MiniZedMaster写入的递增计数。
在下面的波形中,可以在读取响应之前在总线侧观察到读取请求。
TX启用相对于TX数据的时序如下所示,请注意我们如何在预期回复时禁用TX路径。
探测MiniZedMaster和Slave上的不同TX使能显示了
结论
FPGA为许多工业应用提供了很好的解决方案,该项目展示了使用常用工业接口连接不同板和传输数据是多么容易。在这个应用程序中,数据速率为1Mb/s,可以实现高达16Mb/s或更快的线速率!
-
FPGA
+关注
关注
1629文章
21736浏览量
603260 -
RS485
+关注
关注
39文章
1159浏览量
82319 -
工业通信
+关注
关注
0文章
122浏览量
15549
发布评论请先 登录
相关推荐
评论