USB 'ye C++ Kodlari ile erismek

Başlatan Digimensch, 26 Ağustos 2006, 18:40:25

Digimensch

C++ Builder ile bir USB Portuna takili Device'ye nasil erisilir derken söyle bir kod buldum.
Bu kod USB'ye baglanmis bir Termometre devresini okumak ve bu Devredeki bir Led lambayi kontrol etmek icin yazilmis anladigim kadaryila.


cy7c63001.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "cy7c63001.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
       // Handle ermitteln
       hTreiber = CreateFile( "\\\\.\\Thermometer_0",
                    GENERIC_WRITE,
                    FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    0,
                    0 );

       // Zeiger ínitialisieren
       pIn = &szIn[0];
       pOut = &szOut[0];
       lpByte = &lByte;

       // Anzeige setzen
       Label1->Caption = "---°C";

       // Fensterposition setzen
       Form1->Top = 100;
       Form1->Left = 100;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
        CloseHandle( hTreiber );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        Timer1->Enabled = false;
        LeseTemp();
        LeseS1();
        Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
// Temperatur auslesen
void TForm1::LeseTemp( void )
{
        int nTemp;
        AnsiString sTemp;

        // 0x04 = Control-Code; Funktionsnummer
        // szOut[0] = Status; [1] = Temperatur; [2] = Vorzeichen; [3] = Schalter
        szIn[0] = 0x0b;

        DeviceIoControl( hTreiber, 0x04, pIn, sizeof(szIn), pOut,
                        sizeof(szOut), lpByte, NULL );

         // Temperatur ermitteln
         nTemp = szOut[1]/2;

        // Ausgabe zusammensetzen
        if ( szOut[2] == 0 ) sTemp += "+";
        else sTemp += "-";
        sTemp += nTemp;
        sTemp += "°C";
        Label1->Caption = sTemp;
}
//---------------------------------------------------------------------------
// Helligkeit der LED D2 einstellen
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
        Timer1->Enabled = false;

        // Setze LED Helligkeit
        szIn[0] = 0x0e;
        szIn[1] = (char)TrackBar1->Position;

        DeviceIoControl( hTreiber, 0x04, pIn, sizeof(szIn), pOut,
                        sizeof(szOut), lpByte, NULL );

        Timer1->Enabled = true;                        
}

//---------------------------------------------------------------------------
// Lese Port 1 lesen uns S1 auskodieren
void TForm1::LeseS1( void )
{
        szIn[0] = 0x14; // Lese Port
        szIn[1] = 0x1;  // Port 1 auslesen

        DeviceIoControl( hTreiber, 0x04, pIn, sizeof(szIn), pOut,
                        sizeof(szOut), lpByte, NULL );

        // Schalter 1 offen
        if ( (szOut[1] & 0x04) == 0x4 )
        {
                Shape1->Brush->Color = clAqua;
                Label3->Caption = "S1 offen";
        }
        // Schalter 1 geschlossen
        else
        {
                Shape1->Brush->Color = clBtnFace;
                Label3->Caption = "S1 geschlossen";
        }
}


cy7c63001.h
//---------------------------------------------------------------------------
#ifndef cy7c63001H
#define cy7c63001H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
#include <ExtCtrls.hpp>
#include <ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// Von der IDE verwaltete Komponenten
        TTimer *Timer1;
        TBitBtn *BitBtn1;
        TTrackBar *TrackBar1;
        TPanel *Panel1;
        TLabel *Label1;
        TLabel *Label2;
        TShape *Shape1;
        TLabel *Label3;
        void __fastcall FormDestroy(TObject *Sender);
        void __fastcall Timer1Timer(TObject *Sender);
        void __fastcall TrackBar1Change(TObject *Sender);
private:	// Anwenderdeklarationen
public:		// Anwenderdeklarationen
        HANDLE hTreiber;
        char szIn[4];          // 4 * 8 Bit ; = long int
        char * pIn;
        char szOut[4];          // 4 * 8 Bit ; = long int
        char *pOut;
        unsigned long int  lByte;
        unsigned long int* lpByte;
        void LeseTemp( void );
        void LeseS1( void );
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


Simdi Kodun su bölümünde
  hTreiber = CreateFile( "\\\\.\\Thermometer_0", 
                    GENERIC_WRITE, 
                    FILE_SHARE_WRITE, 
                    NULL, 
                    OPEN_EXISTING, 
                    0, 
                    0 );

