آموزش میکروکنترلر STM32 – خروجی کردن GPIO

قبلاً در این خصوص که GPIO  چیست صحبت کردیم و گفتیم در صورتیکه بخواهیم یک پایه را به شکل دلخواه صفر یا یک کنیم باید آن را در حالت GPIO_Output ، و به طور برعکس اگر بخواهیم صفر یا یک اعمال شده به آن را بخوانیم باید آن را به صورت GPIO_Input ، پیکربندی کنیم. در ادامه مبحث آموزش میکروکنترلر STM32 قصد دارم نحوه‌ی خروجی کردن GPIO را به همراه یک مثال عملی شرح دهم.

مثال عملی ما در ساده‌ترین حالت ممکن قرار دارد. قرار است یک LED را به صورت چشمک‌زن خاموش و روشن کنیم. اگر با همان بردی که من استفاده می‌کنم، کار می‌کنید، بر روی برد یک جامپر به نام led وجود دارد که اگر آن را وصل کنیم پین PA4 میکروکنترلر را به آند led روی برد با نام D1، وصل می‌کند. در اینصورت ما می‌توانیم از همین D1 برای انجام مثال خودمان استفاده کنیم.

تذکر: نسخه‌ی STM32CubeMX مورد استفاده در این پست ورژن 5.5 و نسخه STM32CubeIDE ورژن 1.2.1 می‌باشد.

ایجاد پروژه با STM32CubeMX :

نرم افزار STM32CubeMX را باز کنید. از آنجا که این اولین بار است که قراره از این نرم‌افزار استفاده کنیم، توضیحاتی ابتدایی برای استفاده کسانی که هیچ آشنایی با آن ندارند می‌دهم. در پست‌های آتی این توضیحات دیگر آورده نمی‌شود.

هنگامی که این نرم‌افزار را باز می‌کنید چنین صفحه‌ای مقابل شما باز می‌شود:

صفحه‌ی آغازینِ نرم‌افزار STM32CubeMX - دیجیلاگیست

از این صفحه ما می‌توانیم یا پروژه‌ای که قبلاً ساخته‌ایم را باز کنیم یا اینکه پروژه‌ای کاملاً جدید را بسازیم. اگر برد شما یکی از بردهای شرکت ST – مثلاً STM32F429I Discovery – است، بهتر است از طریق BOARD SELECTOR برد خودتان را انتخاب کنید تا به پروژه تنظیمات پیش فرض اضافه‌تر اضافه شود و کار شما را سرعت بخشد. در غیر این صورت از طریق MCU SELECTOR -کادر قرمز تصویر بالا- این امکان را دارید تا مستقیماً میکروکنترلر خود را انتخاب کنید. با توجه به اینکه برد من از بردهای رسمی ST نیست، راه دوم را پیش گرفتم. بعد از کلیک بر روی کلید ACCESS TO MCU SELECTOR صفحه‌ای مشابه با تصویر زیر برایتان باز خواهد شد.

انتخاب میکروکنترلر در STM32CubeMX - دیجیلاگیست

ناحیه سمت چپ MCU Filters نام دارد. هنگامی که چیزی در این قسمت وارد نکردید در قسمت MCUs List نام همه‌ی میکروکنترلرهای شرکت ST لیست می‌شود. اما هر بار که به این قسمت فیلتری را اضافه می‌کنید خواهید دید که این لیست محدودتر می‌شود. در اینجا ما قبلاً میکروکنترلرمان را انتخاب کردیم و در نتیجه کافی است در قسمت Part Number Search ابتدای نام آن – stm32f030f4 – را وارد کنیم تا در لیست تنها نام میکروی مدنظرمان را نشان دهد. اما گاهی هنوز در خصوص پارت نامبر میکروکنترلرمان به تصمیم نهایی نرسیده‌ایم. در این صورت اینجا یک جای فوق العاده است تا این تصمیم گیری را راحت‌تر انجام دهید. چراکه به کمک فیلترها می‌توانید لیست پیش رویتان را محدود کنید. حتی می‌توانید لیست خود را بر اساس پارامتر مدنظرتان مثل قیمت میکروکنترلر مرتب کنید و نهایتاً به انتخاب مطلوب خود دست پیدا کنید.

