在工業應用中傳輸信息可能具有挑戰性。在這個項目中,讓我們看看我們如何使用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文章
21729瀏覽量
603010 -
RS485
+關注
關注
39文章
1156瀏覽量
82291 -
工業通信
+關注
關注
0文章
121瀏覽量
15548
發布評論請先 登錄
相關推薦
評論