"\\\\.\\Thermometer_0",   ---> Bu nedir?
nerden bulup bunu yazmislar? Bu acaba USB'ye bagl Aletin Driverin adresi falanmi?
Ikinci konu USB'ye bagli Device'nin Outpointlerin adreselerine okuma ve yazma icin nasil ulasiliyor?
Bu adresleri nerden biliyorlar?

Simdi ben bu Kodlari elimdeki Memory Stick üzerindeki led lambasina nasil uyarlayabilirim?Bu Memory Stick'i PC taniyor ve üzerindeki Led lamba Bilgi Okuma ve Memory Stick'e yazma aninda yanip sönüyor.Simdi yukardaki Kodu ben bu Memory Stick'in PC'deki Driverine göre ayalayip Led lambayi high -low yapmak istiyorum bunu yapabilirmiyim?
Bana bunlari aciklayabilecek bir Arkadas varmi?

argeci

selamün aleyküm
Bu konuda bir bilgim yok fakat lambanın usb porttan kontrol edildiğini sanmıyorum en azından generic olarak yani eğer sana lambanın kontrolüne ait bir registere ulaşmana kontrol çipi izin verirse ulaşırsın ama bunu her memory stick ile yapabilirmisin bu konuda şüphelerim var benim kanaatim emin değilim ama veri alış verişi olduğunda bu lamba usb ile flash chipleri arasındaki trafiği yöneten chip tarafından yakılıyor olabilir mesela benim flash belleğim bekleme anında  hiç bir veri transferi yok iken 1.5 saniye onn 1.5 saniye off oluyor ama başka bir bellekte bu olmuyor o sebepten koddan önce gerekirse belleğini açıp kontrolcüsünü öğren datasheet'e bak ondan sonra işe başla derim.
Şunuda ekleyeyim bu adamlar sanırım bu chipi baz almışlar
kodda kullanılan chipin pdf i seninde o işi yapabilmen için her halde bu chip gibi h dosyasına ihtiyacın var en baştaki CY7C63001.h
zaten o fonksiyonların bazılarını sağlıyordur kanaatindeyim.
zaten datashettinde onun şöyle bir entegre olduğunu yazıyor
Low-cost solution for low-speed USB peripherals such as mouse, joystick, and gamepad
esselamü aleyküm ve rahmetüllahi ve berekatühü Allahın selamı rahmeti bereketi hepinizin ve hepimizin üzerine olsun

Digimensch

Kisaca ben USB 'ye bagli bir Deviceye yukardaki Kodlarla nasil ulasabilirim onu ögrenmek istedim.
Memory Stick üzerindeki Lamba önemli değil.Bunu PIC18F4550 ile yapmis oldugum bir Devre olarak görürsek ben yukardaki Kodu kendi devreme nasil uyarlayip USB üzerinden bu devremi Kontrol edebilirim?
Yani yukardaki kodda
  hTreiber = CreateFile( "\\\\.\\Thermometer_0", 
                    GENERIC_WRITE, 
                    FILE_SHARE_WRITE, 
                    NULL, 
                    OPEN_EXISTING, 
                    0, 
                    0 );  

"\\\\.\\Thermometer_0", ---> Bu nedir?   Bu kismi kendi olusturdugum bir devre icin nasil uyarlamaliyim?

Yada söyle anlatayim Ben 18f4550 ile su asagidaki devreyi kurdum diyelim.


Bu Devreye PC tarafi icin ben C++ Builder ile Program yazip , Yukardaki Devredeki LED lambalari yakip söndürmek istiyorum.
C++ Builder ile program yazacagim bu program USB'de Bagli devreye veri göndercek , PIC18F45550 gelen veriye göre islem yapacak.
Iste yukardaki Kodu degistirerek  bunu yapmam mümkünmü?
yada bu isi yapabilecegim Kod veya yapilmis bir proje örnegi varmi?
Insallah anlatabilmisimdir.
Ögrenmek istedigim USB'ye PC tarafindan C++ ile veri göndermek.

SpeedyX

Selam
Bildiğim kadarıyla
\\\\.\\com10

yazınca com10 u dosya gibi açıyor.
Zaten bu C ve php gibi ortamlarda herşey dosya değilmidir :)

m_hCommPort = CreateFile(m_strPort,GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED |
FILE_FLAG_NO_BUFFERING,NULL);
if (m_hCommPort == INVALID_HANDLE_VALUE) return FALSE;