به هر ترتیب، بر روی نام میکروکنترلر انتخابی خود در قسمت MCUs list دوبار کلیک کنید تا به صفحه اصلی تنظیمات پروژه برسید.

کانفیگ پین‌ها و پریفرال‌های مورد نیازمان:

راه اندازی پریفرال GPIO به صورت خروجی :

در این صفحه شما شاهد میکروکنترلر خود به صورت گرافیکی هستید. اگر بر روی هر کدام از پین‌هایش کلیک کنید به شما حالت‌های ممکن آن پین را نشان می‌دهد. هر کدام از این حالت‌ها نقش متفاوتی است که شما می‌توانید برای آن پین تعریف کنید. نقشی که در اینجا به دنبال آن هستیم GPIO_Output است. پس با این حساب روی پین PA4 کلیک کنید و این نقش را برایش تنظیم کنید. اگر درست کار را پیش برده باشید، خواهید دید که همانند زیر رنگ پین از حالت خاکستری به سبز تغییر کرده است. می‌توانیم با راست کلیک بر روی همین پین و انتخاب Enter User Label نام دلخواه خودمان -مثلاً led- را بر روی آن بگذاریم.

کانفیگ پین‌های مدنظر در STM32CubeMX - دیجیلاگیست

همانطور که گفتیم پریفرالی که در حال راه‌اندازی‌اش هستیم، GPIO نام دارد. تا الان مشخص کردیم که این پریفرال بر روی پین PA4 به صورت خروجی پیاده سازی شود. اما هنوز می‌توان تنظیمات بیشتری را اعمال کرد. برای اینکار باید گزینه GPIO را از قسمت سمت چپ صفحه -کادر 1- انتخاب کرد تا لیستی از پین‌های فعال شده، برایمان ظاهر گردد. 

کانفیگ پریفرال gpio_output - دیجیلاگیست

 

از این لیست باید پین مدنظرمان را پیدا کرده و بر روی آن کلیک کنیم تا به این ترتیب تنظیمات بیشتر آن برایمان نمایان شود.

 

ستون وسط قابلیت پنهان شدن هم دارد. این کار توسط دو فلشی که در بالای آن قرار دارد -کادر 2- صورت می‌گیرد. پس اگر غیب شد و موندید که کجا رفت یا اینکه هر چه روی GPIO کلیک می‌کنید این ستون ظاهر نشد، با کلیک بر روی فلش بالایی دوباره ظاهرش کنید.

GPIO Output Level :

اولین گزینه تنظیمات، GPIO Output Level  است. از آنجا که ما پین را به صورت GPIO خروجی تعریف کردیم پس وظیفه‌ی ماست که مقدارش را هم مشخص کنیم. البته اینطور نیست که تا ابدالدهر این مقدار ثابت باشد. بلکه خواهید دید که می‌توانیم مقدار آن را در برنامه خود تغییر دهیم و آن را صفر یا یک کنیم. اما مقداری که در اینجا تعریف می‌کنیم، اولین وضعیتی است که پس از تنظیم پایه به حالت GPIO_Output قرار است به آن برسد. در  اینجا من low را انتخاب کردم، در این صورت انتظار داریم پس از خروجی کردن PA4، صفر دیجیتال بر روی آن قرار بگیرد.

GPIO mode :

گزینه بعدی GPIO mode است. توضیح این یکی کمی سخت‌تر از قبلی است.

در حالت GPIO خروجی با دو مُد روبرو هستیم: Output Push Pull و Output Open Drain . مُد پوش پول، مُدی است که اغلب با آن کار داریم. در این مُد وقتی که پین خروجی را از طریق نرم‌افزار صفر کنیم، بر روی آن صفر ولت می‌افتد و وقتی که آن را یک می‌کنیم VCC می‌افتد. اگر بخواهیم کمی بیشتر وارد جزئیات شویم بهتر است نگاهی به تصویر زیر که وضعیت پایه در مُد پوش پول را نشان می‌دهد، بیندازید.

وضعیت پین gpio_output در حالت پوش پول

