در این آموزش میخواهیم با نحوهی راهاندازی واحد USB در میکروکنترلرهای STM32 آشنا شویم. در این آموزش ما از میکروکنترلر STM32F103C8T6 یا همان Bluepill استفاده میکنیم. در قسمت اول آموزش میخواهیم از طریق پورت USB میکروکنترلر به کامپیوتر داده ارسال کنیم.
نرمافزار CubeMX را باز کرده و پروژهی جدیدی ایجاد میکنیم. میکروکنترلر موردنظر را جستجو کرده و آن را انتخاب میکنیم. تنظیمات RCC را بهصورت زیر انجام دهیم.

در قسمت SYS برای دیباگ گزینهی Serial Wire را انتخاب میکنیم.

در قسمت Connectivity قسمت USB را انتخاب کرده و تیک Device (FS) را میزنیم.

سپس به قسمت Middleware رفته و کلاس Communication Device Class که بهاختصار CDC گفته میشود را انتخاب میکنیم. با انتخاب کلاس CDC، میکروکنترلر میتواند از طریق اینترفیس USB بهصورت Com Port مجازی داده ارسال و دریافت کند.

سپس به قسمت تنظیمات کلاک میرویم و تغییرات زیر را اعمال میکنیم.

در انتها به قسمت Project Manager رفته و اسم پروژه و محل ذخیره پروژه را تعیین میکنیم. میخواهیم از ادیتور Keil استفاده کنیم به همین خاطر گزینهی MDK-ARM را در Toolchain/IDE انتخاب میکنیم و برای ساختهشدن پروژه GENERATE CODE را میزنیم. پس از ساختهشدن پروژه در پنجرهی باز شده گزینهی Open Project را میزنیم تا پروژه را در نرمافزار Keil باز کند.

خلاصهی راهاندازی واحد USB :

در Keil از پوشه Application/User/Core فایل main.c را باز میکنیم. هدر فایل usbd_cdc_if.h را به فایل main.c اضافه میکنیم.

در فایل usbd_cdc_if.c میتوانید تابع ارسال و تابع Callback برای دریافت از طریق USB را مشاهده کنید. برای ارسال داده از طریق ارتباط USB از تابع CDC_Transmit_FS استفاده میکنیم. این تابع آرایهی پیام (اشارهگر به ابتدای پیام) و طول پیام را دریافت کرده و از طریق USB پیام را ارسال میکند.

با بررسی محتوای این تابع میتوان مشاهده کرد درصورتیکه TxState مساوی صفر نباشد این تابع USBD_BUSY را بر میگرداند. این حالت (state) نشان میدهد که واحد USB میکروکنترلر در حال ارسال پیام هست و ارسال قبلی تمام نشده است. بهتر است موقع ارسال داده خروجی تابع را بررسی کنیم و درصورتیکه ارسال قبلی تمام نشده باشد منتظر بمانیم و بعد از اتمام ارسال قبلی، پیام جدید را ارسال کنیم.
میخواهیم پیام Hello World را از طریق USB میکروکنترلر ارسال کرده و در کامپیوتر پیام را دریافت کنیم. در فایل main.c در داخل حلقه while به تابع CDC_Transmit_FS پیام موردنظر و سپس طول پیام را ارسال میکنیم. پس از آن یک تأخیر 500 میلی ثانیهای قرار میدهیم تا هر 500 میلی ثانیه پیام ارسال شود.

برنامه را کامپایل کرده و میکروکنترلر را پروگرام میکنیم. بعد از پروگرام کردن میکروکنترلر، اتصال پروگرامر را قطع میکنیم و با کابل USB میکروکنترلر را به کامپیوتر وصل میکنیم.

پس از وصل کردن میکروکنترلر به کامپیوتر با کابل USB، با باز کردن Device Manger میتوان Com Port ای که وصل شده است را مشاهده کرد.

برای دریافت اطلاعات ارسال شده میتوان از نرمافزارهایی مانند Termit، Putty، QCom و… استفاده کرد. ما از نرمافزار QCom استفاده میکنیم.

با موفقیت توانستیم پیامهای ارسال شده را دریافت کنیم.
میتوانیم پیام موردنظر را در یک آرایه قرار داده و به تابع آرایه را ارسال کنیم. میدانیم متغیر آرایه در واقع یک اشارهگر به محتوای اندیس صفر آرایه است. در مثال زیر ما آرایه را از نوع char تعریف کردهایم. اگر خود آرایه را به تابع ارسال کنیم، با کامپایل کردن مشاهده میکنیم که یک Warning نشان میدهد که مربوط به نوع آرایهی ارسال شده میباشد. تابع CDC_Transmit_FS در آرگومان اول یک اشارهگر از نوع uint8_t دریافت میکند، برای رفع warning، آرایه را به یک اشارهگر uint8_t تبدیل (cast) کرده و به تابع ارسال میکنیم.

همانطور که قبلاً اشاره کردیم بهتر است موقع ارسال، خروجی تابع CDC_Transmit_FS را بررسی کنیم تا درصورتیکه ارسال قبلی تمام نشده است منتظر بمانیم تا پس از اتمام آن دادهی جدید را ارسال کنیم. اگر ارسال قبلی تمام نشده باشد تابع مقدار USBD_BUSY را بر میگرداند، در این صورت باید صبر کنیم تا ارسال قبلی تمام شود تا بتوانیم دادهی جدید را ارسال کنیم. برای پیادهسازی این قسمت از حلقهی while استفاده میکنیم. در شرط while خروجی تابع CDC_Transmit_FS را بررسی میکنیم، اگر برابر با USBD_BUSY باشد، شرط حلقه درست بوده و حلقه اجرا میشود. بهعبارتدیگر، برنامه در این قسمت میماند تا زمانی که ارسال قبلی تمام شود و تابع دادههای جدید را دریافت کند.

فایلهای این آموزش را میتوانید از لینک گیتهاب زیر دانلود نمایید:
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.