Bu tarz birşey ile erişebilirsin sanırım (okuma ve yazma)
yada
m_hPort = CreateFile (\\\\.\\com10,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);

com10 ise kendi tanımladığın, driverın yönettiği usb portu

Digimensch

USB üzerinden tanittigim bir Alete PC com1,com2 veya com3 gibi isimler atamiyorki?
Ben örnegin USB Protundan tanittigim bir Printerin hangi Com port oldugunu nerden bilecegim?
Serial Portta ok oluyor ama USB'de nasil bilmiyorum.

SpeedyX

Sizin verdiğiniz program USB ye direkt erişmiyor ki.
Erişmek için arada driver kullanıyor (FT232 vs..)

Bu işler için Human Interface Devices (HID) diye bir olay var.
http://www.lvr.com/hidpage.htm
http://www.intel.com/intelpress/usb/examples/ZipFiles/DUSBVC.htm
http://www.alanmacek.com/usb/

#include "usb.h"
#include <setupapi.h>
#include <hidsdi.h>

HANDLE connectToIthUSBHIDDevice (DWORD deviceIndex)
{
    GUID hidGUID;
    HDEVINFO hardwareDeviceInfoSet;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
    PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetail;
    ULONG requiredSize;
    HANDLE deviceHandle = INVALID_HANDLE_VALUE;
    DWORD result;

    //Get the HID GUID value - used as mask to get list of devices
    HidD_GetHidGuid (&hidGUID);

    //Get a list of devices matching the criteria (hid interface, present)
    hardwareDeviceInfoSet = SetupDiGetClassDevs (&hidGUID,
                                                 NULL, // Define no enumerator (global)
                                                 NULL, // Define no
                                                 (DIGCF_PRESENT | // Only Devices present
                                                 DIGCF_DEVICEINTERFACE)); // Function class devices.

    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    //Go through the list and get the interface data
    result = SetupDiEnumDeviceInterfaces (hardwareDeviceInfoSet,
                                          NULL, //infoData,
                                          &hidGUID, //interfaceClassGuid,
                                          deviceIndex, 
                                          &deviceInterfaceData);

    /* Failed to get a device - possibly the index is larger than the number of devices */
    if (result == FALSE)
    {
        SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
        return INVALID_HANDLE_VALUE;
    }

    //Get the details with null values to get the required size of the buffer
    SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet,
                                     &deviceInterfaceData,
                                     NULL, //interfaceDetail,
                                     0, //interfaceDetailSize,
                                     &requiredSize,
                                     0); //infoData))

    //Allocate the buffer
    deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize);
    deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

    //Fill the buffer with the device details
    if (!SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet,
                                          &deviceInterfaceData,
                                          deviceDetail,
                                          requiredSize,
                                          &requiredSize,
                                          NULL)) 
    {
        SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
        free (deviceDetail);
        return INVALID_HANDLE_VALUE;
    }

    //Open file on the device
    deviceHandle = CreateFile (deviceDetail->DevicePath,
                               GENERIC_READ,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,        // no SECURITY_ATTRIBUTES structure
                               OPEN_EXISTING, // No special create flags
                               0, 
                               NULL);       // No template file

    SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
    free (deviceDetail);
    return deviceHandle;
}

HANDLE connectToUSBHIDDevice (DWORD *vendorID, DWORD *productID, DWORD *versionNumber)
{
    HANDLE deviceHandle = INVALID_HANDLE_VALUE;
    DWORD index = 0;
    HIDD_ATTRIBUTES deviceAttributes;
    BOOL matched = FALSE;

    while (!matched && (deviceHandle = connectToIthUSBHIDDevice (index)) != INVALID_HANDLE_VALUE)
    {
        if (!HidD_GetAttributes (deviceHandle, &deviceAttributes))
            return INVALID_HANDLE_VALUE;

        if ((vendorID == 0 || deviceAttributes.VendorID == *vendorID) &&
            (productID == 0 || deviceAttributes.ProductID == *productID) &&
            (versionNumber == 0 || deviceAttributes.VersionNumber == *versionNumber))
            return deviceHandle; /* matched */
        
        CloseHandle (deviceHandle); /* not a match - close and try again */

        index++;
    }

    return INVALID_HANDLE_VALUE;
}

http://www.alanmacek.com/usb/usb.c

Digimensch

