Предыдущие статьи:
Включение светодиода через usb.
usb светофор.
Управление шаговыми двигателями через USB порт.
В этой статье рассмотрим пример передачи информации от микроконтроллера компьютеру через 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;i〈NUMBER_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;i〈NUMBER_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 (можно заказать по ссылке).
Включение светодиода через 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;i〈NUMBER_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;i〈NUMBER_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〉
Скачать программу для микроконтроллера можно по ссылке:https://yadi.sk/d/EJJiYBuRbxEXB
Программу для ПК по ссылке:https://yadi.sk/d/ZDdoRYtObxEfe
КАРТА БЛОГА (содержание)
Подходящие микроконтроллеры ATmega8a-pu (можно заказать по ссылке).
Комментариев нет:
Отправить комментарий