1. 程式人生 > >基於MFC的USB上位機開發(3)資料傳輸模組

基於MFC的USB上位機開發(3)資料傳輸模組

延伸閱讀:

基於MFC的USB上位機開發(1)概述

基於MFC的USB上位機開發(2)速度測試模組

基於MFC的USB上位機開發(3)資料傳輸模組

基於MFC的USB上位機開發(4)環路模組

基於MFC的USB上位機開發(5)下環路模組

目錄

1. 設計思路

1.1 傳送資料

1.2 接收資料

1.3 清空管道

2. MFC控制元件相關操作

2.1 Edit Control控制元件數值操作

2.2 使用時間命名

2.3 資料儲存

2.4 長陣列進行分行顯示

2.5 開啟資料夾

3. 功能測試

3.1 傳輸512位元組固定數值資料

3.2 傳輸512位元組遞增資料

3.3 傳輸混合固定數值資料

3.4 清空管道

3.5 開啟資料記錄

4. 參考


    本模組用於FPGA環路程式的除錯,在上位機視窗上包括兩個區域:資料控制區域和資料顯示區域。當FPGA需要讀取USB的資料時,上位機可向USB端傳送指定數目和數值或者512位元組遞增的資料,當FPGA往USB寫好資料時,上位機也可以手動接收來至USB的512位元組資料。上位機接收的資料不僅可以顯示在視窗上,還可以儲存至電腦本地檔案中。在FPGA環路除錯中,如果USB的FIFO管道內出現了非512位元組整數倍的無效資料,可使用清空管道命令來完成USB管道的清空,本模組的介面效果如下:

1. 設計思路

1.1 傳送資料

        由於FPGA與USB之間的資料線位數為16bit,為單位元組(8bit)的偶數倍,所以傳送資料的數量必須為偶數,其大小範圍是0~512。

        待發送的資料可以按指定數目和數值的方式進行發生,只要累積傳送512位元組,上位機端就可以收到512位元組資料。待發送的資料也可以是512位元組遞增資料,資料包含2個從0x 00遞增至0x FF的256位元組資料。

        傳送模組的程式流程圖如下,在上位機的Public區定義了變數Increment_req,用於判斷是否傳送遞增資料的請求。當按下“傳送指定資料”按鈕時,上位機會向USB傳送指定數目和大小的資料。如果按下“傳送512位元組遞增資料”按鈕,公共變數Increment_req會賦值true,上位機會向USB傳送512位元組遞增資料,在該次執行緒結束時Increment_req會賦值false。

1.2 接收資料

    接收模組的程式流程圖如下,當接收按鈕按下上位機立馬建立接收512位元組資料的執行緒,如果接收成功就將資料進行顯示和儲存,如果接收失敗就提醒先向FPGA傳送資料,與此同時將該按鈕禁用。512位元組資料的顯示是本環節的設計難點,涉及到陣列轉換為字串和字串多行顯示的知識點,詳細介紹請閱讀第2.4 節長陣列進行分行顯示。

1.3 清空管道

在進行FPGA環路程式碼除錯之前,是不清楚USB的端點EP6內有多少位元組資料未讀出,EP6的深度為2KByte,那麼USB管道內的無效資料數量NUM會介於0~2KByte之間。

(1)當NUM=2KByte時,上位機通過接收4次512位元組資料即可完成管道清空;

(2)當NUM<512Byte時,上位機需要通過判斷NUM的具體數字,來清空管道;

(3)當NUM介於512B和2KB之間時,需要進行1~3次512位元組資料接收再加一次無效資料位元組數的判斷,即可完成管道的清空。

清空管道的程式流程如下:

2. MFC控制元件相關操作

2.1 Edit Control控制元件數值操作

將上位機文字框數值賦給內部變數:UpdateData(true);

將內部變數值更新到上位機文字框內:UpdateData(false);

2.2 使用時間命名

有關C++時間結構體CTime的知識可以閱讀參考文章[1]和[2],下列程式碼中Y、m、d、H、M和S,依次表示年、月、日、時、分和秒,str字串交代了檔案的儲存路徑是“C:\USB_file_recevie”,儲存的檔名形式是file_20181219213250.hex。

CTime t=CTime::GetCurrentTime();
str=t.Format(_T("C:\\USB_file_recevie\\file_%Y%m%d%H%M%S.hex"));