Dostum bu bukadar nasil zor olur ya.Anlamiyorum.
Alt tarafi PIC18F4550 ile yaptigim bir devreyi USB'ye baglayim ona PC ortamindan komut göndermek.Bu iside C++ Builder ile yazmak.Bu Serial Port ortaminda gayet basitti.Neden USB ile bukadar zor?
Bu neden bu kadar zor ki?

SpeedyX

C bu hocam, daha kolay bir yolu varsada ben bilmiyorum.
Belki CreateFile ile USB yi de comport gibi açabiliyordur. Ondan emin değilim. Cihazlarla haberleşmek için genelde HID kullanılır.

Digimensch

Su linkte eleman cok güzel örnekler yapmis.
Hepsini USB üzerinden uyarlamis ama kullandigi Programlarin source kodlarini vermemis.
Bu tahminimce bir Yugoslav .Türkce böyle bu isi anlatan bir site yokmu bildiginiz .Türkce kaynaklar cok az her konuda.

http://milan.milanovic.org/skola/parport/usbport-00.htm

Analyzer

Selam,

Kodu biraz açıklayayım ondan sonra belki bir ışık yanabilir :)

Alıntı yapılan: "Digimensch""\\\\.\\Thermometer_0",   ---> Bu nedir?
nerden bulup bunu yazmislar? Bu acaba USB'ye bagl Aletin Driverin adresi falanmi?
Bu arkadaş Cypress'in cy7c63001 psoc'u ile yapmış devresini. Sürücüsü kendisini tanıtırken de Thermometer_0 olarak sisteme kaydolmuş. Bağlantı noktaları kısmında Thermometer_0 şeklinde bir "bağlantı noktası" oluşturulmuş. Daha sonra bunu arkadaş güzelce createfile fonksiyonu ile açmış filehandle almış. Arkasından htreiber pointeri üzerinden DeviceIoControl prosedürü ile okumuş.

Alıntı yapılan: "Digimensch"
Ikinci konu USB'ye bagli Device'nin Outpointlerin adreselerine okuma ve yazma icin nasil ulasiliyor?
Bu adresleri nerden biliyorlar?

DeviceIoControl çağırılmadan önce SizeIn ile komut yönlendiriliyor SizeOut ile veri alınıyor.

Senin devrende ise yine CreateFile ile bir file stream açılıp; bu stream'e writefile()/readfile() fonksiyonları ile erişilip, yazılıp okunması gerekiyor.
Eğer istersen sen de DeviceIoControl ile erişmen mümkün. Mesela portu açıp bir bilgi gönderirsin. 18F4550'de gelen bilgiyi alır mukayese eder uygunsa istediğin ledi yakar/söndürür.

Analyzer
Üşeniyorum, öyleyse yarın!

SpeedyX

O arkadaş VB kullanmış, C++ değil.
Alıntı YapBiblioteka IO.DLL
Za rad pod WindowXP i Windows2000 operativnom sistemu neophodno je da preuzmete ovu biblioteku i da je iskopirate u folder \Windows\System32.
io.dll kütüphane dosyasını \Windows\System32 dizinine kopyalıyor ve VB programı ile verileri ona gönderiyor.
Ve dikkat ederseniz HID kullanıyor.

Digimensch

Evet dostum VB kullanmis biliyorum ama ben Türkce olarak ne C++ ,ne VB nede Delphi ile anlatilmis bir kaynak bulamadim onu ifade etmeye calistim.
Ayrica bu konu acildikca aciliyor .
Peki simdi bu bahsettigin HID ne?

ground

HID bir pc arabirimi.. Human Interface Devices..

Microsoft , intel ve birkaç büyük firmanın kurduğu usb.org sitesi tarafından standartlaştırılan. Pcde ( özellikle windows 2000 ve xpde sorunsuz ) bir driver gerektirmeden ( aslında driver gerektirmeyen değilde zaten OS da standart bulunması düşünülmüş ) çalışabilen bir arabirim..

İlk aşamada klavye , mouse ve oyun konsolları için düşünülmüş ama yakın zamanda elektronik geliştiricileri tarafından saygıyla karşılanmış bir araç.

İyi Çalışmalar..
⌒╮'╭⌒╮⌒╮.
╱◥██◣                  
| 田︱田田|              
╬╬╬╬╬╬╬╬╬

Picproje - Sözde değil özde paylaşım..


Digimensch

sağol un arkadaslar bu konuyu biraz arastirayim.
saygilar