out پایه خروجی است و بقیه تصویر داخل چیپ قرار دارد. هنگامی که خروجی را صفر می‌گذاریم ترانزیستور پایینی -NMOS- فعال می‌شود و زمین را بر روی خروجی می‌اندازد در حالی که ترانزیستور بالایی هم خاموش است. گویی که اصلاً نیست. برعکس هنگامی که خروجی را یک می‌کنیم، ترانزیستور بالایی -PMOS- فعال می‌شود و در نتیجه VCC بر روی پین خروجی می‌افتد. در اینجا هم ترانزیستور پایینی خاموش است و مثل این می‌ماند که اصلاً حضوری ندارد. به این مدار اصطلاحاً پوش پول می‌گویند.

اما حالا تصور کنید که کلاً ترانزیستور بالایی را از مدار حذف کنیم. چه می‌شود؟

وقتی که خروجی را به صورت نرم‌افزاری صفر می‌کنیم، ترانزیستور موجود -تصویر زیر- روشن می‌شود و گراند یا همان صفر ولت را در خروجی می‌اندازد. وقتی هم که خروجی را یک می‌کنیم، ترانزیستور خاموش می‌شود. در این حالت مقاومتی که از سمت پایه درین ترانزیستور می‌بینیم، زیاد است. در نتیجه انگار که اصلاً چیزی وجود ندارد و پایه خروجی از داخل آی‌سی به هیچ جا وصل نیست. این درست همان وضعیتی است که در حالت open drain شاهد آن هستیم. همانطور که اشاره کردم کاربرد این حالت کم است. اما با این حال مواردی هست که چنین ویژگی لازم می‌شود.

وضعیت پین gpio_output در حالت open drain

GPIO Pull-up/Pull-down :

حالت نوبت به GPIO Pull-up/Pull-down میرسه. به طور خلاصه هر گاه پین تراشه را با یک مقاومت -مثلاً ده کیلواهم- به VCC وصل کنیم، آن را اصطلاحاً پول آپ کرده‌ایم و برعکس اگر آن را با مقاومت به زمین وصل کنیم، پول داون کردیم. در میکروکنترلرها اغلب این امکان وجود دارد که به صورت داخلی این کار را انجام دهیم. یعنی با دستور نرم‌افزاری مشخص کنیم که پایه، Pull-up شود یا Pull-down. در اینجا از آنجا که نیازی به نه pull down داریم و نه pull up، گزینه No pull-up and no pull-down را انتخاب می‌کنیم.

Maximum output speed :

گزینه بعدی Maximum output speed است که به کمک آن سرعت تغییر حالت از صفر به یک -rise time- و یا از یک به صفر -fall time- پایه را تعیین می‌کنیم. احتمالاً موافقید که همیشه بهتر این گزینه را روی حداکثر میزان خود قرار دهیم. به هر حال هر چه سرعت بیشتر بهتر.

اما باید در نظر داشت که دنیای مهندسی، دنیای trade off است. ما اغلب نمی‌توانیم همه چیز را با هم داشته باشیم. با این حساب باید این سوال در ذهن شما آمده باشد که با سرعت بالا قرار است چه چیز از دست بدهیم؟

سرعت rise/fall time بالا باعث مصرف توان بیشتر میکروکنترلر می‌شود. شاید این مورد برای شما اهمیت آنچنانی نداشته باشد. اما علاوه بر این، مشکل دیگری که ممکن است در اثر این سرعت بالا برای ما به وجود بیاید، کراس تاک است. به عبارت ساده‌تر این سرعت بالای تغییر وضعیت gpio باعث انتشار نویز بیشتر در محیط می‌شود که اگر اثرش قابل توجه باشد قطعاً در کارکرد مدار شما و یا حتی مدارات اطرافش می‌تواند مشکل ساز شود. 

با این توضیحات فکر کنم قانع شده‌اید، تا جایی که امکان دارد و لزومی ندارد، بهتر است حداکثر سرعت خروجی پایه را بر روی low قرار دهید.

User label :

اگر قصد دارید نام خاصی را بر روی پایه خود قرار دهید، – مثلاً led – در کادر انتهای این تنظیمات آن را وارد کنید. کاری که البته ما به شکل دیگری انجامش دادیم.

میان نوشت:

قبل از اینکه از این مرحله عبور کنیم و بریم سراغ کانفیگ کلاک، بد نیست به نکته‌ای که البته در آینده بیشتر خواهیم دید، اشاره کنم.

اگر دقت کرده باشید، بعد از اینکه پین PA4 را خروجی کردیم، کنار پریفرال‌های ADC و USART1 علامت هشدار ظاهر شد. می‌تونید حدس بزنید چرا؟

روی ADC کلیک کنید تا تنظیماتش باز شود. 

کانفلیکت IN4 با GPIO_Output در پین PA4

گزینه IN4 قرمز است. این به ما نشان می‌دهد که دیگر نمی‌توانیم از PA4 به عنوان IN4 پریفرال ADC استفاده کنیم. چراکه در حال حاضر آن را به صورت یک GPIO_Output مورد استفاده قرار داده‌ایم. مشابه همین ماجرا هم برای USART1 برقرار است و ما نمی‌توانیم حالت Synchronous را برای این پریفرال تعریف کنیم، چراکه این حالت نیاز به پین PA4 دارد که اون هم الان برای یک کار دیگه مورد استفاده قرار گرفته. اگر اوضاع از این خراب‌تر بود و هیچ کدام از حالت‌های مثلاً ADC را نمی‌توانستیم انتخاب کنیم، در این صورت می‌دیدیم که به جای علامت هشدار، کلاً این پریفرال قرمز می‌شد. 

کانفیگ SYS:

در همین قسمت پریفرال‌ها گزینه‌ای داریم به اسم SYS. برای امکان پروگرام و یا دیباگینگ میکرو، لازم و واجب است که تیک Debug Serial Wire زده شود. در این صورت خواهید دید که دوتا از پایه‌های دیگر نیز سبز می‌شوند. این دو پایه که به عنوان SWCLK و SWDIO نام گذاری شده‌اند باید به پین‌‌های تعیین شده به همین نام بر روی پروگرامر ST-Link، وصل شوند.

کانفیگ پایه‌های مربوط به کلاک:

RCC یا واحد مربوط به کلاک هم قسمت دیگری است که باید تکلیفش مشخص شود. این واحد تنظیمات اولیه‌اش در همینجا صورت می‌گیرد و برای تنظیمات بیشتر آن، باید به تب بعدی -که در ادامه توضیح خواهم داد- رجوع کرد.

برای تنظیمات این قسمت، شما -برای این میکروکنترلر- دو گزینه پیش‌رو دارید:

اولی BYPASS Clock Source است، که درصورتی باید انتخاب شود که قصد داریم از اسیلاتور برای تامین کلاک استفاده کنیم. در غیر این صورت اگر می‎خواهیم از کریستال یا رزوناتور برای تکمیل مدار تولیدکننده کلاک استفاده کنیم، باید گزینه دوم یعنی Crystal/Ceramic Resonator را مد نظر قرار دهیم. من از آنجایی که روی بردم از کریستال استفاده شده، از گزینه دوم استفاده می‌کنم. پس از انتخاب این گزینه، مشاهده خواهید کرد که پایه‌های مربوطه به سبز تغییر رنگ می‌دهند. به تنظیمات دیگر این واحد در اینجا کاری نداریم و ازشون عبور می‌کنیم.

تا اینجا، کار ما با این صفحه به اتمام رسیده و بهتره سراغ تب بعدی – clock configuration – برویم.

کانفیگ کلاک میکروکنترلر:

در این تب، هر تنظیمی که لازم است برای تعیین مقدار کلاک واحدهای مختلف انجام دهیم، صورت می‌گیرد. این صفحه فوق العاده است. هم دید بهتری از قسمت‌های مختلف کلاک سیستم به شما می‌دهد و هم اینکه شما را از انجام محاسبات گوناگون برای تعیین عدد هر قسمت، بی‌نیاز می‌کند.

تنظیم کلاک در STM32CubeMX - دیجیلاگیست

من با توجه به بردم که بر روی آن کریستال هشت مگاهرتز نصب شده، عدد هشت را برای Input Frequency وارد کردم. از طرفی چون می‌خواهم با حداکثر کلاک یعنی 48 مگاهرتز کار کنم، این عدد را در قسمت HCLK و SYSCLK گذاشتم. اگر به نمودار این صفحه دقت کنید، می‌بینید که برای ساختن SYSCLK، سه راه وجود دارد.

