воскресенье, 12 октября 2014 г.

Ввод через usb.

Предыдущие статьи:
Включение светодиода через usb.
usb светофор.
Управление шаговыми двигателями через USB порт.
В этой статье рассмотрим пример передачи информации от микроконтроллера компьютеру через USB порт. Для передачи состояния кнопки можно использовать схему:
Рисунок 1 - Ввод через usb

Полный текст программы для микроконтроллера приведен в статье управление шаговыми двигателями через USB порт. Рассмотрим участок кода для передачи информации на компьютер:
if(rq->bRequest == CUSTOM_RQ_GET_STATUS){
            static uchar dataBuffer[1];     /* buffer must stay valid when usbFunctionSetup returns */
//отослать состояние 3го бита порта D

if(!(PIND & (1< {
dataBuffer[0] = 0;
}
else
{
dataBuffer[0] = 1;
}

usbMsgPtr = dataBuffer;         /* tell the driver which data to return */
            return 1;                       /* tell the driver to send 1 byte */
        }

Код может быть не понятен но нетрудно догадаться что передаваемый байт записывается в переменную usbMsgPtr. Из строки:
if(rq->bRequest == CUSTOM_RQ_GET_STATUS)
понятно что для передачи информации на ПК на микроконтроллер с этого ПК приходит запрос:
CUSTOM_RQ_GET_STATUS
Рассмотрим теперь код для ПК:

#include windows.h
#include stdio.h
#include stdlib.h
#include usb.h        /* this is libusb */
#include stdbool.h  //булева библиотека
#include GL/gl.h
#include GL/glext.h
#include GL/glu.h
#include "opendevice.h" /* common code moved to separate module */
#include "../firmware/requests.h"   /* custom request numbers */
#include "../firmware/usbconfig.h"  /* device's VID/PID and names */
#define USB_CFG_VENDOR_NAME     'e','l','e','c','t','e','.','b','l','o','g','s','p','o','t','.','c','o','m'
#define USB_CFG_VENDOR_NAME_LEN 19
#define USB_CFG_DEVICE_NAME     'm','y','u','s','b','d','e','v','i','c','e'
#define USB_CFG_DEVICE_NAME_LEN 11
#define NUMBER_TRANGLE     30
int i=0;
int j=0;

HDC hdc;
HGLRC hrc;

usb_dev_handle      *handle = NULL;
const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}, rawPid[2] = {USB_CFG_DEVICE_ID};
char                vendor[] = {USB_CFG_VENDOR_NAME, 0}, product[] = {USB_CFG_DEVICE_NAME, 0};
char                buffer[4];
int                  vid, pid;

// Enable OpenGL
void EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC )
{
  PIXELFORMATDESCRIPTOR pfd;
  int iFormat;

  // get the device context (DC)
  *hDC = GetDC( hWnd );

  // set the pixel format for the DC
  ZeroMemory( &pfd, sizeof( pfd ) );
  pfd.nSize = sizeof( pfd );
  pfd.nVersion = 1;
  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pfd.iPixelType = PFD_TYPE_RGBA;
  pfd.cColorBits = 24;
  pfd.cDepthBits = 16;
  pfd.iLayerType = PFD_MAIN_PLANE;
  iFormat = ChoosePixelFormat( *hDC, &pfd );
  SetPixelFormat( *hDC, iFormat, &pfd );

  // create and enable the render context (RC)
  *hRC = wglCreateContext( *hDC );
  wglMakeCurrent( *hDC, *hRC );
}

// Disable OpenGL
void DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC )
{
  wglMakeCurrent( NULL, NULL );
  wglDeleteContext( hRC );
  ReleaseDC( hWnd, hDC );
}
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{

BOOL bQuit = FALSE;
float coords_trangles[NUMBER_TRANGLE];
float dcoords_trangles[NUMBER_TRANGLE];
float angles_trangles[NUMBER_TRANGLE];
float dangles_trangles[NUMBER_TRANGLE];

for (i=0;iNUMBER_TRANGLE;i++)
{
coords_trangles[i]=0;
dcoords_trangles[i]=0;
angles_trangles[i]=0;
dangles_trangles[i]=0;
}

    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */
    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);
    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;
    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           800,                 /* The programs width */
           600,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

usb_init();

