PICでUSBを!(知識ゼロからのスタートです)
PIC18F14K50のUSB機能を100%自前のソフトで制御する試みです。しかもアセンブラで!
当記事は2009年12月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 2011.7.12

前へ
次へ
目次へ戻る
ホームページトップへ戻る
☆USB(HID)送信プログラム

パソコンからPIC18F2550へデータを送信するプログラムの試験的なものはすでにできています。
そのプログラムをもとに実用的なプログラムに作り上げました。
実用になったHID送信プログラムの説明です。

[第65回]

●HID送信プログラムリストです

//hidwr2
//for ND80Z write
//
//10/4/29 4/30
//
#include <windows.h>
#include <setupapi.h>
extern "C" {
#include "hidsdi.h"
}
#include <iostream.h>
#pragma comment(lib, "hid.lib")
//
        HANDLE handle;
        int hidget();
        FILE *rfp;
        char inbf[4096]="\0";
        char *fname;
//
void main(int argn,char *args[])
{
        cout << hex;
        fname=args[1];
//file open
        if(!(rfp=fopen(fname,"rb")))
        {
                printf("ファイル名が指定されていないかまたはファイルがみつかりません %s\n",fname);
                return;
        }
// get hid handle       
        if (!hidget()){cout <<"hid device is not found" <<endl;return;}
//
        DWORD nwrite=65;//not 64!
        DWORD nwritn=0;
        unsigned char wbf[65]="\0";
//read file
        int i;
        int d;
        int j;
        int dx;
        int inbfn;
        int dtbyte=0;
        
        while(fgets(inbf,127,rfp)!='\0')//63*2+1
        {
// data set to wbf,max 63 bytes
                inbfn=strlen(inbf);
                j=2;
                for (i=0;i<inbfn;i++)
                {
// ascii(hex) to bynary
// high 4bits
                        d=inbf[i];
                if (d<30)continue;
                if (d<=0x39)dx=(d-0x30)*16;
                else dx=(d-0x37)*16;
//low 4bits
                        i++;
                        d=inbf[i];
                if (d<30)continue;
                if (d<=0x39)dx=dx+(d-0x30);
                else dx=dx+(d-0x37);
//set binary data to wbf[]
                wbf[j]=dx;
                j++;
                }
//set number of send data to wbf[1]
                wbf[1]=j-2;
                dtbyte=dtbyte+j-2;
// send data (64bytes)
                if(!WriteFile(handle,&wbf,nwrite,&nwritn,NULL))cout<<"write error"<<endl;
        }
        printf("send data %d(=%x) bytes\n",dtbyte,dtbyte);
        CloseHandle(handle);
}
//
// get hid handle
int hidget()
   {
        int getmk=0;
        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);
//      
        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_HANDLE"<<endl;continue;}
        HIDD_ATTRIBUTES attr;
        HidD_GetAttributes( handle, &attr ) ;
        if (attr.VendorID==0x4d8 && attr.ProductID==0xa){getmk=1;break;}
     } 
        return getmk;
   }
//end

WriteFile()関数のためのHID handleを取得する部分はhidget()としてまとめました。
この部分は[第48回]のあたりで説明しておりますHIDテストプログラムのHID handle検出までの部分と同じです。

HIDでの送信データは64バイトごとに送られます。
先頭の1バイトは実際に送信するバイト数を入れますから、送信データは63バイトずつになります。
読み込んだファイルのデータは63バイトごとに区切って送信します。
最後のデータだけは63バイト以下になります。

PIC18F2550へ送るデータは、バイナリデータのまま送信します。
しかし今回読み込むデータファイルはバイナリファイルではなくて1バイトのデータを16進数2桁にして、それをASCIIコードで書いたデータファイルです。

そこでこのプログラムでは、ファイルから読み込んだ、ASCIIコードの16進数データを、上位4ビット、下位4ビットの2回に分けて変換し、それを合わせて1バイトのバイナリデータにした上で、63バイトごとにまとめて、PIC18F2550に送信しています。
CPUをつくろう!第492回(2010.5.2upload)を再編集

PICでUSBを![第65回]
2011.7.12upload

前へ
次へ
目次へ戻る
ホームページトップへ戻る