راه اول استفاده از مولد کلاک داخلی -HSI: high-speed internal oscillator- است، که با یک مدار RC این کلاک را می‌سازد. ویژگی‌ای که دارد این است که غیر دقیق است، اما برای جاهایی که کلاک خارجی به هر دلیلی از کار می‌افتد یا اینکه می‌خواهیم کاهش هزینه داشته باشیم، می‌تواند مفید واقع شود.

دومین راه، استفاده از کلاک تولید شده خارجی -HSE: high-speed external oscillator- بدون هرگونه تغییر در مقدار آن. یعنی اگر کریستال هشت مگاهرتز استفاده می‌کنید همان هشت مگاهرتز را برای SYSCLK استفاده می‌کند.

در روش سوم هم بسته به انتخاب شما، فرکانس HSI یا HSE را می‌گیرد و به PLL داخلی میکرو می‌دهد تا برای ما مقدار آن فرکانس را چند برابر کند. درست همانند کاری که من در اینجا انجام دادم. فرکانس 8 مگاهرتز HSE را گرفتم و برای ساخت 48 مگاهرتز SYSCLK آن را تحویل PLL دادم.

توضیحات برای کلاک تا همینجا کافی است. نگران سایر اسامی مختلفی که در این صفحه می‌بینید نباشید. قرار نیست همه‌ی آن‌ها را یکجا یاد بگیرید. برای این پست، کار ما دیگر با این صفحه به اتمام رسیده، بهتره سراغ صفحه بعدی برویم و بعد از یکسری توضیح کوتاه حاصل کار خود را مشاهده کنیم.

آماده سازی پروژه برای ایجاد:

برای اینکار به تَب Project Manager بروید. نام پروژه را وارد کنید و محلی که می‌خواهید آن را ایجاد کنید مشخص نمایید. در قسمت IDE هم محیط توسعه مدنظرتان را وارد کنید. IDE مورد علاقه این روزهای من، TrueSTUDIO است. سعی می‌کنم در آینده در پستی مجزا از دلایل این دلبستگی بگویم:). شما می‌توانید با هر IDE که راحت‌ترید یا مجبورید! کد بزنید، اما بدانید و آگاه باشید که توضیحات بعدی  من بر اساس این محیط خواهد بود. 

حالا دیگه وقتشه که پروژه را ایجاد کنیم. پس بی معطلی بر روی کلید GENERATE CODE در بالای صفحه اصلی برنامه کلیک کنید. در انتهای عملیات ایجاد به شما پیامی می‌دهد مبنی بر اینکه آیا پروژه را باز کند یا خیر. آن را ببندید تا از طریق دیگر پروژه را باز کنیم.

کار بر روی پروژه در محیط truestudio :

نرم افزار truestudio را باز کنید. در پنجره Project Explorer  راست کلیک کرده و import را کلیک کنید. توجه کنید که همانند شکل زیر Existing Projects into Workspace انتخاب شده باشد.

وارد کردن پروژه در Truestudio

سپس Next را بزنید و از طریق Brows محلی که پروژه‌تان در آن قرار دارد را انتخاب کنید و نهایتاً Finish را بزنید.

وارد کردن پروژه در Truestudio - دیجیلاگیست

حالا اگر درست این کارها را انجام داده باشید بایست در Project Explorer آن را به صورت باز شده، مشاهده کنید.

در همین پنجره Project Explorer در پوشه source پروژه، به دنبال main.c باشید و بر روی آن دابل کلیک کنید تا فایل اصلی که قرار است با آن کار کنیم را مشاهده کنید. همانطور که مشاهده می‌کنید اگرچه هنوز هیچ کدی نزده‌اید اما پروژه خالی خالی هم نیست. در واقع این‌ها کار CubeMX است. این برنامه کار شما را راحت کرده و آن تنظیمات گرافیکی که در مراحل قبل انجام دادید را به این کدها تبدیل کرد.

نکته مهم: یادتان باشد که از الان به بعد هر کدی که می‌خواهید به فایل‌های ایجاد شده توسط CubeMX اضافه کنید را در جاهایی وارد کنید که این نرم‌افزار مشخص کرده. مثلاً بین این دو کامنت:

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