// compute VID/PID from usbconfig.h so that there is a central source of information
    vid = rawVid[1] * 256 + rawVid[0];
    pid = rawPid[1] * 256 + rawPid[0];

    if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0){
MessageBox(hwnd, "Could not find USB device\n","error", 0);
        exit(1);
    }
else
{
MessageBox(hwnd, "Find USB device done!\n","Done!", 0);
}

    ShowWindow (hwnd, nFunsterStil);
EnableOpenGL( hwnd, &hdc, &hrc );

while (!bQuit)
{
if (PeekMessage(&messages, NULL, 0, 0, PM_REMOVE))
{
// handle or dispatch messages
if (messages.message == WM_QUIT)
            {
              bQuit = TRUE;
            }
else
            {
              TranslateMessage(&messages);
              DispatchMessage(&messages);
            }
}
else
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);

usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_STATUS,0,0, buffer, sizeof(buffer), 5000);
if(buffer[0]==0)
{

SetWindowText(hwnd, "Button on");
}
else
{
SetWindowText(hwnd, "Button off");
}

for(i=0;iNUMBER_TRANGLE/3;i++)
{
if(buffer[0]==0)
{
coords_trangles[i*3]=0.0f;
coords_trangles[i*3+1]=0.0f;
coords_trangles[i*3+2]=0.0f;

dcoords_trangles[i*3]=((float)rand())/(100*(float) RAND_MAX)-((float)rand())/(100*(float) RAND_MAX);
dcoords_trangles[i*3+1]=((float)rand())/(100*(float) RAND_MAX)-((float)rand())/(100*(float) RAND_MAX);
dangles_trangles[i*3+2]=((float)rand())/((float) RAND_MAX)-((float)rand())/((float) RAND_MAX);
}

glPushMatrix();
glTranslatef(coords_trangles[i*3],coords_trangles[i*3+1],coords_trangles[i*3+2]);
glRotatef(angles_trangles[i*3+2], 0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex2f( 0.0f, 0.20f );
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex2f( 0.287f, -0.25f );
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex2f( -0.287f, -0.25f );
glEnd();
glPopMatrix();

coords_trangles[i*3]+=dcoords_trangles[i*3];
coords_trangles[i*3+1]+=dcoords_trangles[i*3+1];
coords_trangles[i*3+2]+=dcoords_trangles[i*3+2];

angles_trangles[i*3+2]+=dangles_trangles[i*3+2];

dcoords_trangles[i*3]*=0.9965f;
dcoords_trangles[i*3+1]*=0.9965f;

}
SwapBuffers( hdc );
}
}

usb_close(handle);
DisableOpenGL( hwnd, hdc, hrc );
    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                
    {
        case WM_DESTROY:
            PostQuitMessage (0);    
        break;
        default:                    
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}

Приём байта осуществляет функция:
usb_control_msg
Рассмотрим пример использования этой функции для передачи:
usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_STATUS, out_conditions[dt_count], 0, buffer, sizeof(buffer), 5000);
Четвёртым параметром является передаваемая информация, шестым-буфер для приёма информации, седьмым- размер этого буфера.
Для приёма информации нужно изменить второй и третий параметры:
usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_STATUS,0,0, buffer, sizeof(buffer), 5000);
Для того чтобы использовать OpenGL пришлось внести изменения в Makefile.
строку:
USBLIBS = -L"c:/Program Files/LibUSB-Win32/lib/gcc" -lusb
заменить на (т.е. немного дописать):
USBLIBS = -L"c:/Program Files/LibUSB-Win32/lib/gcc" -lusb -lopengl32 -lglu32 -mwindows
и в папку
c:/Program Files/LibUSB-Win32/lib/gcc
добавить файлы:
libopengl32.a
libglu32.a
Также необходимо добавить заголовочные файлы:
#include GL/gl.h
#include GL/glext.h
#include GL/glu.h


И добавить эти заголовочные файлы в папку GL (в папке include (в папке MinGW)) если их там нет.
Скачать программу для микроконтроллера можно по ссылке:https://yadi.sk/d/EJJiYBuRbxEXB
Программу для ПК по ссылке:https://yadi.sk/d/ZDdoRYtObxEfe


КАРТА БЛОГА (содержание)

Подходящие микроконтроллеры ATmega8a-pu (можно заказать по ссылке).

Комментариев нет:

Отправить комментарий