2019年10月28日 星期一

Hinet 網頁系列 --- USB DIY 系列(十二)---USB DIY 講座 (十)應用軟體簡介

(補充說明:如果你問我:比較喜歡寫軟體呢?還是寫韌體?其實我是比較喜歡搞"系統"。

因為沒有偏好軟體或韌體,其實都是工作的一部分,在寫韌體時,可以自己寫一點軟體,

是可以協助完成韌體的開發與除錯。畢竟USB 多少還是都跟PC 端的應用軟體有關,可以自己

寫軟體是可以很快的驗證自己所定義的通訊協定是否正常,而且現在搞韌體應該沒有人還在用

ICE 那一種一步一步 Trace 程式的方式吧~現在的單晶片常常劈哩啪啦,一下子就跑了一大堆

的東西出來了,除非你是像我以前在幫忙Debug 八核心MCU 開發過程中,還真的需要 Step

by Step 的看東西,否則,現在工程師真的很難有那麼多美國時間跟你這麼玩的。

至於系統應用韌體,最討厭的倒也不是這些東西,而是後來發展過程中,你突然發現,

原來有很多東西可能要做到向前兼容,剛開始也只是覺得反正老闆或長官急著要東西而已,

就隨隨便便的搞個初版就給了,結果沒想到東西後來還需要擴充與升級,結果這下就面臨

命令或通訊協定需要新舊版本兼容,這下就昏倒了。沒辦法,大家都習慣邊上機寫程式,

邊自己定義命令組或通訊協定...沒有養成事先規劃工作,所以啦~如果你要我從這些文章

中,有哪些啟發的教訓?我想最重要的一點就是這一個吧。真的~好技術或好東西是值得

一輩子珍藏的~但先決條件就是要隨時可以升級與維護的...)

>>>>>>>>>>++++++++++++++++++++++++++++++++++
既然上次都提到有關在PC端的驅動程式架構了,我就稍微介紹一下PC端的應用程式吧。

說真的~怎麼寫驅動程式?我不會。但目前我的所有最上層應用程式,可都是我自己寫的。

當然,以我 USB DIY 來說,我是認為這樣子已經可以在USB 世界裡,作我想作的東西了。

以前剛學PC的應用程式時,也是為了利用PC周邊的東西,來作一些東西。只是那時只有

RS232 而已。而我也不會寫 C語言。後來,也是人家給我一個範例程式

現在要找範例程式就容易多了,因為網路上的東西很多了,只不過是人家講的一句笑話:

網際網路裡,什麼都有,只有您要的沒有?!就算有,您也找不到!!您學USB 是不是

也有這種感覺?!那您來我的網站就對了啊!哈~哈~),自己就一步一腳印慢慢的摸~

雖然寫出來的程式不像專業人是寫得那麼漂亮,卻自己覺得怡然自得了。

畢竟我們寫的還是跟周邊硬體有相關的。重點是在這些周邊控制的東西。

而非是那花俏的程式吧。

        首先,我先 說明一下我使用的開發環境吧:這個開發環境也不是我挑的~是人家給我的

範例程式!!因為不會寫 USB 的驅動程式,只好回頭找老同事幫忙(因為當初作計畫時

的團隊已經鳥獸散了,幸好我的人緣還不錯, 我把我的來意與用意說明之後,我們當初寫

驅動程式與軟體的工程師就三兩下給我一版~就說:以後就自求多福了,但對我來說:

已經恩同再造了,又什麼好要求的呢?!)。我的上層應用程式開發環境是 Microsoft Visual 

C++ 6.0 ~您要不要用MFC~就看您自己的所好了。在此之前我所曾使用的是 DOS 時代的 

Turbo C 。那時也不知道要從何學起?就找一個實例的來親自作一次!就學起來了。

但是,這次接觸 Visual C++ 時,人家可好心的警告我說:MFC 至少要磨個兩三個月以上,

您才會慢慢的進入狀況!年紀一大把,為什麼我還那麼『歹命』啊?但是我很慶幸我還是

走過了!(雖然之前一度還是回到傳統的 C的開發觀念~但是對那些視窗的東西,

實在是喔~ 只能說:年紀真的太大了!)

        若是您是用 VB 或其他的,不好意思!真的我已經沒那個體力了。或是,您也覺得人家

都是用 C 語言,前輩也跟我說:對一些有關周邊控制的東西還是也C語言為主~

而我到底要不要換開發環境呢?!您就會跟我上述的心情一樣了。或許,您看了我這篇

文章後,您內心的掙扎會更大吧。

        基本的架構跟我前一章節所述的軟體架構有點雷同:


所以,我們的軟體大哥就給我一個 GT68XX.SYS (經千錘百鍊驗證過的驅動程式)配上

一組 GUID 定義檔(好像只要不同的驅動程式搭配不同的GUID定義檔就不怕同一棵IC或

平台會相衝了,這點我也不懂,我大概只知道微軟在視窗操作環境中都是靠GUID再做判別

區分的!),再給個Library 檔 加上一個簡單的 OpenDriver 的原始碼~就教我自求多福了!

唉~這樣子就完全解決我在USB 開發上在PC端的重要瓶頸了。
        
怎麼用?很簡單,也是看圖:(若不會在Visual C++ 中開 Project 的我也沒辦法教您了!)


這是我做ATMEL ISP 燒錄器的範例程式。