شما به هر دلیل امکان دارد که بخواهید در تنظیمات پروژه با کمک CubeMX دوباره تغییراتی چون تغییر پریفرال‌ها انجام دهید. اگر کدهایتان را بین این دو خط مشخص شده، وارد نکرده باشید، با generate دوباره پروژه، همه‌ی کدهایتان به باد فنا می‌رود. اما اگر این نکته را رعایت کرده باشید، کیوب ام ایکس می‌فهمد که نباید کاری به کار آن‌ها داشته باشد و تنها سایر قسمت‌ها را باید تغییر دهد.

اما بگذارید کمی هم از کارهایی بگوییم که CubeMX برایمان تا الان انجام داده. اگر کامنت‌های کنار هر خط را بخوانید به راحتی متوجه می‌شوید که در آنجا چه اتفاقی قرار است بیفتد. خوشبختانه کیوب ام ایکس عزیز به اندازه کافی برایمان کامنت می‌گذارد.

در اولین قدم، برنامه ما به واسطه‌ی فراخوانی تابع HAL_Init پریفرال‌ها را به حالت دیفالت می‌برد و میکروکنترلر را آماده برای تنظیمات بعدی می‌کند. بعد از این کار نوبت به کانفیگ کردن کلاک طبق تنظیماتی که در CubeMX انجام دادیم می‌شود. ما تنها یک پریفرال را فعال کردیم و آنهم gpio بود. از این رو در مرحله بعد همه‌ی کارهای مربوط به این مورد توسط تابع MX_GPIO_Init انجام خواهد شد. در آینده خواهید دید که مشابه با همین نام‌گذاری برای سایر پریفرال‌ها به کار خواهد رفت. مثلاً اگر SPI1 را فعال کنید در تابعی با نام MX_SPI1_Init تنظیمات مربوطه‌اش فعال خواهد شد.

بد نیست به بدنه این تابع نگاهی بیندازید. برای اینکار در truestudio کافی است که کرسر را بر روی نام تابع بیاورید و F3 را فشار دهید. خواهید دید که به بدنه آن هدایت خواهید شد. این کار را برای متغیرها، ثوابت و … نیز می‌توانید انجام دهید که در آن صورت به جایی هدایت خواهید شد که تعریف شده‌اند.

static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

خوشبختانه نام گذاری‌های کتابخانه HAL به نحوی هست که گویای عملکرد آن باشد. این ویژگی بسیار خوبی است که قبلاً در این پست در خصوصش صحبت کردیم.

از تعریف struct ای که برای کانفیگ gpio لازم است بگذریم، به دو خط می‌رسیم که برای فعال کردن کلاک مربوط به gpio نیازند. در میکروکنترلر علاوه بر تنظیمات کلاک اصلی که قبل از فراخوانی این تابع انجام دادیم، لازم است برای هر پریفرالی که می‌خواهیم استفاده کنیم نیز کلاک مربوطه‌اش را فعال کنیم. راستی چرا کلاک GPIOF در اینجا فعال شده است؟! منتظر پاسخ شما در نظرات هستم:)

درست بر طبق همان تنظیماتی که در CubeMX انجام دادیم، این کدها آورده شده است. شما می‌توانید این کدها را از اینجا تغییر دهید مثلاً سرعت تغییر وضعیت پین را بالاتر ببرید. اما باید مراقب باشید که دفعات بعد با CubeMX دوباره پروژه را generate می‌کنید، این تغییرات با همان کانفیگی که در این نرم‌افزار هست جایگزین خواهد شد. پس برای اینکه مشکلی پیش نیاید چه بهتر که تغییرات خودتان را به جای اینجا در فایل CubeMX پروژه انجام دهید و دوباره پروژه را generate کنید.

می‌خواهیم یک لایه پایین‌تر برویم و ببینیم که توابعی که با آن gpio کانفیگ شده، کجا تعریف شده‌اند. پس کرسر را باز بر روی مثلاً HAL_GPIO_Init قرار دهید و F3 را فشار دهید. اینبار به جای فایل main.c به فایل دیگری به نام stm32f0xx_hal_gpio.c هدایت شدیم. این فایل یکی از فایل‌های مجموعه کتابخانه‌ی HAL است که البته کلاً برای gpio نوشته شده است. از طریق پنجره Outline شما می‌توانید به فهرست چیزهایی که در این فایل تعریف شده‌اند دسترسی پیدا کنید. اگر این پنجره برایتان باز نیست از طریق View->Outline می‌توانید آن را باز کنید.

