2016年6月29日 星期三

MFC AfxBeginThread 使用方法

1.在主要functino的class中使用CWinThread宣告Thread指標。
class CMFCApplication1Dlg : public CDialogEx
{
public:
   CMFCApplication1Dlg(CWnd* pParent = NULL); // 標準建構函式
   CWinThread* pThread;
// 對話方塊資料
#ifdef AFX_DESIGN_TIME
   enum { IDD = IDD_MFCAPPLICATION1_DIALOG };
#endif

   protected:
   virtual void DoDataExchange(CDataExchange* pDX);
   ...
// 程式碼實作
protected:
   ...
}

2.定義MyThread(),必將要執行的工作寫在裡面,可搭配
在 MFC 上使用lusb-win32】一文中提到的Console _cprintf來觀察是否有進入MyThread()。
UINT MyThread(LPVOID LParam)
{
   _cprintf("Start MyThread...\n");
   ...
   while(1){
      _cprintf("Hello World!\n");
   }
   return(0);
}

3.在欲開啟MyThread的Dialog按鈕程式碼中創建Thread
void CMFCApplication1Dlg::OnBnClickedButton1()
{
   pThread = AfxBeginThread(MyThread, NULL);
   ...
}

4.使用TerminateThread關閉MyThread
void CMFCApplication1Dlg::OnBnClickedButton2()
{
   // TODO: 在此加入控制項告知處理常式程式碼
   TerminateThread(pThread->m_hThread, 0);
   _cprintf("Close MyThread............\n");

}


執行結果:
當按下Button1後,會一直執行MyThread()中的「_cprintf("Hello World!\n");」,按下Button2後可以看到確實將MyThread()給關掉,Console不再印出Hello World!!字串。

在 MFC 上使用lusb-win32

將lusb-win32導入MFC專案步驟:
1.建立MFC專案後,將"libusb.lib"與"libusb0.dll"丟到所建立的專案目錄下。
2.在標頭檔中加入"lusb0_usb.h"檔案,加入"#pragma comment(lib, "libusb")"至"lusb0_usb.h"或是專案主程式XXX.cpp中來link libusb.lib。
3.在專案主程式XXX.cpp中include "lusb0_usb.h"後,就可以開始撰寫你要的功能了。


MFC(VS2015 Community)中的Console printf
1.添加標頭檔
#include "io.h"
#include "fcntl.h"
#include "conio.h"

2.新增InitConsoleWindow()至主程式中
void InitConsoleWindow()
{
  int nCrt = 0;
  FILE* fp;
  AllocConsole();
  nCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),   _O_TEXT);
  fp = _fdopen(nCrt, "w");
  *stdout = *fp;
  setvbuf(stdout, NULL, _IONBF, 0);
}

3.在::OnInitDialog()初始化函數中添加InitConsoleWindow()
BOOL CUsbXSTM32F4xxDlg::OnInitDialog()
{
  CDialog::OnInitDialog();

  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  ASSERT(IDM_ABOUTBOX < 0xF000);

  CMenu* pSysMenu = GetSystemMenu(FALSE);
  if (pSysMenu != NULL)
  {
    ...
  }

  SetIcon(m_hIcon, TRUE); // 設定大圖示
  SetIcon(m_hIcon, FALSE); // 設定小圖示
  InitConsoleWindow();

  return TRUE; // 傳回 TRUE,除非您對控制項設定焦點
}

4.由於VS2015使用網路上printf的方式無法輸出到console上,有另外找到解決方法,加入"conio.h"用_cprintf可以解決無法輸出到console上的問題。

2016年6月21日 星期二

MinGW+MSYS 使用 libusb-win32 使PC與MCU通信

本篇文章將介紹如何使用libusb-win32來撰寫USB開發程式

準備軟體:
libusb-win32(1.2.6.0)
MinGW&MSYS: http://www.mingw.org/

MinGw教學:
http://shunyuan-chou.blogspot.tw/2010/02/2-mingw-windows-gnu.html

範例程式:
Usblib-win32-HID

下載libusb-win32-bin-1.2.6.0.zip解壓縮後,可以看到如下圖中有多個目錄。
當編譯程式告知缺少libusb0.sys或是libusb0.dll時,可至bin資料夾中選擇符合你環境的設定檔。

lib目錄下有不同compiler可以使用的library,由於本實驗使用gcc,所以將gcc下的libusb.a複製到撰寫程式的目錄下。


首先在C:\MiGW 下建立Project\HID,將libusb-win32-bin-1.2.6.0中的example與include複製到HID目錄下,libusb.a & libusb0.dll複製到example目錄下。



將bulk.c中定義的MY_VIDMY_PID更改為你要測試USB device 的參數。

編譯指令:
gcc -l ../include -g -c bulk.c -o bulk.o
gcc -g bulk.o libusb.a -o USB.exe

編譯完後可以執行USB.exe,測試是否有抓到USB device。

成功開啟USB裝置後,就可以使用lusb0_usb.h中的function來與MCU溝通拉。

int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);

int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);

int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);

2016年6月16日 星期四

Bus Hound USB Get_Descriptor Command之分析

使用Bus Hound 發送Get_Descriptor command

目前先將實驗解果稍作分析,未來對USB有更深入的了解後,有機會在更新這部分的資料。

  • Cmd: 80 06 00 01 00 00 FF 00

Value: 00 01
USB回傳訊息:會回傳USB的Device Descriptor,裡面包含了VID&PID的資料。

Device Descriptor 內容可對照usb_2.0 spec 表9-8。


  • Cmd: 80 06 00 02 00 00 FF 00
Value: 00 01
USB回傳訊息:會回傳HID configuration descriptor,可以看出此裝置是甚麼樣的device(Mouse, Keyboard...)。
HID Configuration descriptor的架構如下
Configuration descriptor
...Interface descriptor
......HID descriptor
.........Endpoint descriptor (for HID interrupt IN Endpoint)
.........Optional Endpoint descriptor (for HID interrupt Out Endpoint)

詳細內容可參考usb_2.0 spec 
9.6.3 Configuration
9.6.5 Interface
9.6.6 Endpoint


  • Cmd: 80 06 01 03 00 00 FF 00~80 06 05 03 00 00 FF 00
此command可以取得儲存在USB的string。

2016年6月15日 星期三

STM32F4XX USB 透過 Bus Hound 存取 HidRaw Device

本篇參考假濕汀的Blogger,並修改文章中所提供的範例程式,透過Bus Hound監聽軟體來驗證傳輸資料是否正確。

由於原作者範例只能將hidraw中的資料由Device端送至PC端,無法由PC端送資料至Device端,因此這裡將介紹如何解決此問題,由於USB這邊是第一次接觸,還有很多不了解的地方,有問題還請各位前輩可以提出來。

假濕汀的Blogger:
http://iamjustinwang.blogspot.tw/2015/11/stm32f401411-hid-testkeyboard-mouse.html
程式連結:
STM32FXXX_HID

修改部分:

  • usbd_hid_core.c:增加USB_HID_DataOut function





  • USBD_HID_CfgDesc array中需修改項目

原程式中只有一個input Endpoint,因此須改改interface中定義Endpoint的數量。

增加Output Endpoint Descriptor


  • main.c


  • Bus Hound驗證:
    • 1.點選interrupt Out
    • 2.輸入要送至Device端的資料與資料大小
    • 3.點選Run,將資料送出
由上圖可觀察到,送出資料後,讀出hidraw data為PC端所輸入的資料,我們已成功將資料送至Device端。