C18を使ってPIC-USBをコントロールする方法については、『PICで楽しむUSB機器自作のすすめ』などに詳しく解説してあります。(残念ながら、CDCが主)
ですが、従来から使っているCCS-Cによる解説はとても少ないようです。さらに、マイクロチップ社のフレームワークの中の汎用USBドライバを使うPC側のソフトは
VC++によるサンプル(上記の書籍でも同様) で、これも従来から使っているVB6やVB.NETなどではすぐには利用できません。 PIC側のコンパイラはCCS-Cを使う、パソコン側はVB6またはVB.NETを使ってUSB-I/Fを動かすことを目標にテストしました。また、VB6で動かせたものがVB.NETに変換すると対応されていない関数があり(ポインタに関するもの)、これに悩まされましたが、これも何とか対応しました。 上の書籍に紹介してある・・・PIC側はC18コンパイラ(期間限定・FREE)、PC側はVC++ ・・・でのテストは一通りいたしました。ですが、できれば結構つかえるCCS-CがあるのにC18を追加購入することに納得できませんし、PC側のソフトも従来の資産(VB6/VB.NET) を活用してそれに組み込みたいと思いました。(2009/10/20) Vi su al Basic 6.0USB2.0デバイスがUSB3.0ポートで動作しない場合の解決法 (2017/1/10 追加) 【追加情報 】 2009/12/20: トランジスタ技術2010年1月号に、Windows XP(SP2), Vista, Windows 7までサポートされているUSBデバイス・ドライバの作成が不要の汎用的なドライバであるWinUSBを使った例が掲載されています。さっそくこれを使ったテスト(汎用USBドライバ使用)をいたしました。結果はPIC側のファームウェアは、[ 2 ]-(1)で紹介しているものがそのまま使えます。 紹介されているリンク先( http://www.lvr.com/winusb.htm )のPC側ソフトの例はVB2008とVC#2008です、そこのPICのファームウェアの例にCCS-Cがありませんが [ 2 ]-(1)が使えます。 PIC側をまったく変更しないで使えるのが嬉しいです。 2011/9/12: WinUSBを使用する、VC++2008/CLI によるサンプル用ソフト(I/Oモニター, 移植が容易)を作成しました。WDK(無償)をインストールしなければならないですが、VC++のWinUSBに関する記述自体はVB.NET/VC#に比べると驚くほどシンプルになっています。WDKで入手できるヘッダーファイルの貢献でしょう。 2011/10/5: さらに、同じくWinUSBを使用する、VC# によるサンプル用ソフトを作成しました。VCとは言っても、VC++とVC#は全く違っており少し戸惑いましたが、文字列の操作についてはVC#の方が取り扱いやすく対応は意外と容易でした。コードを記述するとき、VC++では "." ,"->" , "::" の区別があり、これは過去の互換性遺産の上に成り立っているのではないかと感じるところがありますが、こういったことを含めてVC#はすっきりしているなと思いました。 2011/12/5: 現在、Windows上で動かすサンプルソフトと共に提供しているUSB-I/Oシリーズを、Linux(Ubuntu 10.04 LTS)上で動かすテストをしました。インターフェイス2011年8月号でも紹介されている Libusbを使ってです。 Libusbには 0.1 と 1.0 がありますが、この両方において、問題なく製品が動作できることを確認しました(ファームウェアは[ 2 ]-(1)で紹介しているもの)。私にとりましては、1997年ころにLinuxを少し扱って以来のことですので、Linuxが格段に取り扱いやすくなっているのに驚きました。GUIについても JAVAの充実, Eclipse(開発環境) の充実などがやはり驚きです。これなら生産現場においても、無償のLinuxと開発ツール群で充分対応できるのではないかと思いました。リナックスにも多数のディストリビューションがあり、選択の自由と裏腹に導入の難しさがありましたが、Ubuntuの登場と、その日本語フォーラムなどの充実によって障害は低くなってきていると思います。さてそれで、USB-I/Oの基本的な動作確認はできましたので、今後、各製品のGUI(Java)を使ったLinuxサンプルを提供できるようにしてまいります。 Ubuntu日本語フォーラム -> https://forums.ubuntulinux.jp/index.php 2015/6/11: ユーザー様の機能追加のご要望があり、数年ぶりに「プログラマブルAC(2CH)タイマーボード(PMCT」のバージョンアップをいたしました。その際、CCS-Cを使用しているUSB通信のコマンド追加作業をいたしました。この基板では 18F2550 を使っています。パソコンとの間に汎用USBドライバ(WinUSB)を使った通信を確立して基板の各種設定をコマンドで実行しておりますが、そのソースを PMCT通販のページ にてご提供することにいたしました。 [1] CDCサンプル CDC(Communication Device Class: RS232C-USB変換用のクラス)を使用すると、PC側は特別なドライバは必要なく(Windows側に標準で内蔵)、仮想COMポートとして動作するので、従来のRS232C使用のアプリはCOM番号を指定するだけで利用できます。(cdc_NTXPVista.inf) |
[2] 汎用USBドライバ使用のサンプル (1) PIC側ソフト CCS-Cによる『MPUSBAPI.DLL』『mchpusb.sys』『mchpusb.inf』をターゲットにしたサンプルは以下の通りです。PCとのデータのやり取りはアスキー文字列で行うようにしました。PC側では、文字列を送りまた文字列で受信するようにしており、RS232Cのターミナルソフト(ハイパーターミナルなど)に似たインターフェイスのモニターソフトを制作し、色々なコマンドを送ってその応答をチェックしています。それでなくとも、アスキー文字列でのやり取りですので、TextBoxを使った簡単な送受信のソフトはすぐにできると思います。(サンプル:CmUsbByTxt.vbp) 【 追記 】 上記の追加情報でも紹介しましたが、このコードは、PC側のデバイスドライバをWinUSBにしてもそのまま動作します。紹介されているダウンロード元 ( http://www.lvr.com/winusb.htm )から降ろしたwinusb_vb.sln (VB2008ソルーション)を起動して走らせ、'V' などのコマンドを送ると画面に応答が表示されますので動作をすぐに確認できます。INFファイルの変更の仕方とVBソフト内のGUID記述の関連などについて良く理解する必要がありますのでトラ技の2010年1月号104~106ページをご参照ください。ダウンロード元には今のところは、CCS-Cのサンプルは無いので、このコードがそのまま使えます。(2009年12月20日) // ************************************************************************* // UsbApiTst2.c // ************************************************************************* #include <18F2550.h> #include <string.h> //configure a 20MHz crystal to operate at 48MHz #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN #use delay(clock=48000000) #use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8) #define OFF 0 #define ON 1 typedef unsigned int Uint; typedef unsigned long Ulng; typedef signed int Sint; typedef signed long Slng; // ========================================================================= // Definition for CCS-C Compiler. // Give a value which is define at usb.h. // ========================================================================= #define USB_HID_DEVICE FALSE // not use HID #define USB_EP1_TX_ENABLE USB_ENABLE_BULK // Active EP1(EndPoint1) IN Bulk/Interrupt #define USB_EP1_RX_ENABLE USB_ENABLE_BULK // Active EP1(EndPoint1) OUT Bulk/Interrupt #define USB_EP1_TX_SIZE 64 // Buffer Tx EndPoint1(4) #define USB_EP1_RX_SIZE 20 // Buffer Rx EndPoint1(3) #include <pic18_usb.h> // Microchip PIC18Fxx5x , CCS PIC USB Driver #include <PicUSB.h> // Description for configure of the USB #include <usb.c> // Handles usb ,tokens and descriptions #define LED0 PIN_C0 #define LED1 PIN_C1 #define LED2 PIN_C2 #define LED_ON output_low #define LED_OFF output_high ///// LCD Initial Setting #define mode 0x03 // tris data #define input_x input_B #define output_x output_B #define set_tris_x set_tris_B #define stb PIN_B3 #define rs PIN_B2 #include "lcd_lib.c" char UsbRxBuf[USB_EP1_RX_SIZE]; // Receive buffer (20 bytes) char UsbTxBuf[USB_EP1_TX_SIZE]; // Send buffer (30 bytes) const char verStr[] = "UsbApi_Test2_091021"; char CR[] = "\r"; void writeUSB(void); //======== USART Valuable ======== int Rnum = 0; // Receive Number char Rbuf[22]; // Receuve Buffer short Rcmflg = FALSE; // Command Receive Flag #include "SciCommand.c" //======== USART receive Interrupt Process ======== #int_rda void isr_rcv() { char data; data = getc(); // Get RCV char if (data == 0x0d || data == 0x0A) // CRorLF? { Rbuf[Rnum] = 0; // String tarminator Rcmflg = TRUE; // RCV CMD Flag On exe_command(); // Execute RS232C Command } else { Rbuf[Rnum] = data; // To buffer Rnum++; // Increment Index if (Rnum > 20) Rnum = 0; // Check Upper Limit } } void writeUSB(void) { //Attempt to create a pointer to a constant strcat(UsbTxBuf, CR); usb_put_packet(1,UsbTxBuf,strlen(UsbTxBuf),USB_DTS_TOGGLE); } void udspnsup(void) // for the command that is not supported { strcpy(UsbTxBuf, "?\r"); writeUSB(); } void usndOK(void) { strcpy(UsbTxBuf, "OK\r"); writeUSB(); } void main(void) { int i, AD[4]; char *p, c; set_tris_b(0x03); // 0x0F -> 0x03 set_tris_c(0xF8); // add // LCD Setting lcd_init(); // Initialize LCD lcd_clear(); // All CLS LCD lcd_cmd(0x0C); // Cursol:OFF, Brink:Off lcd_cmd(0x80); printf(lcd_data, "Hello! UsbApiTst"); setup_adc_ports(AN0_TO_AN3); // A/D setup_adc(ADC_CLOCK_INTERNAL); // Enable Interrupt enable_interrupts(INT_RDA); // USART Enable enable_interrupts(GLOBAL); // Global INT Enable LED_ON(LED0); LED_OFF(LED1); LED_OFF(LED2); printf("Hello! UsbApiTst2\r\n"); usb_init(); // Initialize of USB usb_task(); // Prepare USB & reset USB usb_wait_for_enumeration(); // Wait till PicUSB consists on PC LED_OFF(LED0); LED_ON(LED1); LED_OFF(LED2); while (TRUE) { if(usb_enumerated()) // PicUSB is configured { if (usb_kbhit(1)) // RX EndPoint1 has data(one packet) from PC ? { usb_get_packet(1, UsbRxBuf, USB_EP1_RX_SIZE); // EP1 -> Buf p = UsbRxBuf; switch(c = toupper(*p++)) { case 'T': // for Test switch(c = toupper(*p++)) { case '0': sprintf(UsbTxBuf, "RX: %d", UsbRxBuf[0]); writeUSB(); break; case '1': break; case '2': break; case '3': sprintf(UsbTxBuf, "-------TEST-------"); writeUSB(); break; case '4': break; } break; case 'A': //Read A/D for(i=0; i<4; i++) { set_adc_channel(i); // CH A0 delay_us(10); // wait AD[i] = read_adc(); // Read } sprintf(UsbTxBuf,"CH0~3:%u,%u,%u,%u",AD[0],AD[1],AD[2],AD[3]); writeUSB(); break; case 'L': //Write LCD for(i=0; i<USB_EP1_RX_SIZE;i++) { if(UsbRxBuf[i]==13) { UsbRxBuf[i] = '\0'; break; } } lcd_cmd(0xC0); printf(lcd_data, p); break; case 'D': //LED On/off D21:Led2->On c = *p++; switch(c) { case '0': if(*p=='0') LED_OFF(LED0); else LED_ON(LED0); break; case '1': if(*p=='0') LED_OFF(LED1); else LED_ON(LED1); break; case '2': if(*p=='0') LED_OFF(LED2); else LED_ON(LED2); break; default: udspnsup(); break; } break; case 'S': //Input SW check i = input_b() & 0x03; sprintf(UsbTxBuf, "IN_B:%X", i); writeUSB(); break; case 'V': strcpy(UsbTxBuf, verStr); writeUSB(); // Version break; case '?': //dspHelp(false); strcpy(UsbTxBuf, "Tx |Test:0~4"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "A |Read A/D"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "Dnv|LED10,1off"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "S |Read SW"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "L..|LCD WR"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "V |Version"); writeUSB(); delay_ms(10); strcpy(UsbTxBuf, "? |Help"); writeUSB(); delay_ms(10); UsbTxBuf[0] = '\0'; writeUSB(); //To stop unnecessary Transmit break; default : udspnsup(); break; } } } else { puts("USB cable was cut off"); reset_cpu(); } } } 【 動作状況 】 茶色の文字が送信文字列、青の文字が受信文字列です。 (2) PC側ソフト(VB6) VB6によるサンプルは次の通りです。リストは各種の定義と送受信の部分だけですので、これを標準モジュールとして組み込み、アプリの部分からこれを呼び出して使えば良いです。 '====================================================================================== ' Routines for to call MPUSBAPI.DLL '====================================================================================== Option Explicit '-------------------------------------------------------------------------------------- ' Function definition contents in VB '-------------------------------------------------------------------------------------- Public Declare Function MPUSBGetDLLVersion Lib "mpusbapi.dll" () As Long Public Declare Function MPUSBGetDeviceCount Lib "mpusbapi.dll" (ByVal pVID_PID As String) As Long Public Declare Function MPUSBOpen Lib "mpusbapi.dll" (ByVal instance As Long, ByVal pVID_PID As String, ByVal pEP As String, ByVal dwDir As Long, ByVal dwReserved As Long) As Long Public Declare Function MPUSBClose Lib "mpusbapi.dll" (ByVal handle As Long) As Long Public Declare Function MPUSBRead Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long Public Declare Function MPUSBWrite Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long Public Declare Function MPUSBReadInt Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long '-------------------------------------------------------------------------------------- ' Constantes for WIN32 API '-------------------------------------------------------------------------------------- Public Const INVALID_HANDLE_VALUE = -1 Public Const ERROR_INVALID_HANDLE = 6& '-------------------------------------------------------------------------------------- ' Function of WIN32 API '-------------------------------------------------------------------------------------- Public Declare Function GetLastError Lib "kernel32" () As Long Public Declare Function timeGetTime Lib "winmm.dll" () As Long '-------------------------------------------------------------------------------------- ' Constantes for connected PIC '-------------------------------------------------------------------------------------- Public Const vid_pid = "vid_04d8&pid_0011" ' VID:04D8(Microchip)/PID:0011 要!・小文字 Public Const out_pipe = "\MCHP_EP1" Public Const in_pipe = "\MCHP_EP1" Public Const MPUSB_FAIL = 0 Public Const MPUSB_SUCCESS = 1 Public Const MP_WRITE = 0 Public Const MP_READ = 1 '-------------------------------------------------------------------------------------- ' Variable of IN_PIPE and OUT_PIPE '-------------------------------------------------------------------------------------- Public myInPipe As Long Public myOutPipe As Long '-------------------------------------- 追加 Public Const BUF_SIZE = 65 Public Send_Buf(0 To BUF_SIZE - 1) As Byte Public Rec_Buf(0 To BUF_SIZE - 1) As Byte Public LenRcv As Long Public TST$ Function GetRecStrings(ByVal tout As Long) As String '受信Byte配列を文字列にして返す(CRは削除) Dim i%, rec$ '受信していなければ、tout後 NULLを返す 'デリミタをVbCR(13)とする rec = "" If (MPUSBRead(myInPipe, VarPtr(Rec_Buf(0)), BUF_SIZE, LenRcv, tout)) Then rec = Rec_Buf rec = StrConv(rec, vbUnicode) '変換する For i = 1 To LenRcv If Mid(rec, i, 1) = vbCr Then rec = Left(rec, i - 1): Exit For 'VbCRの前を抜き出す End If Next End If GetRecStrings = rec End Function '【パケットの受信】 '受信している1パケットをMPUSBRead()しない限り、次のパケットは捨てられるようである。 '-------------------------------------------------------------------------------------- ' Open peripheral '-------------------------------------------------------------------------------------- Sub OpenMPUSBDevice() Dim tempPipe As Long Dim count As Long tempPipe = INVALID_HANDLE_VALUE count = MPUSBGetDeviceCount(vid_pid) If count > 0 Then myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, MP_WRITE, 0) myInPipe = MPUSBOpen(0, vid_pid, in_pipe, MP_READ, 0) If myOutPipe = INVALID_HANDLE_VALUE Or myInPipe = INVALID_HANDLE_VALUE Then MsgBox Str(myOutPipe) + " " + Str(myInPipe) + " When open pipes, error occurs" myOutPipe = INVALID_HANDLE_VALUE myInPipe = INVALID_HANDLE_VALUE End If Else MsgBox "Peripheral device is not connected" End If End Sub '-------------------------------------------------------------------------------------- ' Close peripheral '-------------------------------------------------------------------------------------- Sub CloseMPUSBDevice() If myOutPipe <> INVALID_HANDLE_VALUE Then MPUSBClose (myOutPipe) myOutPipe = INVALID_HANDLE_VALUE End If If myInPipe <> INVALID_HANDLE_VALUE Then MPUSBClose (myInPipe) myInPipe = INVALID_HANDLE_VALUE End If End Sub '-------------------------------------------------------------------------------------- ' Function: Send_Receive ' ' SendData: Sending data buffer ' SendLength: Sending data length ' ReceiveData: Receiving data buffer ' ReceiveLength: Receiving data length ' SendDelay: Sending Time-out(ms) ' ReceiveDelay: Receiving Time-out(ms) '-------------------------------------------------------------------------------------- Function Send_Receive(ByRef SendData() As Byte, SendLength As Long, _ ByRef ReceiveData() As Byte, ByRef ReceiveLength As Long, _ ByVal SendDelay As Long, ByVal ReceiveDelay As Long) As Long Dim SentDataLength As Long Dim ExpectedReceiveLength As Long ExpectedReceiveLength = ReceiveLength 'パイプが使える状態かを確認してから送受信に入る If (myOutPipe <> INVALID_HANDLE_VALUE And myInPipe <> INVALID_HANDLE_VALUE) Then '送信 If (MPUSBWrite(myOutPipe, VarPtr(SendData(0)), SendLength, SentDataLength, SendDelay) = MPUSB_SUCCESS) Then '受信 If (MPUSBRead(myInPipe, VarPtr(ReceiveData(0)), ExpectedReceiveLength, ReceiveLength, ReceiveDelay) = MPUSB_SUCCESS) Then '受信データ長の確認 If (ReceiveLength = ExpectedReceiveLength) Then Send_Receive = 1 ' All OK Exit Function ElseIf (ReceiveLength < ExpectedReceiveLength) Then Send_Receive = 2 ' Received it, but it's broken Exit Function End If Else CheckInvalidHandle ' Message of Error End If Else CheckInvalidHandle ' Message of Error End If End If Send_Receive = 0 ' Operation failed End Function '-------------------------------------------------------------------------------------- ' Show the error type '-------------------------------------------------------------------------------------- Sub CheckInvalidHandle() If (GetLastError() = ERROR_INVALID_HANDLE) Then ' It is usually caused by unconnected states of the devices CloseMPUSBDevice Else MsgBox "Error code: " + Str(GetLastError()) End If End Sub '-------------------------------------------------------------------------------------- ' Function : Send ' ' SendData: Sending data buffer ' SendLength: Sending data length ' SendDelay: Sending Time-out(ms) '-------------------------------------------------------------------------------------- Function Send(ByRef SendData() As Byte, SendLength As Long, ByVal SendDelay As Long) As Long Dim SentDataLength As Long If (myOutPipe <> INVALID_HANDLE_VALUE And myInPipe <> INVALID_HANDLE_VALUE) Then If (MPUSBWrite(myOutPipe, VarPtr(SendData(0)), SendLength, SentDataLength, SendDelay) = MPUSB_SUCCESS) Then Send = 1 ' All OK Exit Function Else CheckInvalidHandle ' Message of Error End If End If Send = 0 ' Operation failed End Function (3) PC側ソフト(VB2005) VB2005によるサンプルは次の通りです。VarPtr関数はサポートされておらずまた定数のvbUnicodeなどもサポートされていないので、それに代わる方法を使っています。リストは、各種の定義と送受信の部分だけですので、これを標準モジュールとして組み込み、アプリの部分からこれを呼び出して使えば良いです。 【 追記 】 この変換によるソフトのUSB入出力の速度は、やや落ちています。VB.NETの場合は、WinUSBによる方法が良いと思います。WinUSBによるテストでは、VB6による速度とほぼ同等になっています。 Option Strict Off Option Explicit On Imports VB = Microsoft.VisualBasic Imports System.Runtime.InteropServices Module VBMPUSBAPI '====================================================================================== ' Routines for to call MPUSBAPI.DLL '====================================================================================== '-------------------------------------------------------------------------------------- ' Function definition contents in VB.NET '-------------------------------------------------------------------------------------- Public Declare Function MPUSBGetDLLVersion Lib "mpusbapi.dll" () As Integer Public Declare Function MPUSBGetDeviceCount Lib "mpusbapi.dll" (ByVal pVID_PID As String) As Integer Public Declare Function MPUSBOpen Lib "mpusbapi.dll" (ByVal instance As Integer, ByVal pVID_PID As String, ByVal pEP As String, ByVal dwDir As Integer, ByVal dwReserved As Integer) As Integer Public Declare Function MPUSBClose Lib "mpusbapi.dll" (ByVal handle As Integer) As Integer Public Declare Function MPUSBRead Lib "mpusbapi.dll" (ByVal handle As Integer, ByVal pData As Integer, ByVal dwLen As Integer, ByRef pLength As Integer, ByVal dwMilliseconds As Integer) As Integer Public Declare Function MPUSBWrite Lib "mpusbapi.dll" (ByVal handle As Integer, ByVal pData As Integer, ByVal dwLen As Integer, ByRef pLength As Integer, ByVal dwMilliseconds As Integer) As Integer Public Declare Function MPUSBReadInt Lib "mpusbapi.dll" (ByVal handle As Integer, ByVal pData As Integer, ByVal dwLen As Integer, ByRef pLength As Integer, ByVal dwMilliseconds As Integer) As Integer '-------------------------------------------------------------------------------------- ' Constantes for WIN32 API '-------------------------------------------------------------------------------------- Public Const INVALID_HANDLE_VALUE As Short = -1 Public Const ERROR_INVALID_HANDLE As Short = 6 '-------------------------------------------------------------------------------------- ' Function of WIN32 API '-------------------------------------------------------------------------------------- Public Declare Function GetLastError Lib "kernel32" () As Integer Public Declare Function timeGetTime Lib "winmm.dll" () As Integer '-------------------------------------------------------------------------------------- ' Constantes for connected PIC '-------------------------------------------------------------------------------------- Public Const vid_pid As String = "vid_04d8&pid_0011" ' VID:04D8(Microchip)/PID:0011 要!・小文字 Public Const out_pipe As String = "\MCHP_EP1" Public Const in_pipe As String = "\MCHP_EP1" Public Const MPUSB_FAIL As Short = 0 Public Const MPUSB_SUCCESS As Short = 1 Public Const MP_WRITE As Short = 0 Public Const MP_READ As Short = 1 '-------------------------------------------------------------------------------------- ' Variable of IN_PIPE and OUT_PIPE '-------------------------------------------------------------------------------------- Public myInPipe As Integer Public myOutPipe As Integer '-------------------------------------- 追加 Public Const BUF_SIZE As Short = 65 Public Send_Buf(BUF_SIZE - 1) As Byte Public Rec_Buf(BUF_SIZE - 1) As Byte Public LenRcv As Integer Public TST As String Function GetRecStrings(ByVal tout As Integer) As String '受信Byte配列を文字列にして返す(CRは削除) Dim i As Short '受信していなければ、tout後 NULLを返す Dim rec As String = "" 'デリミタをVbCR(13)とする 'ガベージコレクションでオブジェクトが移動されないようにする(VarPtrがサポートされないため以下の方法でアドレスを得る) Dim gch As GCHandle = GCHandle.Alloc(Rec_Buf, GCHandleType.Pinned) Dim adrs As Integer = gch.AddrOfPinnedObject().ToInt32() If (MPUSBRead(myInPipe, adrs, BUF_SIZE, LenRcv, tout)) Then For i = 0 To LenRcv - 1 'StrConv(rec, vbUnicode) はアップグレードされないので以下の方法を使う If Rec_Buf(i) <> 13 Then rec = rec & Chr(Rec_Buf(i)) 'VbCRの前まで End If Next End If GetRecStrings = rec 'ハンドルを開放する gch.Free() End Function '【VB6 ->VB.NET】変換時に変換不可であった VarPtr, StrConv(rec, vbUnicode) については・・・ '(1) VarPtr についてはガベージコレクションを停止しそして再開する方法を調べ出して使用した。 '(2) vbUnicodeがサポートされていないので、rec = rec & Chr(Rec_Buf(i))を繰り返した。 '-------------------------------------------------------------------------------------- ' Open peripheral '-------------------------------------------------------------------------------------- Sub OpenMPUSBDevice() Dim tempPipe As Integer Dim count As Integer tempPipe = INVALID_HANDLE_VALUE count = MPUSBGetDeviceCount(vid_pid) If count > 0 Then myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, MP_WRITE, 0) myInPipe = MPUSBOpen(0, vid_pid, in_pipe, MP_READ, 0) If myOutPipe = INVALID_HANDLE_VALUE Or myInPipe = INVALID_HANDLE_VALUE Then MsgBox(Str(myOutPipe) & " " & Str(myInPipe) & " When open pipes, error occurs") myOutPipe = INVALID_HANDLE_VALUE myInPipe = INVALID_HANDLE_VALUE End If Else MsgBox("Peripheral device is not connected") End If End Sub '-------------------------------------------------------------------------------------- ' Close peripheral '-------------------------------------------------------------------------------------- Sub CloseMPUSBDevice() If myOutPipe <> INVALID_HANDLE_VALUE Then MPUSBClose(myOutPipe) myOutPipe = INVALID_HANDLE_VALUE End If If myInPipe <> INVALID_HANDLE_VALUE Then MPUSBClose(myInPipe) myInPipe = INVALID_HANDLE_VALUE End If End Sub '-------------------------------------------------------------------------------------- ' Function: Send_Receive ' ' SendData: Sending data buffer ' SendLength: Sending data length ' ReceiveData: Receiving data buffer ' ReceiveLength: Receiving data length ' SendDelay: Sending Time-out(ms) ' ReceiveDelay: Receiving Time-out(ms) '-------------------------------------------------------------------------------------- Function Send_Receive(ByRef SendData() As Byte, ByRef SendLength As Integer, ByRef ReceiveData() As Byte, ByRef ReceiveLength As Integer, ByVal SendDelay As Integer, ByVal ReceiveDelay As Integer) As Integer Dim SentDataLength As Integer Dim ExpectedReceiveLength As Integer 'ガベージコレクションがオブジェクトを移動できないようにする(VarPtrが使えないため) Dim gch As GCHandle = GCHandle.Alloc(SendData, GCHandleType.Pinned) Dim adrs As Integer = gch.AddrOfPinnedObject().ToInt32() Dim gch2 As GCHandle = GCHandle.Alloc(ReceiveData, GCHandleType.Pinned) Dim adrs2 As Integer = gch2.AddrOfPinnedObject().ToInt32() ExpectedReceiveLength = ReceiveLength If (myOutPipe <> INVALID_HANDLE_VALUE And myInPipe <> INVALID_HANDLE_VALUE) Then If (MPUSBWrite(myOutPipe, adrs, SendLength, SentDataLength, SendDelay) = MPUSB_SUCCESS) Then '読み出し:元々第3引数はExpectedReceiveLengthである。これでエラーが出るのでBUF_SIZEとするとOKになる。 If (MPUSBRead(myInPipe, adrs2, BUF_SIZE, ReceiveLength, ReceiveDelay) = MPUSB_SUCCESS) Then If (ReceiveLength = ExpectedReceiveLength) Then Send_Receive = 1 ' All OK Exit Function ElseIf (ReceiveLength < ExpectedReceiveLength) Then Send_Receive = 2 ' Received it, but it's broken Exit Function End If Else CheckInvalidHandle() ' Message of Error End If Else CheckInvalidHandle() ' Message of Error End If End If Send_Receive = 0 ' Operation failed gch.Free() gch2.Free() End Function '-------------------------------------------------------------------------------------- ' Show the error type '-------------------------------------------------------------------------------------- Sub CheckInvalidHandle() If (GetLastError() = ERROR_INVALID_HANDLE) Then ' It is usually caused by unconnected states of the devices CloseMPUSBDevice() Else MsgBox("Error code: " & Str(GetLastError())) End If End Sub '-------------------------------------------------------------------------------------- ' Function : Send ' ' SendData: Sending data buffer ' SendLength: Sending data length ' SendDelay: Sending Time-out(ms) '-------------------------------------------------------------------------------------- Function Send(ByRef SendData() As Byte, ByRef SendLength As Integer, ByVal SendDelay As Integer) As Integer Dim SentDataLength As Integer 'ガベージコレクションがオブジェクトを移動できないようにする(VarPtrが使えないため) Dim gch As GCHandle = GCHandle.Alloc(SendData, GCHandleType.Pinned) Dim adrs As Integer = gch.AddrOfPinnedObject().ToInt32() If (myOutPipe <> INVALID_HANDLE_VALUE And myInPipe <> INVALID_HANDLE_VALUE) Then If (MPUSBWrite(myOutPipe, adrs, SendLength, SentDataLength, SendDelay) = MPUSB_SUCCESS) Then Send = 1 ' All OK Exit Function Else CheckInvalidHandle() ' Message of Error End If End If Send = 0 ' Operation failed gch.Free() End Function End Module |
|
汎用製品通販のページへ 高速フーリエ変換(dsPIC-FFT)へ USB-IOのページに戻 る |