پنجره outline در truestudio - دیجیلاگیست

توضیح تک تک این توابع از حوصله این پست خارج است. اما در آینده با پیشرفت پروژه هر جا که نیاز بود به توضیح آن تابع خواهیم پرداخت.

کاری که قصد داریم در اینجا انجام دهیم چشمک زن کردن ledای است که به پایه PA4 وصل است. تا اینجای کار، ما این پایه را به کمک CubeMX خروجی کردیم و تنها کاری که در اینجا باید انجام دهیم این است که بر روی آن بطور دائم صفر و یک بنویسیم. البته اگر بخواهیم این صفر و یک کردن با چشم قابل مشاهده باشد باید بین این دو نوشتن تاخیری مثلاً 500 میلی ثانیه‌ای وجود داشته باشد.

حالا که الگوریتم کلی برنامه را مشخص کردیم، بریم سراغ پیاده‌سازی آن.

 

بار دیگر به فهرست توابع فایل stm32f0xx_hal_gpio.c نگاه بیندازید. به نظرتان کدام تابع برای کار ما مناسب است؟

اگر درست بررسی کرده باشید باید به مناسب بودن تابع HAL_GPIO_WritePin رسیده باشید. این تابع سه ورودی می‌گیرد. اولی نام پورت است. مقادیری که می‌تواند بگیرد  به شکل کلی GPIOx است که البته جای x با توجه به نام پورت یک حرف انگلیسی قرار می‌گیرد. ورودی بعدی این تابع نام پین مدنظر ما می‌باشد. شکل کلی ورودی‌هایی که می‌توانیم به این آرگومان بدهیم به صورت GPIO_PIN_x است. در اینجا هم به جای x باید شماره پین را بگذاریم. مثلاً شماره 4، که نهایتا می‌شود GPIO_PIN_4. ورودی آخر هم، مقداری است که می‌خواهیم بر روی این پین بنویسیم. قاعدتاً صفر یا یک می‌تواند بگیرد اما بهتر است برای خوانایی بیشتر از تعریف GPIO_PIN_RESET به جای صفر و GPIO_PIN_SET به جای یک استفاده کنیم.

حال تنها چیزی که برای تکمیل برنامه خود نیاز دارید بدانید، نحوه ایجاد تاخیر است. خوشبختانه کتابخانه HAL برای ما امکان ایجاد تاخیر با واحد میلی ثانیه را به راحتی فراهم کرده. کافی است از تابع HAL_Delay برای این کار استفاده کنید. تنها ورودی که این تابع می‌گیرد هم مقداری است که برای تاخیر – به میلی‌ثانیه – نیاز داریم.

 

با توجه به مطالبی که تا الان یاد گرفتید، باید بتوانید این برنامه چشمک زن را بنویسید. بعد از اینکه موفق شدید کد خودتان را با کد زیر مقایسه کنید.

  /* USER CODE BEGIN WHILE */
  while (1) {

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
	HAL_Delay(500);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
	HAL_Delay(500);

  }
  /* USER CODE END 3 */

تست برنامه در عمل:

ما نیاز نیاز داریم تا در حین پروسه برنامه نویسی، مرحله به مرحله تا جایی که نوشتیم را تست و خطایابی کنیم. برای اینکار لازم است که برنامه را بر روی میکروکنترلر پروگرام کنیم. قبل از پروگرام کردن باید پروگرامر خودتان را از یک طرف به USB کامپیوتر و از طرف دیگر پین‌های SWCLK و SWIO و GND آن را به پین‌های مربوطه بر روی میکروکنترلر وصل کنید. علاوه بر این‌ها تغذیه میکروکنترلر هم باید تامین شود که می‌توان از همان 3.3ولت روی پروگرامر برای اینکار استفاده کرد. اما گاهی این تغذیه جوابگوی مدار نیست و عملیات پروگرام کردن با موفقیت انجام نمی‌شود. به همین دلیل بهتر است که تغذیه 3.3 ولت مورد نیاز را از منبع مستقل دیگری بگیریم. البته در این صورت فراموش نکنید که زمین این تغذیه مستقل را هم باید به مدار وصل کنید.