那一個Library到那裡去了?! 也是看圖:


接下來,您就可以大大方方,放心地寫您的上層的應用程式了!啊~寫USB 的應用程式

這麼簡單?!有沒有搞錯?!哈~哈~套一句人家說的:好的老師帶著您上天堂;

不好的老師,帶您住套房!您一定覺得我在乎籠您。但您看了我這麼多文章,您還會這樣子

認為嗎?!所以我說為什麼老是要用那種:用起來總是會有那麼一點提心吊膽的HID 驅動

程式呢? 您一定對我所說的那的 Opendriver.CPP 原始碼很有興趣吧!沒關係,您就用力

下載來看吧!不過,也真的看不出什麼?!我一定要搞得懂嗎?!對我來說:

我沒那個精力。作USB 周邊比較實際呢?還是搞得懂視窗程式來龍去脈比較重要呢?!

對不起!我的網站標榜的是USB DIY 啊!

            用力下載-->  opendriver.cpp  及 opendriver.h

            (PS : 看不懂得不要問我,人家我們軟體大哥不是說了嗎:自求多福!!)

        應用程式怎麼寫?那更簡單了:以下就是透過 Endpoint 0 (就是Setup Token )下一組

 64 Bytes 資料下去(就是下一個命令兼帶參數,讓韌體去控制LED 的閃爍)!

並讀回韌體的相關數據 :

void CUSBAISPDlg::USB_DEVICE_SET_LED_CONTROLLER(UCHAR BlinkingCNT, UCHAR LEDCR)
{
      int i;

      hDEV = open_dev();
      if(hDEV!=INVALID_HANDLE_VALUE)
      {
        //for(i=0;i<64;i++) iobuffer[i]=0x00;
        //----
        //------ LED Controller
        //----
        //---- Command set = 0x81
        //---- arg_0 : Blinking counter , Default = 0x30
        //---- arg_1 : LED control
        // bit 1: RED ON
        // bit 2: GREEN ON
        // bit 3: BLUE ON
        // bit 4: Global Blinking
        // bit 5: RED Blinking
        // bit 6: GREEN Blinking
        // bit 7: BLUE Blinking
        // if Global Blinking is ON, then will ignor the LED ON !!
        for(i=0;i<8;i++) STICommandString[i]=0x00; // reset the parameters
        STICommandString[0]=0x87;        // LED Control Command
        STICommandString[1]=BlinkingCNT; // Blinking Speed !
        STICommandString[2]=LEDCR;       // LED Control Register
        USB_DEVICE_SEND_STI_COMMAND(STICommandString);

        CloseHandle(hDEV);
        hDEV=INVALID_HANDLE_VALUE;
      }
}

 
其中:

USB_DEVICE_SEND_STI_COMMAND(STICommandString) 就是:

UCHAR CUSBAISPDlg::USB_DEVICE_SEND_STI_COMMAND(UCHAR *STICommandString)
{
        int i;
        BOOL success;
        iobuffersize = 0x40;
         for(i=0;i<8;i++)
                iobuffer[i]=STICommandString[i];

        // 
 利用 Endpoint 0 的Setup Out Token 下一組 64 Bytes 的資料給 韌體
        success = DeviceIoControl(hDEV,
                                  IOCTL_GrandTech_Scanner_STI_Send_Command,
                                  iobuffer,
                                  iobuffersize,
                                  iobuffer,
                                  iobuffersize,
                                  (unsigned long *)&nBytes,
                                   NULL);
        // 利用 Endpoint 0 的Setup In Token ! 讀回 USB Device 的 64 Bytes 資料!
        success = DeviceIoControl(hDEV,
                                  IOCTL_GrandTech_Scanner_STI_Get_Status,
                                  iobuffer,
                                  iobuffersize,
                                  iobuffer,
                                  iobuffersize,
                                  (unsigned long *)&nBytes,
                                    NULL);
        return (iobuffer[1]);
}
很簡單吧~還是老話一句:我為什麼要用HID 驅動程式呢?!哈~哈~

  至於 Bulk In 與 Bulk Out 我好像有舉過例子吧?!再寫一次寫沒關係:

Bulk In :
HANDLE hRead=INVALID_HANDLE_VALUE;
              hRead = open_file(inPipe);

        if(hRead==INVALID_HANDLE_VALUE)
        {
            ///----
            MessageBox("Open in pipe Error",NULL,MB_OK);
            return ;
        }

        BOOL success;

        success = ReadFile(hRead,
                           Raw_Buffer,
                           nLength,   // 
<---- 一次要多少就有多少!!
                           &nBytesRead,
                           NULL);

        CloseHandle(hRead);
 
Bulk Out :
hWrite = open_file(myoutpipe);
        if(hWrite==INVALID_HANDLE_VALUE)
        {
            MessageBox("Open Out Pipe Error",NULL,MB_OK);
            return ;
        }
        success = WriteFile(hWrite,
                            fwbuf,
                            nLength, // 
<-- 一次要傳多少出去隨您高興!
                            &nBytesRead,
                            NULL);

        CloseHandle(hWrite);
 

    好了~您要我寫什麼結論呢?!要不要套個股市名嘴張老師的一段話?

哈~哈~

還是老話一句:多給掌聲鼓勵鼓勵吧!否則,我真的不太想寫有關USB 的東西了。

    謝謝您們!下台一鞠躬。

沒有留言:

張貼留言