基于Spartan-6的高速數據采集、處理和實時傳輸研究
擇一種最佳的設計方案。表 1為不同抽取倍數下的帶寬和混疊衰減規格:
本文引用地址:http://www.j9360.com/article/201612/326826.htm最后確定選擇CIC2濾波器抽取倍數為15,CIC5抽取倍數為2,RCF抽取倍數為2就可以滿足系統設計的要求。
3.2.3 可變系數RCF濾波器參數設置
根據2.2.1節設計得到的RCF抽取倍數為30,可以根據式來計算得到抽取濾波器的抽頭數為150。

其中,為60MHz,
為15,
為CIC5濾波器抽取降速后的頻率也即2MHz,當輸入通道模式時單通道實模式時為1。對可變系數的RCF濾波器進行編程設置時需要先向地址0x30C寫入整數 149(
=59)。然后濾波器的響應
逐一寫入到地址0x000~0xFF中。這樣就完成了RCF寄存器的編程設置。
3.2.4 AD6620工作模式寄存器編程
對頻率變換單元、固定系數的CIC2和CIC5以及RCF濾波器變化進行編程設置后,要使AD6620正常工作還需要對其工作方式和相關寄存器進行配置。AD6620的工作方式主要由地址0x300H的寄存器中低四位決定,其中,bit0=1時系統處于軟復位狀態,bit0=0則處于正常狀態;bit1=1時系統處于雙通道實數輸入模式;bit2=1時系統處于單通道復數輸入模式;如果bit0~bit2都是0,那么系統處于單通道實數輸入模式;bit3=1/0為時鐘主從工作模式。因此,當各寄存器配置完成后需要將寄存器bit0拉低,也即置為0狀態使其脫離軟復位狀態,進入正常工作模式。另外,在本文中AD6620讀寫內部寄存器是采用的異步讀寫時序,數據輸出是并行16位輸出模式。 總的來說,采用FPGA實現AD6620初始化的過程如下:
1)首先判斷AD6620有沒有經過硬件復位,如果沒有經過硬件復位而又要實現系統復位,那么可以通過程序去編程地址0x300H的寄存器的bit0位置為1,使得AD6620處于軟件復位狀態,這樣就可以對非動態的寄存器進行相關編程;
2)對NCO單元、CIC2、CIC5濾波器的抽取倍數和系數進行編程,將相應的控制系數寫入相對應的地址寄存器中;
3)對RCF濾波器系數進行編程,分別向地址0x000H~0xFF中寫入這150個抽頭系數,剩下的寫入0。
4)對AD6620所有配置工作完成后,必須向地址0x300H的bit0寫入0,使其脫離軟復位狀態,這樣AD6620才可以在所配置工作方式下對輸入的數據進行處理。
4.實時數據傳輸模塊
基于USB2.0的數據傳輸設計主要包括以下幾個部分:(1)基于EZ-USB FX2的硬件電路設計(2)EZ-USB FX2系列器件CY7C68013A的固件程序(設置CY7C68013A工作模式、傳輸方式等,需要對其內部寄存器進行相關配置),主要通過Keil C51軟件進行開發。
4.1 實時數據傳輸部分的硬件設計
實時數據傳輸部分(USB2.0的數據傳輸)的硬件設計方案如圖10所示,USB模塊與FPGA間的連線如圖11所示。
在高速數據傳輸部分采用了Cypress公司的EZ-USB FX2 CY7C68013A芯片,采用單片USB 2.0外設可以避免用FPGA直接實現USB通信協議時可靠性低的問題。在數據采集、傳輸以及測試過程中,CY7C68013A作為從機,負責將FPGA發送給它的基帶數據,利用其16位SLAVE FIFO(關于SLAVE FIFO的傳輸示意圖如圖所示)將數據緩沖發送給上位機。在SLAVE FIFO數據傳輸中,上位機應用程序、固件程序和FPGA程序都非常關鍵,要配合好才能完成數據的高速數據傳輸。在這個系統中,FPGA起著主控制器作用,CY7C68013A則相當于一個從設備。具體的工作流程是:FPGA把接收過來的16位數字基帶信號發送給CY7C68013A,CY7C68013A以SLAVE FIFO的方式將這些數據緩沖,并以批量數據傳輸的方式發送給上位機,上位機接收到這些數據后加以存儲和顯示。
4.2 CY7C68013A的固件程序設計
固件程序是指運行在設備CPU中的程序,只有在該程序運行時,外設才能稱之為具有給定功能的外部設備。固件程序負責初始化單元,重新設置設備。主要包括設備描述符信息、設備功能代碼。設備描述信息描述USB設備的一半特性和配置,如設備類別、接口配置、VID和PID等。主機在設備列舉時要獲取USB設備的描述符,從而獲得設備的配置信息和相關驅動信息。用戶可以通過修改固件中的描述符來改變設備的特性。設備功能代碼有設備的功能需求決定。通信控制功能代碼執行主機請求分析處理和數據交換處理功能。
采用ARM公司的Keil C51 uVision4.02開發CY7C68013A的固件程序。為了簡化固件編程,CYPRESS提供了固件編程框架,在此基礎上添加我們所需要的配置代碼即可完成軟件編程。
復位上電時,固件先初始化一些全局變量,然后調用初始化函數ID_Init(),初始化設備一直到沒有配置的狀態和打開中斷,循環1s后枚舉,直到端點0接收到SETUP包退出循環,進入循環語句while,執行任務函數,函數包括:
(a)TD_POLL()用戶任務調度函數;
(b)如果發現USB設備請求,則執行對應的USB請求;
(c)如果發現USB空閑置位,則調用TD_Suspend()這個掛起函數,調用成功后則內核掛起,直到出現USB遠程喚醒信號,調用TD_Resume(),內核喚醒后重新進入while循環。
固件框架程序需要以下幾個文件:
(1)FX2.h:庫函數申明,以及變量、宏定義、數據類型定義;
(2)Fxregs.h:FX2LP寄存器頭文件;
(3)Fw.c:固件框架源文件;
(4)Periph.c:用戶調度函數、用戶可以修改,在不同的應用中文件名不一樣;
(5)Dscr.a51:USB描述符列表,用戶可以修改;
(6)Ezusb.lib:EZUSB庫文件;
(7)USBJmpTb.OBJ:中斷跳轉函數目標文件
這種情況下,需要在固件程序中,進行相應的修改。在SLAVE FIFO中,特別是自動傳輸(CY7C68013A單片機不干預數據傳輸),固件程序主要完成各個端口的初始化。因此我們要修改兩個地方:(1)USB設備描述符列表Dscr.a51,根據實際情況修改里面的端口數和傳輸方式等;(2)初始化函數void TD_Init(void)。在SLAVE FIFO這種方式下,設置EP2為4緩沖的輸出端口,EP6為4緩沖的輸入端口。
5. 上位機軟件設計
上位機應用程序是系統與用戶之間交流的接口,它通過通用驅動程序完成對外設的控制和通信。主機端應用程序負責向FX2的FIFO發送或者接收數據。本報告中采用的固件架構是EZ-USB FX2/FX2LP(CY7C68013, 驅動程序是Cyusb.sys。用Visual Studio2008軟件進行上位機開發,利用C++/MFC來開發基于對話框的應用程序,系統的主要功能模塊有:打開USB設備、復位USB設備、系統數據測試與顯示等。
在VS2008中建立一個MFC 單文檔/對話框應用程序后,在路徑項目中包含頭文件cyapi.h和cyapi.lib所在的路徑。然后手動導入cyapi.lib,注意是CV6_7的lib,不要導入BCB的。
開發USB應用程序的一般工作流程如下。
1)首先要創建一個USB設備對象
CCyUSBDevice *USBDevice = new CCyUSBDev(Handle);括號中的Handle是USB所關聯對象的句柄,一般在MFC中直接就是m_hwnd。
2)打開USB設備。
可以用到兩個函數open();isopen()這兩個都可以用來打開USB設備,isopen()還可以判斷能否獲得USB設備句柄,一般來說,如果只有一個USB設備連接,可以這樣打開:
USBDevice->open(0)//打開0號USB設備;如果要判斷,可以:
if(!USBDevice->open(0)) //打開失敗
{messagebox("USB未連接");}
或者if(!USBDevice->Isopen())
如果連接有多個USB設備,那么可以枚舉所有的USB,用到DeviceCount()函數;具體的可以參考cybulk的例子。執行USBDevice->DeviceCount()后,返回所連接的USB設備個數:
if (USBDevice->DeviceCount()) //保證至少有一個USB設備連接
{
for (i = 0; i DeviceCount(); i++) //枚舉所有USB設備
{
USBDevice->Open(i);//打開第i號USB設備
m_DeviceListComBox.AddString(USBDevice->DeviceName);//所選擇的當前設備名}
}
3)端點枚舉
在cybulk的例子中介紹了如何枚舉固件中使用的所有端點,也就是使用多個端點的情況,其枚舉步驟主要包括一下幾個端點:
(1)創建USB設備并打開該設備
CCyUSBDevice *USBDevice=new CCyUSBDevice(m_hWnd);//USB設備USBDevice->Open(0);//打開0號USB設備。
(2)獲取所用的端點數目
intepts = USBDevice->EndPointCount();
EndPointCount();函數返回當前所用的端點數+1,也就是包含了控制端點。例如在固件接口描述符Interface Descriptor中設置Number of end points項(第5項)的值為4,則epts的值為4+1=5。
(3)定義端點指針
CCyUSBEndPoint *endpt;CCyUSBEndPoint建立一個端點對象,可建立所有的端點類型,控制端點,bulk端點,ISO端點等;
(4)枚舉端點,并獲得其屬性:端點號,傳輸方向
for (i=1; i
{
endpt = USBDevice->EndPoints[i];//EndPoints-端點列表,最大16.EndPoints[0]指向控制端點(CCyControlEndPoint),未使用的端點設置為NULL。
if (endpt->Attributes == 2) // Bulk Attributes 判斷傳輸類型bulk,control,等。
{
sprintf(s, "0x%02x", endpt->Address);
if (endpt->Address & 0x80) //Address--判斷傳輸方向in or out 0x8_-in;0x0_-out
{
m_InEndptComBox.AddString(s); //最高位為8,in端點,添加到in組合框m_InEndptComBox.SetItemData(m_InEndptComBox.GetCount()-1,i);
else
{
m_OutEndptComBox.AddString(s); //否則,最高位為0,out端點,添加到out組合框m_OutEndptComBox.SetItemData(m_OutEndptComBox.GetCount()-1,i);
}}} 這樣,就完成了某個具體端點的選擇。如果只需要使用一個端點的話,那上面的代碼無疑就顯得冗長不夠簡潔了。僅使用一個端點,可以使用EndPointOf()函數,該函數直接使用指定的端點,返回其指針;例如,要使用端點2,in傳輸,那么,可以這樣:
CCyUSBDevice *USBDevice=new CCyUSBDevice(m_hWnd); //USB設備
USBDevice->Open(0); //打
評論