PICでUSBを!(知識ゼロからのスタートです)
PIC18F14K50のUSB機能を100%自前のソフトで制御する試みです。しかもアセンブラで!
| 当記事は2009年12月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 |
2011.7.11 前へ 次へ 目次へ戻る ホームページトップへ戻る |
| ☆C++でUSB(HID)アクセスプログラムを作成 PIC側のプログラムはC18コンパイラを使わずPICアセンブラで作成しますが、パソコン側のUSB(HID)アクセスプログラムはBorland C++コンパイラで作成します。 しかしこれがまた難物で悪戦苦闘の連続でありました。 |
[第52回]
●HID送信テスト
いままで説明してきましたHIDテストプログラムに送信部分を付け加えて実行してみました。
HID送信はWriteFile関数を使います。送信はWindowsマシンからUSBケーブルで接続したPIC18F4550基板に対して行い、PIC18F4550からはRS485で当社のBASICボードZB25Kに対して行います。
その簡単な接続図と写真は[第29回]でお見せしたものと同じです。
[第29回]では、64バイト固定長のデータを送信するテストでしたが、今回は任意の長さのデータを送ってみました。
まずは今回のテストプログラムを実行したときの画面のコピーをお見せします。

右側が送信側です。
左側の画面はBASICボードZB25KがRS485経由でPIC18F4550から受信したデータをパラレルポート経由でWindowsマシンのDOS窓に表示させているところです。
RS485(RS232C)のボーレートは9600ボーです。
HID通信の概略については、[第29回]から以後の何回かにわたって説明をしていますから、HIDについて忘れてしまったよ、というお方はもう一度お読みくださいませ。
そこでも説明しましたようにHID送信(もちろん受信も同じ)では、一度に64バイトしか送ることができません。
右側の送信画面に見えておりますように、データが無い部分は全て00にしてしまえば、送信データ部分だけが認識できるようにも思われますが、そういうわけにはいきません。
今回は見やすさも考えて、ASCII文字コードで送りましたが、メモリデータやプログラムなどをバイナリ(2進数)データのまま送信することも考慮すると、その場合には00〜FFの全てがデータになる可能性がありますから、00とかFFをデータがないことを示す記号にすることはできません。
同様の理由で改行コード0D・0Aも、データエンドマークとしては使うことができません。
ではどうするか。
これはもう、64バイトのうちの1バイトを使って、送信文字数を示すことしかないのではありませんか?
画面右のDOS窓では、送信する文字列データをそのまま表示させたあと、そのデータコードを16進数で表示させています。
最初のバイトが[00]ですが、これはWriteFile関数、ReadFile関数の約束事です。
送信、受信するデータは64バイトですが、送受信バッファは65バイト必要です。
そして最初のバイトには00を入れます。
実際に送受信されるデータは2バイト目からになります。
今回の送信プログラムでは、その2バイト目に、送信バイト数を入れています。
これを受信したPIC18F4550は、この先頭の文字数情報によって、送られてきた64バイトのうち、真の送信データが何バイトかを知ることができますから、必要なデータのみを取り出すことができます。
●HID送信プログラムリストです
今回の送信テスト(上の画面)で使ったHID送信プログラムです。
//HID TEST from hidtest8
//
//10/4/13 4/15 4/16
//
#include <windows.h>
#include <setupapi.h>
extern "C" {
#include "hidsdi.h"
}
#include <iostream.h>
#pragma comment(lib, "hid.lib")
void main( void )
{
cout << hex;
GUID hidGuid;
HidD_GetHidGuid(&hidGuid);
HDEVINFO devinf;
devinf = SetupDiGetClassDevs(&hidGuid, NULL, 0, DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA spid;
spid.cbSize = sizeof(spid);
//
int getmk=0;
HANDLE handle;
for( int index = 0; ; index++ )
{
if(!SetupDiEnumDeviceInterfaces(devinf, NULL, &hidGuid, index, &spid))break;
unsigned long size;
SetupDiGetDeviceInterfaceDetail( devinf, &spid, NULL, 0, &size, 0 );
PSP_INTERFACE_DEVICE_DETAIL_DATA dev_det =new SP_INTERFACE_DEVICE_DETAIL_DATA[size];
dev_det->cbSize=sizeof(*dev_det);
SetupDiGetDeviceInterfaceDetail( devinf, &spid, dev_det, size, &size, 0 );
//
handle = CreateFile( dev_det->DevicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if(handle==INVALID_HANDLE_VALUE){cout<<"INVALID_HADLE"<<endl;continue;}
HIDD_ATTRIBUTES attr;
HidD_GetAttributes( handle, &attr ) ;
if (attr.VendorID==0x4d8 && attr.ProductID==0xa){cout << "GET!" <<endl;getmk=1;break;}
CloseHandle(handle);
}
if (getmk==0){cout <<"not found" <<endl;return;}
//
//write file test
DWORD nwrite=65;//not 64!
DWORD nwritn=0;
unsigned char wbf[65]="\0";
char *wdata1="samidareo/atsumetehayashi/mogamigawa";
int n=strlen(wdata1);
wbf[1]=n+2;//with CR+LF
int i;
int j=0;
for (i=2;i<=n+1;i++){wbf[i]=wdata1[j];j++;}
wbf[i]=0x0d;
wbf[i+1]=0x0a;
cout << wdata1 << endl;
int d;
for (i=0;i<=0x40;i++)
{
d=wbf[i];
printf("[%x]",d);
}
cout << endl;
if(!WriteFile(handle,&wbf,nwrite,&nwritn,NULL))cout<<"write error"<<endl;
else cout<< "write ok"<<endl;
CloseHandle(handle);
}
|

//HID WRITE TEST from hidtest8n
//
//10/4/13 4/15 4/16
//
#include <windows.h>
#include <setupapi.h>
extern "C" {
#include "hidsdi.h"
}
#include <iostream.h>
#pragma comment(lib, "hid.lib")
//
void hidwrite(char *wdata);
HANDLE handle;
//
void main( void )
{
cout << hex;
GUID hidGuid;
HidD_GetHidGuid(&hidGuid);
HDEVINFO devinf;
devinf = SetupDiGetClassDevs(&hidGuid, NULL, 0, DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA spid;
spid.cbSize = sizeof(spid);
//
int getmk=0;
for( int index = 0; ; index++ )
{
if(!SetupDiEnumDeviceInterfaces(devinf, NULL, &hidGuid, index, &spid))break;
unsigned long size;
SetupDiGetDeviceInterfaceDetail( devinf, &spid, NULL, 0, &size, 0 );
PSP_INTERFACE_DEVICE_DETAIL_DATA dev_det =new SP_INTERFACE_DEVICE_DETAIL_DATA[size];
dev_det->cbSize=sizeof(*dev_det);
SetupDiGetDeviceInterfaceDetail( devinf, &spid, dev_det, size, &size, 0 );
//
handle = CreateFile( dev_det->DevicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if(handle==INVALID_HANDLE_VALUE){cout<<"INVALID_HADLE"<<endl;continue;}
HIDD_ATTRIBUTES attr;
HidD_GetAttributes( handle, &attr ) ;
if (attr.VendorID==0x4d8 && attr.ProductID==0xa){cout << "GET!" <<endl;getmk=1;break;}
CloseHandle(handle);
}
if (getmk==0){cout <<"not found" <<endl;return;}
//
//write file test
char *wdata1="samidareo/atsumetehayashi/mogamigawa";
char *wdata2="natsukusaya/tsuwamonodomoga/yumenoato";
char *wdata3="shizukasaya/iwanishimiiru/seminokoe";
char *wdata4="yukuharuya/torinakiuono/mewanamida";
char *wdata5="araumiya/sadoniyokotou/amanogawa";
hidwrite(wdata1);
hidwrite(wdata2);
hidwrite(wdata3);
hidwrite(wdata4);
hidwrite(wdata5);
CloseHandle(handle);
}
//
void hidwrite(char *wdata)
{
DWORD nwrite=65;//not 64!
DWORD nwritn=0;
unsigned char wbf[65]="\0";
int n=strlen(wdata);
wbf[1]=n+2;//with CR+LF
int i;
int j=0;
for (i=2;i<=n+1;i++){wbf[i]=wdata[j];j++;}
wbf[i]=0x0d;
wbf[i+1]=0x0a;
cout << wdata << endl;
int d;
if(!WriteFile(handle,&wbf,nwrite,&nwritn,NULL))cout<<"write error"<<endl;
else cout<< "write ok"<<endl;
return;
}
//
|