در پست قبل یاد گرفتیم چگونه میتوان پایه میکرو را به صورت GPIO_Output کانفیگ کرد و در ادامه با ساخت پروژه led چشمک زن چیزهایی که یاد گرفتیم را در معرض آزمون قرار دادیم. در این قسمت میخواهیم به نحوهی ورودی کردن GPIO بپردازیم. مثال سادهای هم که برای این قسمت در نظر گرفتم، خواندن وضعیت یک کلید – از نوع tactile button– است. برای ارجاع راحتتر، نام مثال این قسمت را هم پروژه کنترل led با تک سوئیچ میگذاریم.
همانطور که اشاره کردم، کلیدی که در اینجا مد نظر ماست یک تک سوئیچ – tactile switch – ساده میباشد که بسته به مداری که طراحی میکنیم، صفر یا یک را روی پایه میکروکنترلر قرار میدهد. اصولاً یکی از دو شماتیک زیر نشاندهنده مداری است که ما کلید را به میکرو وصل میکنیم.
پول آپ و پول داون کردن یک پایه:
اگرچه در پست خروجی کردن gpio توضیح کوتاهی در خصوص مفهوم پول آپ و پول داون دادیم. اما بد نیست که هم برای یادآوری و هم توضیح کاملتر پاراگراف بعدی را بخوانید.
در یک مدار دیجیتال، به مقاومتی که بین VCC+ و پایه آیسی قرار میگیرد، مقاومت پول آپ میگویند. این کار باعث میشود تا هنگامی که به این پایه، مدار دیگری وصل نیست یا مداری وصل است که مقاومت ورودیاش بسیار بالاست -High Impedance- ما مطمئن باشیم که مقدار یک دیجیتال بر روی پایه قرار میگیرد. بطور عکس، اگر این مقاومت بین VCC- (یا GND) و پایه آی سی قرار گیرد، به آن مقاومت پول داون میگویند.
بعضی از میکروکنترلرها این قابلیت را دارند که به صورت داخلی و با فرمان نرمافزاری Pull Up یا Pull Down شوند. هر چند در صنعت برای اطمینان بیشتر گاهی توصیه نمیشود از این قابلیت داخلی استفاده کنیم.
بار دیگر به دو شماتیک بالا توجه کنید. تفاوت این دو در چیست؟
بله، در یکی ما پایه را Pull up کردهایم و در دیگری Pull Down. در صورتی که پایه ما Pull up باشد، بطور عادی مقدار 3.3 ولت یا یک دیجیتال را بر روی این پایه خواهیم داشت و اگر کلید فشرده شود مقدار 0 ولت یا صفر دیجیتال بر روی پایه قرار میگیرد. برعکس همین ماجرا برای حالت Pull down برقرار است.
با این حساب برای اینکه بفهمیم کلید فشرده شده یا خیر، بایست مقدار دیجیتال اعمال شده به پایه در حالت GPIO_Input را بفهمیم. بعد از اینکه وضعیت کلید را مشخص کردیم، میتوان تصمیم گرفت در صورتی که کلید فشرده شد، چه کاری باید صورت بگیرد.
در پروژه led چشمک زن، از پین PA4 برای کنترل LED روی برد، استفاده کردیم. در پروژهی این پست –کنترل led با تک سوئیچ– هم نیاز است تا همان کارهایی که در آنجا انجام دادیم را تکرار کنیم با این تفاوت که قرار است یک ورودی GPIO برای اتصال به تک سوئیچ به آن اضافه کنیم.
شما میتوانید این پروژه را در CubeMX، از صفر شروع به ساختن کنید تا با تکرار آموختههای قبلی، مطالب در ذهنتان بهتر تثبیت شود. اما اگر نیازی به این کار نمیبینید، میتوانید پس از باز کردن فایل .ioc پروژه led چشمک زن، به منوی فایل بروید و با کلیک بر روی save as یک نسخه جدید از این فایل را با نام و محل ذخیره جدید، ایجاد کنید.
من پین PB1 را برای اتصال به تک سوئیچ انتخاب کردم. در این صورت با کلیک بر روی این پین در تب Pinout & Configuration و انتخاب گزینه GPIO_Input، آن را به عنوان ورودی کانفیگ میکنیم. برای تنظیمات بیشتر مانند دفعهی قبل از گزینههای سمت چپ صفحه GPIO و از لیست پینهای باز شده PB1 را انتخاب میکنیم.
بهتر است برای راحتی کار در اینجا Pull up داخلی PB1 را فعال کنیم. با این کار دیگر نیازی به اضافه کردن یک مقاومت به مدارخودمان نخواهیم داشت. من برای خوانایی بهتر برنامه برای این پین یک label با نام button قرار دادم. در ادامه خواهید دید که در برنامه به جای استفاده از PB1 از این کلمه استفاده خواهم کرد. این کار به خصوص در برنامههایی که قرار است پینهای زیادی کانفیگ شوند، اهمیت بالایی در خوانایی برنامه دارد. از این رو توصیه میکنم که شما هم از این امکان بهره ببرید و برای پینهای خودتان label تعریف کنید.
بعد از همهی این کارها نوبت به generate کردن پروژه میرسد. پس این کار را انجام دهید و با truestudio پروژه خودتان را باز کنید. از آنجا که این بار هم قصد کار کردن با GPIO را داریم، همانند دفعهی قبل فایل stm32f0xx_hal_gpio.c را از طریق Project Explorer پیدا کرده و آن را باز کنید. بار دیگر از طریق پنجرهی Outline به فهرست توابع تعریف شده این فایل نگاهی بیندازید. به نظرتان این بار کدام تابع برای خواندن پین به کار میآید؟
احتمالاً حدس زده اید که تابع زیر همان چیزی است که به آن نیاز داریم:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
واضح است که در اینجا هم به جای آرگومان اول نام پورت را باید قرار دهیم و به جای آرگومان دوم نام پایهای از این پورت که میخواهیم بخوانیم.
با توجه به توضیحاتی که تا الان گفته شد، باید بتوانید برنامه را خودتان بنویسید. سعی کنید بدون کمک گرفتن از کسی این کار را انجام دهید. میتوانید مطالب جلسات قبل و یا حتی همین پست را دوباره یا حتی چند باره بخوانید. از این کار هیچ ترسی نداشته باشید. چیزی که از آن باید ترسید، فرارِ از فکر کردن و صبر نداشتن است. این راهیست که باید طی شود و هیچ قرصی هم ندارد. لطفاً صبور باشید، تا به نتیجه برسید و شیرینیاش را بچشید:)
برای تست عملی برنامه نیاز دارید تا یک تک سوئیچ را از یک سمت به PB1 و از سمت دیگر به زمین، وصل کنید. این کار را میتوانید به کمک یک سیم جامپر و برد بورد انجام دهید.
با این حال، کد زیر به جهت مقایسه با برنامه ای که نوشته اید آورده شده.
هشدار مجدد:
“دیدن این کد، قبل از هرگونه تلاش و فکر کردن هرگز توصیه نمیشود.”
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(HAL_GPIO_ReadPin(button_GPIO_Port, button_Pin) == GPIO_PIN_RESET) { //button is pressed, so turn led on. HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, GPIO_PIN_SET); } else { //button is released, so turn led off. HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, GPIO_PIN_RESET); } } /* USER CODE END 3 */
تمرین:
به عنوان تمرین بیشتر برنامهای بنویسید که با هر بار فشار دادن تک سوئیچ، وضعیت led از خاموش به روشن یا از روشن به خاموش تغییر کند.