به نام خدا

سلام خدمت دوستان عزیز!

اینبار رفتم سراغ usb یه چیزایی یاد گرفتم بعلا ازش جدا شدم! قرار میدم تا ازش استفاده کنید!


تعریف اولیه از USB!

اونجور که من فهمیدم usb host برای میزبانی usb هست! مثلا وقتی شما یک فلش رو به کامپیوتر میزنید ، کامپیوتر میشه host

و usb device هم برای خروجی هست! مثلا یک دسته بازی که usb داره (دقت کنید بهش usb نمیخوره بلکه usb ازش خارج میشه) خود فلش هم شاید نوعی usb device باشه! موس و صفحه کلید و هرچی که به کامپیوتر وصل میشه usb device هست!


کلاس های USB HOST:

(Human Interface Device (HID             

(Mass Storage Device (MSC


کلاس های USB Device :

Audio Device (ADC) - to exchange streaming audio data

Communication Device (CDC) - to realize a virtual COM port

Human Interface Device (HID) - to exchange control and configuration data

Mass Storage Device (MSC) - to store and access data


A human interface device such as a mouse, keyboard, tablet, or game controller

An imaging device such as a scanner, printer, or camera

A mass storage device such as a CD-ROM drive, floppy drive, or DVD drive


منبع:

http://www.eca.ir/forum2/index.php?topic=49894.msg258876#msg258876


ساختار کلی یک دستگاه USB

هر دستگاه USB دارای چندین Endpoint است. هر Endpoint در حقیقت یک بافر است که با پروتکل خاصی با کامپیوتر ارتباط برقرار می کند. تبادل اطلاعات در پورت USB فقط به واسطه Endpoint ها صورت می گیرد پس هر دستگاه حد اقل باید یک Endpoint کنترلی با ID صفر داشته باشد ولی در تعداد Endpoint ها هیچ محدودیتی نیست و دستگاه می تواند تا صدها Endpoint داشته باشد. Endpoint مقصد یا مبدا انتقال داده است. در پروتکل USB کامپیوتر فقط با خواندن یا نوشتن در Endpoint ها با دستگاه تبادل داده می کند و نه از راه دیگر.

توجه کنید که این پوت همانند پورت سریال نیست که دستگاه هر وقت اراده کرد داده ها را به سمت کامپیوتر ارسال کند، در اینجا دستگاه باید داده ها را روی Endpoint خروجی خود قرار دهد و منتظر شود تا کامپیوتر محتوای آن Endpoint را بخواند.

برای درک بهتر موضوع باید این نکته را بدانید که پورت USB با تمامی پورتهای رایج متفاوت است. در واقع Endpoint ها به این جهت به وجود آمدند تا کار طراحی دستگاه را ساده تر کنند. به عنوان مثال یک دستگاه را در نظر بگیرید که هم اسکنر است و هم پرینتر، در طراحی این دستگاه بهتر است از یک Endpoint برای ارسال تصویر اسکن شده به کامپیوتر استفاده شود و از Endpoint دیگری برای دریافت اطلاعات پرینت تصویر استفاده شود و از یک Endpoint برای هماهنگی های لازم همانند کنترل میزان جوهر در کارتریج و ... در واقع بهتر است از هر Endpoint به منظور کار مشخصی استفاده شود تا برنامه نویسی برای میکروکنترلر و PC راحت تر شود.

 

مشخصات یک Endpoint

  1.  اندازه : گفتیم Endpoint یک بافر است که مسلما اندازه ثابتی دارد. (مثلا 64 بایتی)

  2.  ID : هر Endpoint را با شماره اش می شناسند. عددی که از صفر تا ... ادامه دارد. (مثلا Endpoint 4)

  3. جهت : هر اندپوینت می تواند ReadOnly , WriteOnly , ReadWrite باشد. جهت این اصطلاحات از دید میزبان تعیین می شود، به گونه ای که :
    الف ) Read :    PC <---- Device
    ب   ) Write :  PC ----> Device
    مثلا طراح دستگاه ممکن است بخواهد از یک Endpoint فقط برای ارسال اطلاعات به کامپیوتر (Read) استفاده کند و از Endpoint دیگر فقط برای دریافت اطلاعات (Write).

  4. نوع انتقال : هر Endpoint می تواند یکی از این چهار نوع انتقال را داشته باشد، در واقع برای کاربردهای مختلف چهار پروتکل مختلف طراحی شده که Endpoint با کامپیوتر مرتبط شود. تفاوت این پروتکل ها در نحوه زمانبندی ، سرعت و ... است.

    • انتقال کنترلی : هر دستگاهی باید Endpoint کنترلی شماره صفر را داشته باشد. این نوع اندپوینت صرفا برای ایجاد هماهنگی میان دستگاه و کامپیوتر طراحی شده، ولی برای دستگاههای ساده که حجم انتقال داده ها کم است نیز جوابگوی نیاز است. ارتباط کنترلی کمی پیچیده تر از سایر ارتباط ها است و در ادامه روی آن بحث می کنیم. (از آنجا که هدف آشنایی با OBDEV USB است و این درایور این نوع انتقال را با سرعت بالاتری انجام می دهد بیشتر روی این تمرکز می کنیم)

    • انتقال وقفه ای  (Interrupt) : این نوع ارتباط برای دستگاه هایی استفاده می شود که ریتم منظمی برای ارسال و در یافت اطلاعات ندارند. این نوع ارتباط فقط و فقط برای ارسال داده بکار می رود. میزبان هرگاه بخواهد میتواند یک بسته را به Endpoint وقفه ای بفرستد و دستگاه نیز هر گاه بخواهد می تواند یک بسته را از Endpoint وقفه ای ارسال کند. توجه داشته باشید که در ارسال دستگاه به میزبان ، میزبان هر وقت بخواهد اطلاعات اندپوینت را می خواند و دستگاه بیچاره باید برای ارسال بسته بعدی اطلاعات منتظر بماند تا میزبان (PC) هر وقت دوست داشت Endpoint را بخواند.

    •  انتقال توده ای ( کیلویی ، Bulk ) : همانند وقفه ای است ، ولی برای حجم بالا طراحی شده . در درایور OBDEV تفاوتی میان این دو قائل نشده اند.

    •  انتقال همزمان(Isochronous) : اطلاعات کاملی ندارم. ولی OBDEV این نوع انتقال را پشتیبانی نمی کند. بیشتر برای مودم ها و اسپیکرها و مانیتورها کاربرد دارد. در این انتقال میزبان حداقل فاصله بین دو بار خواندن یا نوشتن در اندپوینت تضمین می شود ، چرا که سیستم عامل کامپیوتر به دلایلی انتقالهای USB را با سرعت نا منظم انجام می هد و در این نوع حداقل فاصله را تضمین می کند.

 

مشخصات یک دستگاه USB

در پورت هایی همچون Lan و COM و ... یکی از مشکلات در برنامه نویسی سمت کامپیوتر همواره پیدا کردن دستگاه از بین دستگاه های متصل به کامپیوتر بود. در پورت USB این مشکل حل شده است. یک دستگاه usb حتما باید دارای 2 کد باشد Vendor ID (آی دی سازنده) و Device ID (آی دی دستگاه) که این دو کد شناسنامه اصلی یک دستگاه USB به شمار می آید. همچنین یک دستگاه USB می تواند شماره سریال اختصاصی نیز داشته باشد. نام شرکت سازنده و نام دستگاه نیز می توانند در داخل خود دستگاه ذخیره شوند تا در صورتی که درایور دستگاه نیز نصب نبود سیستم عامل کامپیوتر بتواند حداقل اطلاعاتی را از دستگاه بدست بیاورد. لازم به ذکر است که کارت های PCI نیز این مشخصات را در خود دارند.


مببع: تاینی انجینر


خوب تا اینجا با مفاهیم اولیه usb آشنا شدیم!

حالا کار کمی راحت تر شد!

اگه از برد eca استفاده میکنید برای usb شش نمونه مثال آورده که میتونید ازش استفاده کنید! به نام های زیر

[25] USB_MIC-SPK

[23] USBHID

[24] USBMem

[22] USBAudio

[20] USBHostLite

[19] USBCDC

خوب اگه اینارو نداشتید رو اسمشون کلیک کنید تا دانلود شه!

فقط وقتی توی لینک بالا رفتید توی کادر جست و جو بنویسید <برنامه نمونه> تا اونارو بیاره! دیگه از اسمش پیداست و میتونید دانلود کنید!


الان ویژگی هر کدوم از مثال هها رو میگیم!

[23] USBHID یکی از بهترین مثال هاست! توی اینجا ما با اتصال usb به کامپیوتر (همون usb که باش پروگرم میکنیم) و روسن کردن جامپر 2 میتونیم به کامپیوتر وصل بشیم و وضعیت کلید ها و led ها رو مشاهده کنیم! (برنامه کامپیوترش هم توی فایل نمونه موجوده)

[24] USBMem توی این مثال با اتصال usb به شیوه بالا میکرو به عنوان یک حافظه خارجی (مثل فلش) شناخته میشه

[22] USBAudio توی این مثال با اتصال usb به روش بالا میکرو به عنوان یک اسپیکر یا همون بلندگو شناخته میشه و میتونید یه هندزفری به میکرو وصل کنید و صدای کامپیوتر رو بشنوید!

[20] USBHostLite  توی این مثال دیگه usb device نیست مثل بالا بلکه usb host هست! یعنی بهش usb میخوره! شما باید یه فلش بهش وصل کنید تا فایل  MSREAD.txt  رو (که شما باید بسازید ) رو کپی کنه و فایل دیگه بسازه

[19] USBCDC توی این مثال وقتی شما usb رو به کامپیوتر وصل میکنید، کامپیوتر به صورت یه پورت com مجازی میشناستش و شما میتونید با هایپر ترمینال با میکرو ارتباط برقرار کنید!

[25] USB_MIC-SPK توی این مثال وقتی usb میکرو رو به کامپیوتر وصل کنید، کامپیوتر به عنوان یک اسپیکر و میکروفون میشناسه و شما میتونید با اتصال میکروفون به میکرو صداتون رو تو کامپیوتر ضبط کنید!


خوب شما بادیدن این مثال ها میتونید خیلی به usb نزدیک بشید! شاید بهترین مثال [23] USBHID  باشه! شما حتما این مثال رو باز کنید و ببینید! توی فایل usbhw.c میتونید اطلاعات خوبی رو پیدا کنید!


بهترین کار مراجعه به یوزرمانوئل UM10360 هست!


توی این دیتاشیت یا یوزر مانوئل من چیزای خوبی گیرم اومد که براتون قرار میدم!


برای دسترسی به usb ما سه نوع دسترسی داریم

1- خواندنی

2- نوشتنی

3- دستورالعمل


مثلا برای اینکه به usb بگیم میخوایم یه دیتا بخونیم به طور کلی باید یه دستور العمل بفرستیم که میخوایم دیتا بخونیم بعد دیتا برای ما ارسال میشه!

کلا رجیستر های usb  به صورت زیر هست!


توی عکس بالا تمام رجیستر های مربوط به usb رو میتونید ببینید!

خوب ما به توضیح رجیستر های مهم میریم!


رجیستر USB Device Interrupt Status register (USBDevIntSt - address 0x5000 C200)

توی این رجیستر وضعیت دیوایس usb رو بررسی میکنیم! از این رجیستر توی حیلی از جاهای برنامه استفاده میشه!

به شکل زیر


خوب این جدول رو داشته باشید کارش داریم!


رجیستر USB Device Interrupt Clear register (USBDevIntClr - 0x5000 C208)

این رجیستر برای پاک کردن وقفه هاست! پرچم کدوم وقفه؟!

وقفه های وضعیت های رجیستر بالا! مثلا بیت 5 رجیستر بالا که میشه CDFULL برای اینه که بفهمیم اطلاعات دریافتی کامل شده! خوب برای اینکار وضعیت اون بیت رو چک میکنیم وقتی 1 شد یعنی دریافت شده!

خوب برای دفعه بعد این بیت یک هست و میکرو فکر میکنه دریافت شده درصورتی که هنوز دریافت نشده برای همین با همین رجیستر اونو پاک میکنیم تا دفعه بعد به مشکل بر نخوریم! 

جدولش هم مثل جدول بالا هر بیت که توی جدول بالاست توسط این رجیستر وقفه اش 0 میشه!


رجیستر USB Command Code register (USBCmdCode - 0x5000 C210)

در این رجیستر که یکی از مهمترین رجیستر هاست! برای ارسال دستور العمل استفاده میشه!

بیت های این رجیستر در شکل زیر آورده شده!


حتما با دقت به جدول نگاه کنید! این رجیستر از مهمترین رجیستر هاست!

توی این رجیستر ما فقط با بایت های 2 و3 کار داریم!

اولین کاری که باید توی برنامه نویسی کرد اینه که بهش 0x500 رو بدیم تا بهش بگیم که میخوایم دستورالعمل بنویسیم! بعد توی بایت 3 دستور العمل رو بهش میگیم که خودش جدول جدا داره!

به تکه کد زیر توجه کنید

void WrCmdDat (U32 cmd, U32 val) {
  LPC_USB->USBDevIntClr = 0x10; // Clear CCEMPTY.
  LPC_USB->USBCmdCode = 0x00D00500; // CMD_CODE=0xD0, CMD_PHASE=0x05(Command)
  while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); // Wait for CCEMPTY.
  LPC_USB->USBDevIntClr =0x10; // Clear CCEMPTY.
  LPC_USB->USBCmdCode = 0x008A0100; // CMD_WDATA=0x8A(DEV_EN=1, DEV_ADDR=0xA),CMD_PHASE=0x01(Write)
  while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
}

 توی این کد توسط خط 2 پرچم وقفه بیت 4 توی رجیستر USBDevIntSt صفر شده!

سپس توی خط سوم دستورالعمل 0XD0 برای USBCmdCode فرستاده میشه!

بعد توی خط بعد منتظر میمونیم تا رجیستر USBDevIntSt بگه که کد ارسال شده توسط USB خونده شد!

دوباره پرچم وقفه بیت 4 توی رجیستر USBDevIntSt صفر شده!

و این بار  0X8A برای USBCmdCode فرستاده میشه!

و دوباره صبر میکنیم تا بخونه!

اینم یه مثل دیگه 

USBDevIntClr = 0x30; // Clear both CCEMPTY & CDFULL
USBCmdCode = 0x00F50500; // CMD_CODE=0xF5, CMD_PHASE=0x05(Command)
while (!(USBDevIntSt & 0x10)); // Wait for CCEMPTY.
USBDevIntClr = 0x10; // Clear CCEMPTY interrupt bit.
USBCmdCode = 0x00F50200; // CMD_CODE=0xF5, CMD_PHASE=0x02(Read)
while (!(USBDevIntSt & 0x20)); // Wait for CDFULL.
USBDevIntClr = 0x20; // Clear CDFULL.
CurFrameNum = USBCmdData; // Read Frame number LSB byte.
USBCmdCode = 0x00F50200; // CMD_CODE=0xF5, CMD_PHASE=0x02(Read)
while (!(USBDevIntSt & 0x20)); // Wait for CDFULL.
Temp = USBCmdData; // Read Frame number MSB byte
USBDevIntClr = 0x20; // Clear CDFULL interrupt bit.
CurFrameNum = CurFrameNum | (Temp << 8);

خوب حالا میخوایم ببینیم چه چیزایی رو باید به عنوان command ارسال کنیم!

به جدول زیر نگاه کنید!

اینا کد هایی هستن که ما میتونیم برای usb ارسال کنیم! 

در این تصویر در ستون dataphase نشان میدهد که بعد از ارسال یک دستورالعمل باید چه مقداری بخوانیخم یا بنویسیم!


توضیح هر کدام از اینها در دیتاشیت در لینک زیر وجود دارد!

دانلود دیتاشیت


صفحه 254 رو مطالعه کنید!


در آخر هم توصیه میکنم فایل PDF زیر رو دانلود کنید و مطالعه کنید! (منبع)


امیدوارم بدردتون خورده باشه!

فعلا!

یا علی مدد...!