Tài liệu hướng dẫn tự làm thiết bị USB (Phần 3)

Viết chương trình C# giao tiếp với thiết bị USB

pdf11 trang | Chia sẻ: franklove | Lượt xem: 2422 | Lượt tải: 3download
Bạn đang xem nội dung tài liệu Tài liệu hướng dẫn tự làm thiết bị USB (Phần 3), để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 1 - Phҫn 3: ViӃt Chѭѫng Trình C# giao tiӃp vӟi thiӃt bӏ USB 1. Tҥo Driver cho thiӃt bӏ và tҥo các thѭ viӋn hàm giao tiӃp USB: Công viӋc ÿҫu tiên mà bҥn phҧi làm vӟi WinDriver ÿӇ tҥo Driver và các thѭ viӋn phҫn mӅm cho chѭѫng trình PC cӫa bҥn. Các bѭӟc tiӃn hành bao gӗm: 1. *ҳn thiӃt bӏ cӫa bҥn vào cәng USB trên máy tính computer: 2. Chҥy DriverWizard và chӑn thiӃt bӏ cӫa bҥn: hình 1: Mӣ hoһc tҥo mӝt WinDriver Project Chӑn thiӃt bӏ cӫa bҥn trong list cӫa WinDriver: NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 2 - Chӑn phát ra file Driver và ÿánh tên cho thiӃt bӏ cӫa bҥn: TiӃp tөc chӑn next ta ÿѭӧc: 7ҥi ÿây bҥn có thӇ kiӇm tra viӋc truyӅn nhұn qua USB xem thiӃt bӏ cӫa bҥn ÿã hoҥt ÿӝng chѭa. ViӋc tiӃp theo là tҥo ra giao diӋn ban ÿҫu và thѭ viӋn trên C#. Click và biӇu tѭӧng Generate Code và chӑn ngôn ngӳ mà bҥn sӱ dөng, hiӋn nay ngôn ngӳ C# thông dөng vӟi nhiӅu ngѭӡi và có nhiӅu tiӋn ích hѫn so vӟi VB nên ӣÿây tôi chӑn nhѭ sau: Công viӋc còn lҥi chӍ là OK và chӡ máy chҥy hihi. NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 3 - Chҥy Project trên Visual Studio 2005 bҥn có thӇ thҩy WinDriver ÿã tҥo cho ta Pӝt giao diӋn ban ÿҫu ÿӫÿӇ sӱ dөng các giao tiӃp USB, bҥn có thӇ sӱ dөng luôn giao diӋn này ÿӇ thӵc hiӋn theo Project cӫa bҥn: Chú ý rҵng bҥn phҧi Project/ Set as Startup Project trѭӟc ÿã. Nhѭng ÿӇ giúp cho ngѭӡi mӟi hӑc có thӇ hiӇu ÿѭӧc mӝt cách nhanh chóng tôi xin tӵ tҥo mӝt giao diӋn khác ÿѫn giҧn ngҳn gӑn hѫn bҵng viӋc sӱ dөng các thѭ viӋn mà WinDriver vӯa tҥo ra cho chúng ta. Ĉó là hai thѭ viӋn project_usb_4550_lib.dll (thѭ viӋn này do ta ÿһt nó cùng vӟi tên Project khi tҥo ra) và wdapi_dotnet921.dll hai thѭ viên này chӭa các lӟp và các ӫy quyӅn rҩt Kӳu ích giúp cho viӋc quҧn lý và thӵc hiên giao tiӃp bҵng USB. Công viӋc tiӃp theo cӫa chúng ta là hãy tam quên ÿi cái giao diӋn mà WinDriver Yӯa tҥo ra ӣ trên, và bҳt tay vào tҥo mӝt giao diӋn cӫa chính chúng ta. Vӟi phѭѫng châm càng ÿѫn giҧn càng tӕt nên hѭӟng dүn này tôi chӍ tҥo mӝt giao diӋn chӍ vӟi 2 Button và 2 textBox dùng ÿӇÿLӅu khiӇn nhѭ sau: NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 4 - 9ұy là song bѭӟc ÿҫu tiên, bѭӟc tiӃp theo là add 2 thѭ viӋn ӣ trên vào trong project cӫa mình và nghiên cӭu cách sӱ dөng chúng. NӃu bҥn add thành công thì Eҥn sӁ thҩy chúng nhѭ sau: Ta hãy xem chúng có nhӳng gì ( viӋc sӱ dөng chӫ yӃu trên thѭ viӋn project_usb_4550_lib.dll): Thѭ viӋn này chӭa 4 uӹ quyӅn (delegates) dành ÿӇ tҥo các sӵ kiӋn quan trӑng Yӟi bus USB và 4 lӟp, trong ÿó 3 lӟp ÿӇÿLӅu khiӇn thiӃt bӏ USB và mӝt lӟp ÿӇ NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 5 - quҧn lý danh sách các thiӃt bӏ USB khác nhau ÿѭӧc gán vào PC. Chúng ta hãy quan sát cө thӇ hѫn vӟi các uӹ quyӅn và các lӟp này: - 8ӹ quyӅn D_USER_ATTACH_CALLBACK Vӱ dөng ÿӇ gán sӵ kiӋn có thiӃt bӏ USB thích hӧp gҳn vào bus USB vӟi mӝt hàm callback do bҥn tҥo ra thѭӡng là khӣi tҥo viӋc truyӅn nhұn dӳ liӋu. - 8ӹ quyӅn D_USER_DETACH_CALLBACK Ĉѭӧc sӱ dөng ÿӇ gán sӵ kiӋn thiӃt bӏ USB ÿã ÿѭӧc tháo ra vӟi mӝt hàm gӑi lҥi do bҥn xây dӵng thѭӡng là thông báo cho nguӡi sӱ dөng vӅ viӋc Disconnect và kӃt thúc viӋc truyӅn nhұn - 8ӹ quyӅn D_USER_TRANSFER_COMPLETION khá hӳu ích vì nó sӁ gán sӵ kiӋn truyӅn nhұn kӃt thúc vào mӝt hàm xӱ lý ÿӑc viӃt dӳ liӋu usb do bҥn xây dӵng. - 8ӹ quyӅn D_USER_POWER_CHANGE_CALLBACK ít ÿѭӧc sӱ dөng Kѫn vì nó liên quan ÿӃn viӋc báo ÿӝng thay ÿәi nguӗn trên bus USB, bҥn có thӇ Wұn dөng ÿӇ thӵc hiӋn các biӋn pháp bҧo ÿҧm cҳt nguӗn bus USB khi có sӵ cӕ. - /ӟp KEY_USB_Device chӭa các hàm ÿӇ thӵc hiӋn viӋc cài ÿһt cҩu hình khác nhau cho thiӃt bӏ USB hay hàm ÿӑc các sӕ hiӋu VP, IP và hàm theo dõi trҥng thái truyӅn nhұn cӫa thiӃt bӏ: - /ӟp KEY_USB_DeviceManager thӵc hiӋn viӋc quҧn lý thiӃt bӏ USB và YӅ sӕ lѭӧng thiӃt bӏ USB ÿѭӧc gҳn vào: - /ӟp KEY_USB_Pipe có sӕ lѭӧng hàm tѭѫng ÿӕi lӟn và chuyên dөng ÿӇ ÿӑc viӃt dӳ liӋu kiӇm tra trҥng thái truyӅn nhұn, kiӇm soát viӋc khӣi ÿӝng và Gӯng các ÿѭӡng ӕng… - Lӟp Pipe_list thӵc hiӋn quҧn lý các ÿѭӡng ӕng vào ra cӫa thiӃt bӏ. 7ұp các hàm này khá linh hoҥt và ÿҫy ÿӫ cho mӑi ӭng dөng USB và bҥn cNJng không cҫn phҧi tìm hiӇu kƭ tҩt cҧ các hàm ÿó vì chúng ta chӍ cҫn làm viӋc vӟi Pӝt sӕ hàm nhҩt ÿӏnh là ÿӫÿӇ giao tiӃp. Bây giӡ là ÿӃn công viӋc khó nhҩt ÿây, ta phҧi viӃt code làm sao cho khi gҳn thiӃt bӏ vào thì nó phҧi nhұn ÿѭӧc và thӵc hiӋn truyӅn phát dӳ liӋu. NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 6 - Ý tѭӣng cӫa tôi là dùng Button1(tên là btwrite) ÿӇ thӵc hiӋn viӋc truyӅn dӳ liӋu ÿѭӧc lҩy trong textBox1(tên là txttrans) tӯ PC xuӕng VĈK, Button2(btread) dùng ÿӇ lҩy dӳ liӋu tӯ VĈK lên PC hiӇn thӏӣ textBox2(txtLog). 9Ӆ thuұt toán thӵc hiӋn chѭѫng trình chúng ta chӍ hҥn chӃ 3 chӭc năng cѫ bҧn là ÿӑc, viӃt dӳ liӋu và phát hiӋn thiӃt bӏ gán vào hay tháo ra (hai sӵ kiӋn nhұn biӃt thiӃt bӏÿӅu ÿѭӧc hiӇn thӏ trên txtLog). Phҫn khai báo USING cӫa chѭѫng trình chúng ta cҫn mӝt sӕ khai báo nhѭ sau: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using Jungo.wdapi_dotnet; //sӯ dӧng thѬ viӉn wdapi_dotnet using Jungo.project_usb_4550_lib; //sӯ dӧng thѬ viӉn project_usb_4550_lib using wdu_err=Jungo.wdapi_dotnet.WD_ERROR_CODES;//sӯ dӧng viӉc khai báo lәi using DWORD = System.UInt32; using WORD = System.UInt16; using UCHAR = System.Byte; phҫn khai báo các biӃn cӫa form chính chúng ta thӵc hiӋn mӝt sӕ khai báo hàng biӃn và tҥo các ÿӕi tѭӧng sau: private const string DEFAULT_LICENSE_STRING = "6C3CC2CFE89E7AD04238DF2EF24449E848CDC187.NguyenNgocHung"; // TODO: If you have renamed the WinDriver kernel module (windrvr6.sys), // change the driver name below accordingly private const string DEFAULT_DRIVER_NAME = "windrvr6"; private const WORD DEFAULT_VENDOR_ID = 0x04D8; private const WORD DEFAULT_PRODUCT_ID = 0x0101; public const DWORD TIME_OUT = 30000; private PROJECT_USB_4550_DeviceManager uDevManager; //khai báo khӡi tңo viӉc quҥn lý ÿӓi tѬӥng USB private PROJECT_USB_4550_Device usb_device; //khai báo ÿӓi tѬӥng USB private PROJECT_USB_4550_Pipe usb_pipe_trs; //khai báo ÿӓi tѬӥng ӓng truyӃn private PROJECT_USB_4550_Pipe usb_pipe_rev; //khai báo ÿӓi tѬӥng ӓng nhүn private delegate void D_ATTACH_GUI_CALLBACK(PROJECT_USB_4550_Device pDev); //khai báo өy quyӃn thông báo thiӁt bӍ gұn vào private delegate void D_DETACH_GUI_CALLBACK(PROJECT_USB_4550_Device pDev); //khai báo өy quyӃn thông báo thiӁt bӍ tháo ra delegate void safeLogTextCallBack(string sMsg); //khai báo өy quyӃn phӧc vӧ hiӅn thӍ Chúng ta ÿã có 1 ÿӕi tѭӧng quҧn lý USB, 1 ÿӕi tѭӧng thiӃt bӏ USB, 2 ÿӕi tѭӧng ÿѭӡng ӕng TRANSFER và RECEIVER, các kӃt nӕi, khai báo driver ÿLӅu khiӇn và các uӹ quyӅn cҫn thiӃt. TiӃp theo chúng ta sӁ xây dӵng các hàm cӫa form theo các sӵ kiӋn chính. Sӵ kiӋn ÿҫu tiên chúng ta cҫn quan tâm là “form load” vì nó xҭy ra ÿҫu tiên trong chuӛi sӵ kiӋn vì vұy có thӇ tұn dөng ÿӇ khӣi tҥo mӝt Vӕ biӃn, ÿӕi tѭӧng cho chѭѫng trình. private void form_main_Load(object sender, EventArgs e) { // ÿăng ký hai hàm sӳ kiӉn ATTACH_CALLBACK & DETACH_CALLBACK NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 7 - D_USER_ATTACH_CALLBACK dDeviceAttachCb = new D_USER_ATTACH_CALLBACK(UserDeviceAttach); D_USER_DETACH_CALLBACK dDeviceDetachCb = new D_USER_DETACH_CALLBACK(UserDeviceDetach); //khӡi tңo ÿӓi tѬӥng quҥn lý thiӁt bӍ USB uDevManager = new PROJECT_USB_4550_DeviceManager(dDeviceAttachCb, dDeviceDetachCb, DEFAULT_VENDOR_ID, DEFAULT_PRODUCT_ID, DEFAULT_DRIVER_NAME, DEFAULT_LICENSE_STRING); } Hàm 2 callback xӱ lý 2 sӵ kiӋn Attacth và Detach theo cѫ cҩu trung gian ÿѭӧc Jӑi ÿӃn 2 hàm UserDeviceAttach & UserDeviceDetach ÿӇ khӣi tҥo các ÿӕi Wѭӧng AttachCb và DetachCb . Trong hàm này còn thӵc hiӋn viӋc khӣi tҥo thiӃt bӏ USB và hai ÿѭӡng ӕng TRANSFER & RECEIVER. private void UserDeviceAttach(PROJECT_USB_4550_Device pDev) { D_ATTACH_GUI_CALLBACK AttachCb = new D_ATTACH_GUI_CALLBACK(DeviceAttachGuiCb); // khӡi tңo thiӁt bӍ USB usb_device = pDev; // khӡi tңo ÿѬӟng ӓng nhүn và truyӃn usb_pipe_rev = (PROJECT_USB_4550_Pipe)usb_device.GetpPipesList()[1]; usb_pipe_trs = (PROJECT_USB_4550_Pipe)usb_device.GetpPipesList()[2]; Invoke(AttachCb, new object[] {pDev}); } Và: private void UserDeviceDetach(PROJECT_USB_4550_Device pDev) { D_DETACH_GUI_CALLBACK DetachCb = new D_DETACH_GUI_CALLBACK(DeviceDetachGuiCb); Invoke(DetachCb, new object[] { pDev }); } Các hàm DeviceAttachGuiCb & DeviceDetachGuiCb chӍ là các hàm hiӇn thӏ trҥng thái thiӃt bӏ gҳn vào hay tháo ra. private void DeviceAttachGuiCb(PROJECT_USB_4550_Device pDev) { TraceMsg("Found new device\r\n"); TraceMsg("Your new device is installed and ready to use\r\n"); } private void DeviceDetachGuiCb(PROJECT_USB_4550_Device pDev) { TraceMsg("Your device has detached\r\n"); } ĈӇ thuұn lӧi cho viӋc hiӇn thӏ trҥng thái chѭѫng trình chúng ta nên bә xung mӝt Vӕ hàm ÿLӅu khiӇn viӋc xuҩt thông báo ví dө 3 hàm dѭӟi ÿây: private void SafeLogText(string sMsg) { // InvokeRequired compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (txtLog.InvokeRequired) { NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 8 - safeLogTextCallBack cb = new safeLogTextCallBack(SafeLogText); this.Invoke(cb, new object[] { sMsg }); } else { txtLog.AppendText(sMsg); } } public void TraceMsg(string sMsg) { SafeLogText(sMsg); } Bây giӡ ta bҳt tay vào viӋc xây dӵng hàm dùng ÿӇ truyӅn nhұn dӳ liӋu. Khi nhҩn vào button write thì thӵc hiӋn truyӅn mӝt byte xuӕng VĈK: private void btwrite_Click(object sender, EventArgs e) { SingleTransfer(); } Hàm SingleTransfer();ÿӇ thӵc hiӋn viӃt sӁ lҩy 1 byte ÿã nhұp vào txttrans và chuyӇn sang dҥng byte ÿӇӣ trong buffer sau ÿó gӑi hàm truyӅn không ÿӗng bӝ: usb_pipe_trs.UsbPipeTransferAsync(false, 0, buffer, dwBuffSize, TIME_OUT, new D_USER_TRANSFER_COMPLETION(Transfer_trs_Completion)); Khi nhҩn vào button read thì thӵc hiӋn nhұn mӝt byte tӯ VĈK lên PC và hiӇn thӏ ra txtLog. private void btread_Click(object sender, EventArgs e) { SingleReceiver(); } Hàm SingleReceiver(); tѭѫng tӵ nhѭ hàm SingleTransfer();ÿӇ thӵc hiӋn viӋc nhұn dӳ liӋu vào bӝÿӋm: usb_pipe_rev.UsbPipeTransferAsync(true, 0, buffer, dwBuffSize, TIME_OUT, new D_USER_TRANSFER_COMPLETION(Transfer_rev_Completion)); Các hàm Transfer_trs_Completion & Transfer_rev_Completion thӵc hiӋn viӋc thông báo hoàn thành truyӅn hoһc nhұn. Hàm DisplayHexBuffer ÿӇ hӛ trӧ viӋc hiӇn thӏ giá trӏ thâp lөc phân. Sau ÿây là toàn bӝ mã cӫa chѭѫng trình: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using Jungo.wdapi_dotnet; using Jungo.project_usb_4550_lib; using wdu_err = Jungo.wdapi_dotnet.WD_ERROR_CODES; using DWORD = System.UInt32; NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 9 - using WORD = System.UInt16; using UCHAR = System.Byte; namespace project_usb_4550 { public partial class form_main : Form { private const string DEFAULT_LICENSE_STRING = "6C3CC2CFE89E7AD04238DF2EF24449E848CDC187.NguyenNgocHung"; private const string DEFAULT_DRIVER_NAME = "windrvr6"; private const WORD DEFAULT_VENDOR_ID = 0x04D8; private const WORD DEFAULT_PRODUCT_ID = 0x0101; public const DWORD TIME_OUT = 30000; private PROJECT_USB_4550_DeviceManager uDevManager; private PROJECT_USB_4550_Device usb_device private PROJECT_USB_4550_Pipe usb_pipe_trs; private PROJECT_USB_4550_Pipe usb_pipe_rev; private delegate void D_ATTACH_GUI_CALLBACK(PROJECT_USB_4550_Device pDev); private delegate void D_DETACH_GUI_CALLBACK(PROJECT_USB_4550_Device pDev); delegate void safeLogTextCallBack(string sMsg); public form_main() { InitializeComponent(); } private void form_main_Load(object sender, EventArgs e) { D_USER_ATTACH_CALLBACK dDeviceAttachCb = new D_USER_ATTACH_CALLBACK(UserDeviceAttach); D_USER_DETACH_CALLBACK dDeviceDetachCb = new D_USER_DETACH_CALLBACK(UserDeviceDetach); uDevManager = new PROJECT_USB_4550_DeviceManager(dDeviceAttachCb, dDeviceDetachCb, DEFAULT_VENDOR_ID, DEFAULT_PRODUCT_ID, DEFAULT_DRIVER_NAME, DEFAULT_LICENSE_STRING); } private void UserDeviceAttach(PROJECT_USB_4550_Device pDev) { D_ATTACH_GUI_CALLBACK AttachCb = new D_ATTACH_GUI_CALLBACK(DeviceAttachGuiCb); usb_device = pDev; usb_pipe_rev = (PROJECT_USB_4550_Pipe)usb_device.GetpPipesList()[1]; usb_pipe_trs = (PROJECT_USB_4550_Pipe)usb_device.GetpPipesList()[2]; Invoke(AttachCb, new object[] {pDev}); } private void DeviceAttachGuiCb(PROJECT_USB_4550_Device pDev) { TraceMsg("Found new device\r\n"); TraceMsg("Your new device is installed and ready to use\r\n"); } private void UserDeviceDetach(PROJECT_USB_4550_Device pDev) { D_DETACH_GUI_CALLBACK DetachCb = new D_DETACH_GUI_CALLBACK(DeviceDetachGuiCb); Invoke(DetachCb, new object[] { pDev }); } NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 10 - private void DeviceDetachGuiCb(PROJECT_USB_4550_Device pDev) { TraceMsg("Your device has detached\r\n"); } private void SafeLogText(string sMsg) { // InvokeRequired compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (txtLog.InvokeRequired) { safeLogTextCallBack cb = new safeLogTextCallBack(SafeLogText); this.Invoke(cb, new object[] { sMsg }); } else { txtLog.AppendText(sMsg); } } public void TraceMsg(string sMsg) { SafeLogText(sMsg); } private void btwrite_Click(object sender, EventArgs e) { SingleTransfer(); } private void SingleTransfer() { DWORD dwBuffSize = 1; byte[] buffer = new byte[1]; string txt = txttrans.Text; buffer[0] = Convert.ToByte(txt[0]); usb_pipe_trs.UsbPipeTransferAsync(false, 0, buffer, dwBuffSize, TIME_OUT, new D_USER_TRANSFER_COMPLETION(Transfer_trs_Completion)); } private void Transfer_trs_Completion(PROJECT_USB_4550_Pipe pipe) { if (pipe.GetTransferStatus() == (DWORD)wdu_err.WD_STATUS_SUCCESS) { TraceMsg("Transfer completed successfully!\r\n "); } else { TraceMsg("tranfer fail\r\n"); } } private void btread_Click(object sender, EventArgs e) { SingleReceiver(); } private void SingleReceiver() { DWORD dwBuffSize = 1; byte[] buffer = new byte[1]; usb_pipe_rev.UsbPipeTransferAsync(true, 0, buffer, NguyӉn Ngӑc Hѭng Lӟp TKTL 40 HVKTQS - 11 - dwBuffSize, TIME_OUT, new D_USER_TRANSFER_COMPLETION(Transfer_rev_Completion)); } private void Transfer_rev_Completion(PROJECT_USB_4550_Pipe pipe) { if (pipe.GetTransferStatus() == (DWORD)wdu_err.WD_STATUS_SUCCESS) { TraceMsg(DisplayHexBuffer(pipe.GetBuffer(),1)); } else { TraceMsg("receiver failure!\r\n"); } } private string DisplayHexBuffer(byte[] buff, DWORD dwBuffSize) { string display = ""; for (DWORD i = 0; i < dwBuffSize; i++) display = string.Concat(display, buff[i].ToString("X")," "); display = string.Concat(display, Environment.NewLine); return display; } } }
Tài liệu liên quan