2.3 資料儲存

    有關C++檔案操作的知識可以閱讀參考文章[3],本上位機僅用到檔案的開啟、清空、寫入和關閉等操作,具體程式碼如下:

mFile.Open(str,CFile::modeWrite|CFile::modeCreate);         //開啟檔案
mFile.SetLength(0);                                    //清空檔案
mFile.SeekToEnd();
mFile.Write(data,nLen);	                //向檔案內寫入512位元組資料
mFile.Flush();                         //強制將緩衝區資料寫入磁碟檔案						
mFile.Close();                         //關閉檔案

2.4 長陣列進行分行顯示

為了方便觀察接收到的512位元組資料,需要將資料進行分行顯示。上位機將資料按位元組分成32行16列,具體的實現方法如下方所示:

void CUSBprojDlg::Matrix_to_String(UCHAR * data_512)
{
	int i=0;
	int j=0;
	int line=1;	
	CString str=_T("line00:  ");
	CString tmp_str=_T("");
	for(i=0;i<512;i++)
	{
		tmp_str.Format(_T("%02X "),data_512[i]);	
		str+=tmp_str;
		if((j!=0)&&(j!=511)&&((j+1)%16==0)) 
		{
			str+=_T(" \r\n");
			tmp_str.Format(_T("line%02d:  "),line);
			str+=tmp_str;
			line++;
		}
		j++;
	}
	data_display +=str;
	data_display +=_T(" \r\n");
}

    程式碼的設計思路是,將512位元組陣列data_512分成32段,在每段的開頭新增line n:,n從0增至31。每個位元組的後面帶兩個空格,每16個位元組的後面新增換行符“ \r\n”。有關陣列轉換為字串的知識可以閱讀參考文章[4]和[5]。

2.5 開啟資料夾

void CUSBprojDlg::OnBnClickedOPEN_FOLDER()
{	
    ShellExecute(NULL, _T("open"), _T("C:\\USB_file_recevie"), NULL, NULL, SW_SHOWNORMAL);
}

3. 功能測試

3.1 傳輸512位元組固定數值資料

先向USB傳送512位元組0x FF

再向USB接收512位元組資料

3.2 傳輸512位元組遞增資料

先向USB傳送512位元組遞增資料

再向USB接收512位元組資料

3.3 傳輸混合固定數值資料

先向USB傳送510位元組0x 00和2位元組0x FF

再向USB接收512位元組資料

3.4 清空管道

        首先,模擬USB管道有無效資料的情況:向USB傳送10位元組0x 00。

        接著,向USB傳送512位元組0x 01,再接收512位元組資料

        由於USB的管道內有10位元組無效的資料0x 00,導致接收的512位元組資料的前10位元組發生了改變,如何解決以上現象呢,有以下兩種方法:

方法1:讓USB開發板重新上電,在電路啟動時USB的FIFO會自動清空。

方法2:使用上位機的清空管道按鈕,通過軟體的方式實現USB的FIFO清空。

        現對方法2進行驗證,先點選管道清空按鈕,接著再向USB傳送512位元組0x 02,最後接收512位元組資料。

        從上方資料可以發現USB管道內的10位元組0x 01已通過上位機軟體清空,所以接收的資料在數值上與上次傳送的資料保持一致。

3.5 開啟資料記錄

        點選“開啟資料記錄”按鈕,即可彈出資料的保持目錄,開啟的目錄路徑為“C:\USB_file_recevie”,和預設的路徑是一致的。每接收512位元組資料都會儲存在以時刻命名的hex檔案中,hex檔案可以使用UltraEdit軟體檢視。

4. 參考

[1] MFC中獲取系統當前時間GetCurrentTime用法 
https://blog.csdn.net/naibozhuan3744/article/details/78773780

[2] VC中CTime怎麼轉換成字串?

https://bbs.csdn.net/topics/60232871

[3] VC++檔案操作之最全篇(總結一下希望對大家有用) 

https://blog.csdn.net/u010258235/article/details/24477429

[4] MFC怎麼讓編輯框多行顯示文字內容

https://bbs.csdn.net/topics/390936461

[5] MFC在編輯框中顯示一個二維陣列 

https://blog.csdn.net/shufac/article/details/20497225