آموزش کار با میکروکنترلرهای سری STM32 – بخش سوم
بخش سوم – پروژهی (1) – راه اندازی واحد GPIO
مقدمه
معمولترین نقطهی شروع کار با میکروکنترلرهای STM32 – یا هر میکروکنترلر دیگری – آموختن نحوهی تعریف پین میکروکنترلر بعنوان خروجی و سپس صفر و یک کردن آن میباشد ، برای راه اندازی واحد GPIO ، پروژهی GPIO Blink بهترین گزینه خواهد بود. پروژهی GPIO Blink را در برنامه نویسی میکروکنترلرها میتوان معادل پروژهی Hello World در برنامهنویسی نرمافزار دانست. GPIO مخفف General Purpose Input/Output به مفهوم واحدی بنیادی از میکروکنترلر میباشد که بوسیلهی آن شما میتوانید پینی را بعنوان ورودی یا خروجی برای هر کاربردی (هدف عمومی = General Purpose) تعریف کنید ، Blink به معنای چشمک زدن است که در اینجا بهانهای است برای یادگیری نحوهی صفر و یک کردن یک پین از واحد GPIO برای زمانی که این واحد بعنوان خروجی تعریف شده باشد (چشمک زدن LEDی متصل به پین خروجی).
صورت مسئله
میخواهیم پروژهای طراحی کنیم که پین PC0 از میکروکنترلر STM32F407ZGT6 بطور دائم با یک میان تاخیر 1 ثانیهای صفر و یک شود. برای اینکه صفر و یک شدن پین به راحتی قابل مشاهده شود میتوانیم یک LED به آن وصل کنیم.
شروع طراحی
برنامهی STM32CubeMX را اجرا کرده و سپس مطابق شکلهای زیر یک پروژهی جدید بر مبنای میکروکنترلر STM32F407ZGTx ایجاد کنید.
برای طراحی این پروژه ابتدا باید تنظیمات منبع کلاک سیستم و مبنای زمانی آن انجام شده و سپس پین PC0 بعنوان خروجی تعریف شود.
به همین منظور مطابق شکل زیر تنظیمات مربوط به تب Pinout را انجام دهید.
[1] منبع کلاک سیستم را کریستال خارجی تعیین کنید. [2] با انتخاب کریستال خارجی بعنوان منبع کلاک ، این دو پین برای اتصال به کریستال خارجی رزرو میشوند. [3] مبنای زمانی سیستم برای استفاده در واحدها و توابعی که به آن نیاز دارند. بطور مثال تابع تاخیر HAL_Delay() – که آن را در همین پروژه استفاده خواهیم کرد – از این مبنا استفاده میکند. مبنای زمانی سیستم میتواند واحد SysTick یا یکی از تایمرهای میکروکنترلر تعریف شود ، در نرمافزار Cube در حالت پیشفرض مبنای زمانی سیستم ، واحد SysTick میباشد (شما نیز در این قسمت آن را تغییر ندهید).SysTick یک تایمر 24بیتی پایین شمار در میکروکنترلرهای STM32 میباشد که همیشه از مقدار حداکثر شروع به کم شدن میکند تا به صفر برسد و پس از آن دوباره به مقدار حداکثر باز میگردد و این چرخه پیوسته تکرار میشود. هر بار که مقدار این تایمر صفر میشود یکبار تابع وقفهی مربوط به آن اجرا میشود. بنابراین شما میتوانید با نوشتن دستورات خود داخل تابع وقفهی این واحد از عملکرد این تایمر استفاده کنید. در حالت پیشفرض فاصلهی زمانی بین دو تیک برابر 1ms میباشد که این مقدار را میتوانید در نرمافزار Keil تغییر دهید. ناگفته نماند دقت شمارش این تایمر قابل قبول است و تابع تاخیر تعریف شده بوسیلهی این تایمر بسیار دقیقتر از تابع تاخیری است که با حلقههای while یا for با دفعات تکرار بالا نوشته میشود.
[4] روی پین PC0 چپ کلیک کنید. [5] از منوی باز شده حالت خروجی را انتخاب کنید.سپس به تب Clock Configuration بروید و تنظیمات نهایی کلاک سیستم را تعیین کنید ، بدین ترتیب که رادیوباتونهای [1] و [2] را انتخاب کرده و سپس در تکستباکس [3] مقدار حداکثر فرکانس سیستم (168MHz) را تایپ کنید و بعد از آن کلید Enter را بزنید ، با این کار Cube بطور خودکار تقسیمات متناسب با مقدار تعیین شده را انجام میدهد. مقدار پیشفرض کریستال خارجی [4] را تغییر ندهید ، این مقدار (25MHz) همان مقدار کریستال خارجی مونتاژ شده روی برد کاتالیست F400 میباشد.
در تب Configuration فعلا در این پروژه تنظیمات خاصی نیاز نیست و همان مقادیر پیشفرض جوابگو میباشند ، اما صرفا محض معرفی بعنوان نمونه به توضیح تنظیمات پیشفرض پین PC0 از واحد GPIO – که در مرحلهی اول آن را بعنوان خروجی تعریف کردیم – میپردازیم.
[1] روی این قسمت کلیک کنید تا پنجرهی تنظیمات مربوط به واحد GPIO باز شود. [2] روی پینی که میخواهید مشخصات قابل ویرایش آن نمایش داده شود (PC0) کلیک کنید. [3] در این قسمت مشخصات قابل ویرایش پین انتخاب شده نمایش داده میشود. [4] وضعیت اولیهی پین خروجی (صفر یا یک) را تعیین میکند. [5] در این قسمت میتوانید یکی از دو مد Output Push Pull یا Output Open Drain را بسته به نوع خروجی مورد نیازتان انتخاب کنید ، از مد Open Drain معمولا زمانی استفاده میشود که به یک ولتاژ پولآپ غیر از 3.3v (پولآپ داخلی) نیاز باشد. [6] در این قسمت تعیین میکنید که Pull-up یا Pull-down داخلی مربوط به پین مورد نظر فعال شود یا نه. بخاطر داشته باشید که حالت Open Drain مد Pull-down ندارد چرا که پایهی سورس ترانزیستور داخلی متصل به پین خروجی در این حالت به زمین وصل است. [7] حداکثر فرکانس خروجی پین منتخب از این قسمت قابل انتخاب است (مربوط به قضیهی Slew Rate).بطور مثال برای STM32F407 داریم:
Low = 2 MHz.
Medium = 12,5 MHz to 50 MHz.
High = 25 MHz to 100 MHz.
Very High = 50 MHz to 200 MHz.
[8] در این قسمت میتوانید روی پین منتخب ، یک عنوان (برچسب) به دلخواه خود اختصاص دهید.پیکره بندیهای مورد نیاز این پروژه در نرمافزار Cube به اتمام رسید ، حالا نوبت آن است که تنظیمات کلی پروژهی Cube را نیز انجام دهید ، برای این منظور
از منوی Project ، زیر منوی Settings را انتخاب کنید ، با این کار پنجرهی تنظیمات کلی پروژه (شکل زیر) باز میشود. مطابق شکلهای زیر عمل کنید.
تب Project
[1] نام پروژهی خود را تعیین کنید. [2] محل پروژهی خود را تعیین کنید. [3] شاخهی فرعی محل پروژه [4] در این قسمت MDK-ARM V5 را بعنوان نرمافزار برنامهنویسی – که میخواهید پیکرهبندیهای انجام شده در قالب آن تولید شود – انتخاب کنید. [5] این چکباکس جزو تنظیمات IDEهای دیگری است و ربطی به MDK-ARM ندارد. [6] از این قسمت میتوانید حداقل اندازهی حافظههای Heap (محل ذخیرهی دادههای آدرس دهی شده توسط برنامهنویس) و Stack (محل ذخیرهی متغیرهای محلی غیر static ، پارامترهای توابع ، آدرسهای بازگشتی توابع) را تعیین کنید. [7] این قسمت مربوط به تنظیمات محل پک نصب شدهی میکروکنترلر استفاده شده در پروژه میباشد.* برای این پروژه فقط موارد قسمتهای [1] , [2] , [4] را تنظیم کنید و بقیهی موارد را در حالت پیشفرض رها کنید.
تب Code Generator
[A] تنظیمات پک نرمافزاری [1] اگر این رادیوباتون انتخاب شود ، تمامی فایلهای کتابخانهی HAL (لازم یا نالازم) داخل پوشهی Drivers در محل پروژهی تولید شده کپی خواهند شد. [2] اگر این رادیوباتون انتخاب شود ، فقط فایلهایی از کتابخانهی HAL داخل پوشهی Drivers از محل پروژهی تولید شده کپی خواهند شد که در پروژه استفاده شدهاند (فایلهای متناظر با واحدهای جانبی پیکرهبندی شده در نرمافزار Cube). [3] اگر این رادیوباتون انتخاب شود ، هیچ فایلی از کتابخانهی HAL در مسیر پروژی تولید شده کپی نخواهد شد و کلا پوشهی Drivers نیز ایجاد نخواهد شد ، بلکه فقط مسیر فایلهای مورد نیاز از کتابخانهی HAL در پروژهی کد اضافه خواهد شد. [B] تنظیمات مربوط به فایلهای تولید شده [4] اگر تیک داشته باشد ، داخل پوشهی Src از محل پروژهی تولید شده به ازای هر واحد جانبی تنظیم شده یک فایل سورس جداگانه ایجاد میشود که تمامی تنظیمات مربوط به واحد را در خود جای داده است ، در غیر این صورت تمامی واحدهای جانبی تنظیم شده همگی در فایل main.c تعریف میشوند. [5] اگر تیک داشته باشد ، با هر بار باز تولید کردن پروژهی Cube ، از فایلهای تولید شدهی قبلی یک پشتیبان گرفته میشود. [6] اگر تیک داشته باشد ، با هر بار باز تولید کردن پروژهی Cube ، از کدهایی که برنامهنویس در قسمتهای تعیین شده نوشته است محافظت خواهد شد. [7] اگر تیک داشته باشد ، با هر بار باز تولید کردن پروژهی Cube ، فایلهایی که مجددا تولید نمیشوند حذف خواهند شد. برای مثال چنانچه در بار اول تولید از واحد UART استفاده شده باشد و در بار دوم تولید از آن استفاده نشود فایلهای تولید شدهی قبلی مربوط به واحد UART حذف خواهند شد. [C] تنظیمات مربوط به درایور HAL [8] اگر تیک داشته باشد ، تمامی پینهایی که در پروژه استفاده نشدهاند ، در حالت Analog پیکرهبندی میشوند ، این کار باعث بهینه شدن مصرف توان میکروکنترلر میشود. مواظب باشید که پینهای مربوط به کانکتور JTAG یا SWDرا در صورتی که بخواهید از عیب یابی توسط این کانکتورها بهرهمند شوید نباید در این حالت (حالت (Analogقرار بدهید ، پس به منظور جلوگیری از بروز این مشکل کافی است قبل از این که تیک چکباکس [8] را بگذارید پینهای متصل به کانکتورهای JTAG یا SWDرا در محیط Chip View در تب Pinout تعریف کنید ، برای این منظور مطابق شکل زیر از IPی SYS و قسمت Debug نوع پورت عیبیابی خود را انتخاب کنید. برای مثال در این شکل از پورت JTAG پنج پین استفاده شده است و پینهای مربوطه به رنگ سبز در Pin map نمایش داده شدهاند. [9] اگر تیک داشته باشد ، قابلیت کتابخانهی HAL به نام Full Assert فعال میشود ، Full Assert یک ویژگی بسیار مفید در طول عیبیابی برنامه است ، این ویژگی پارامترهای ورودی توابع HAL را بررسی میکند و در صورت غیرمجاز بودن آنها تابع assert_failed موجود در فایل main.c را فراخوانی میکند. شما میتوانید داخل تابع assert_failed دستورات دلخواه خود را که مایلید در هنگام شناسایی ورودی غیرمجاز برای توابع HAL اجرا شوند را بنویسید.برای مثال دستور HAL_GPIO_WritePin(GPIOC, GPIO_PIN_17, GPIO_PIN_SET); تابع assert_failed را فراخوانی خواهد کرد چرا که برای پورت C پین 17 وجود ندارد. همچنین به کمک تابع assert_failed میتوانید نام فایل و شمارهی سطر ورودی غیر مجاز را بدست آورید.
[D] تنظیمات مربوط به فایلهای الگو ، از این قسمت میتوان فایلهای الگوی جدیدی تعریف کرد تا در هنگام تولید پروژهی کد در کنار فایلهای اصلی پروژه قرار گیرند.* برای این پروژه در این تب فقط رادیوباتون [2] را انتخاب کنید و بقیهی موارد را در حالت پیشفرض رها کنید.
تب Advanced Settings
* صرفا جهت آموزش این قسمت برخی از واحدهای جانبی دیگر به پروژه اضافه شده است.
[A] تنظیمات مربوط به نوع درایور کتابخانهای بکار رفته در واحدهای جانبی: در این قسمت تعیین میکنید که برای تولید کدهای پیکرهبندی متناظر با واحد جانبی انتخاب شده از چه نوع درایور کتابخانهای استفاده شود. [1] میتوانید نام واحد جانبی را از این قسمت جستجو کنید. [2] میتوانید لیست واحدهای جانبی قسمت [A] را از این قسمت براساس الفبا مرتب کنید یا قسمت توضیحات مربوط به واحدها را نمایان یا مخفی کنید. [3] لیست واحدهای جانبی استفاده شده در پروژه [4] برخی از واحدهای جانبی دارای زیر واحد هستند ، مثلا واحد I2C زیر واحدهای I2C1 و I2C2 و I2C3 (در صورت استفاده شدن در پروژه) را دارد که نوع درایور کتابخانهای هر کدام میتواند بطور مجزا تعیین شود. [5] از این قسمت میتوانید نوع درایور کتابخانهای واحد جانبی متناظر را تعیین کنید که البته درایور LL فقط در برخی از میکروکنترلرهای سری STM32 قابل انتخاب است نه در تمام آنها ، پس در اکثر موارد شما در این قسمت انتخاب دیگری غیر از درایور HAL ندارید. [B] تنظیمات مربوط به نوشته شدن/نشدن توابع و همچنین ترتیب نوشته شدن آنها در پروژهی کد [6] شمارهی اولویت نوشته شدن تابع در پروژهی کد [7] نام تابع متناظر با واحد جانبی که در پروژهی کد به آن نام نشان داده خواهد شد. [8] نام واحدهای جانبی استفاده شده در پروژه [9] اگر چکباکس متناظر با یک واحد جانبی تیک داشته باشد ، تابع آن واحد در پروژهی کد تولید نخواهد شد. [10] با تیک زدن به این چکباکس ، تمام چکباکسهای پایینی تیکدار میشوند البته بغیر از چکباکسهای غیر فعال (و برعکس با برداشتن تیک آن ، تیک همهی چکباکسها برداشته میشود). [11] برای بالا و پایین بردن اولویت نوشته شدن تابع واحد جانبی در پروژهی کدی که تولید خواهد شد ، ابتدا واحد مورد نظر را از لیست [B] انتخاب کرده و سپس از این پوشباتونها استفاده کنید. [12] این پوشباتون لیست قسمت [B] را بر اساس حروف الفبا مرتب میکند.* برای این پروژه در این تب هیچ تنظیماتی لازم نیست.
بالاخره با انتخاب زیر منوی Generate Code از منوی Project ، پروژهی کد متناظر با پیکرهبندیهای شما در Cube ، ایجاد میشود و سپس پنجرهی زیر نمایش داده خواهد شد.
با کلیک روی پوشباتون Open Project فایل پروژهی کیل تولید شده ، مستقیما اجرا خواهد شد.
با کلیک روی پوشباتون Open Folder پوشهی پروژهی تولید شده باز خواهد شد.
در غیر اینصورت روی پوشباتون Close کلیک کرده ، برنامهی کیوب را ببندید و سپس به محلی که پروژهی کدتان را تولید کردهاید بروید.
شکل زیر برخی از پوشهها و فایلهای تولید شده توسط نرمافزار Cube را نشان میدهد.
پوشهی Drivers حاوی فایلهای مربوط به درایورهای HAL و CMSIS میباشد.
پوشهی Inc حاوی فایلهای هیدر اختصاصی پروژه میباشد.
پوشهی MDK-ARM حاوی فایل اصلی پروژهی Keil ، فایل تنظیمات مربوط به نرمافزار Keil و فایل اسمبلی مربوط به ساختار بنیادی میکروکنترلر میباشد.
پوشهی Src حاوی فایلهای سورس اختصاصی پروژه میباشد.
فایل GPIO Blink.ioc همان فایل اصلی پروژهی نرمافزار Cube میباشد ، فایل .mxproject نیز مربوط به این برنامه است.
فایل GPIO Blink.uvprojx را اجرا کنید تا پروژهی کد در برنامهی Keil باز شود.
از داخل برنامه ، فایل main.c را باز کرده و دستورات زیر را داخل حلقهی نامتناهی while (1) بین دو کامنت مشخص شده بنویسید.
/* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); HAL_Delay(1000); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); HAL_Delay(1000); /* USER CODE END WHILE */
سطر اول پین خروجی 0 از پورت C را 1 میکند و سطر سوم آن را 0 میکند.
سطر دوم و چهارم نیز یک تاخیر 1 ثانیهای مابین هر بار صفر و یک شدن PC0 ایجاد میکند.
* برای تمام توابع و دستورات بکار رفته در این پروژه از کتابخانهی جدید و قدرتمند HAL استفاده شده است.
** برای ایجاد تاخیر لازم در برنامه از تابع آمادهی کتابخانهی HAL بر مبنای واحد زمانی SysTick استفاده شده است (این روش بسیار دقیقتر از توابع تاخیری است که قبلا برنامهنویسان با استفاده از حلقههای با تکرار بالا ایجاد میکردند).
*** برنامهی بالا را بصورت سادهتر نیز میتوان نوشت:
/* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0); HAL_Delay(1000); /* USER CODE END WHILE */
پس از اتمام مراحل کدنویسی ، برنامهی خود را یکبار Build کنید ، برای این منظور از منوی Project زیر منوی Build target را انتخاب کنید.
چنانچه برنامهی نوشته شده بدون خطا Build شد ، به دو صورت میتوانید آن را اجرا کرده و عملکردش را بررسی کنید:
الف – عیبیابی نرمافزاری که توسط شبیه ساز توکار برنامهی Keil قابل اجراست.
تنظیمات نرمافزار کیل برای استفاده از شبیه ساز: ابتدا باید از منوی Project زیر منوی Options for Target را انتخاب کرده و سپس در پنجرهی باز شده به تب Debug رفته و رادیوباتون Use Simulator را انتخاب کنید.
اجرای برنامه توسط شبیه ساز: از منوی Debug استفاده کنید.
ب – عیبیابی سخت افزاری که برای این منظور در ادامه – همانطور که در بخش اول این سری آموزشی گفته شد – از پروگرمر J-Link و برد آموزشی کاتالیست سری 400 استفاده شده است.
پس از فراهم آوردن یک ارتباط سخت افزاری بینقص بین برد آموزشی و کامپیوتر و البته به واسطهی پروگرمر J-Link ، برای اینکه بتوانید از پروگرم کردن و عیبیابی یکجا یا گام به گام J-Link بهرهمند شوید ، ابتدا باید از منوی Project زیر منوی Options for Target را انتخاب کرده و سپس طبق شکلهای زیر عمل کنید.
سپس از داخل برنامهی Keil با انتخاب زیر منوی Download از منوی Flash ، برنامهی نوشته شده را روی میکروکنترلر مونتاژ شده بر روی برد کاتالیست پروگرم کنید. بعد از انجام این کار مشاهده خواهید کرد که LEDی موجود روی برد کاتالیست – که به PC0 وصل است – شروع به چشمک زدن میکند.
همچنین جهت اجرای برنامه بصورت یکجا یا Step by Step همانند قسمت Simulator میتوانید از منوی Debug استفاده کنید.
* بدیهی است عیبیابی سخت افزاری از جهت اجرای عملکرد برنامه در محیط واقعی ، نسبت به شبیه ساز مجازی برتری دارد ، البته شبیه سازی مجازی نیز مزایای نسبی خود را دارد که کاهش هزینههای ناشی از تهیهی سخت افزار متناسب با میکروهای مختلف را یکی از این مزیتها میتوان دانست.
با عرض پوزش
این اموزش برمبنای تصویر هست.خدایی خودتون چشم تون زوم کنید.ببینید چیزی متوجه میشید از روی تصاویر.اخه چی بگم.یه مقاله نتشر میشه نباید متن ها در داخل تصاویر خونده بشه.