بعد از انجام این اتصالات و کامپایل کامل و بدون خطای برنامه شما کافی است که از طریق Run -> Debug برنامه را بر روی میکروکنترلر بریزید و نتیجه‌ی کار خودتان را ببینید.

تو قسمت بعد به این می‌پردازیم که چه جوری می‌تونیم یک پایه را ورودی کنیم. بعد از اون می‌تونید از طریق کلیدی که به میکروکنترلر وصل شده، به led فرمان روشن یا خاموش شدن رو بدید. 

۱۱ دیدگاه‌ها

  1. عالییییییی بود عزیز خیلی کمکم کرد دستت درد نکنه ادامه بده

  2. کارتون خیلی درسته. ادامه بدین لطف.اگه منابع اموزشی خوبی هم میشناسین معرفی کنین مثلا خودتون چه جوری st رو شروع کردین یا امبد کارکردین؟. واقعن جای این بحثا تو وب فارسی خالیه!(متاسفانه!)

    • سلام نظر لطف شماست. متاسفانه کمبود وقت و تنبلی باعث شده از این برنامه عقب بمونم. ولی سعی میکنم به زودی به روزرسانی بلاگ رو ادامه بدم.

  3. سلام خسته نباشید،آقا من برنامه رو با کلاک داخلی راه اندازی میکنم کار میکنه ولی با کریستال خارجی کار نمیکنه!!تنظیمات رو هم دقیقا مثل تنظیمات شما انجام دادم،البته از سری Stm32f030k6t6 استفاده کردم و کریستال زدم به پایه ۲و۳ و از هر پایه یه خازن ۲۲ پیکو وصل کردم به زمین،
    به نظرتون مشکل کار از کجاست؟

    • سلام
      اگر برد رو خودتون زدید حتماً چک کنید که به درستی لحیم شده. برد رو هم خوب تمیز کنید که روغن لحیم رو برد نمونده باشه. اگر اسکوپ دارید ببینید کریستال یا اسیلاتور فرکانسی که باید بده رو میده.

  4. سلام. نمیدونم چقدر درتس باشه ولی اون کلاک برای پروگرمر باید باشه احتمالا؟ درسته؟

  5. مهدی شفیع

    سلام
    قسمت ospeedr توضیحاتت کمکم کرد من فکر می کردم سرعت کلی کلاک را تغییر میدهد
    نگو سرعت بالا رونده را کنترل می کند ولی بازم نفهمیدم دقیقه واسه چیه اگه میشه بازترش کن

    • سلام، بله در واقع ospeedr میزان slew rate پایه را تغییر می‌دهد. خب همونطور که گفتم اگر برامون مهم نیست رو کمترین سرعت قرارش بدیم بهتره. اما گاهی برای مثال در ارتباط با یک IC خارجی، لازمه که slew rate میزان خاصی باشد وگرنه سیگنال‌ها به درستی شناسایی نخواهند شد، در این صورت باید سرعت صفر و یک شدن پایه‌ها را در حد مطلوب قرار دهیم.

  6. سلام دوست عزیز خداقوت.
    یه قسمت رو اشتباه نوشتید، بخش پوش پول ترانزیستوری اون مدل CMOS در واقع یک گیت NOT هم محسوب میشهع،هنگامی که ولتاژ۰هست ماسفت نوع P فعال میشه و زمانی که ولتاژ مثبت هست (بالاتر از ولتاژ ترشولد)،ترانزیستور پایینی یعنی نوع N فعال میشه.

    • سلام. ممنونم. فکر می‌کنم شما منظورتون ولتاژی که روی in -بر روی شکل- میفته هست، که در این صورت درست میگید. اما من تو متن منظورم این ولتاژ نیست. من ولتاژی که روی out میفته رو میگم که در صورت تنظیم نرم افزاری روی یک، روی آن vcc میفتد و بالعکس در حالت صفر روی آن gnd میفتد.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *