آموزش STM32 با توابع HAL قسمت پنجم: GPIO Input & Output

آموزش STM32 با توابع HAL قسمت پنجم: GPIO Input & Output

آموزش STM32 با توابع HAL قسمت پنجم: GPIO Input & Output
آموزش STM32 با توابع HAL قسمت پنجم: GPIO Input & Output

در قسمت‌های پیشین سری آموزش STM32 با توابع HAL، با محیط نرم‌افزار STM32CubeIDE، پیکربندی پروژه و نحوه دیباگ آشنا شدیم. در این قسمت می‌خواهیم اولین پروژه عملی سری آموزش را انجام دهیم و به سراغ کد نویسی و استفاده از توابع HAL برویم. در ابتدا در مورد پایه‌های ورودی خروجی میکرو و جزییات سخت‌افزار GPIO در STM32 صبحت می‌کنیم و سپس به سراغ استفاده از این پایه‌ها در برنامه و تنظیم پایه‌ها به‌عنوان خروجی و یا ورودی برای ارسال یا دریافت فرمان، استفاده خواهیم کرد. با سیسوگ همراه باشی

 

پایه‌های ورودی خروجی همه منظوره (GPIO) در STM32

در میکروکنترلرهای STM32  برای هر پورت همه‌منظوره ورودی/خروجی (I/O)، دو رجیستر تنظیم 32 بیتی، یک رجیستر 32 بیتی به‌منظور Set/Reset کردن، یک رجیستر 16 بیتی برای Reset کردن و همچنین یک رجیستر قفل 32 بیتی، وجود دارد. هرکدام از پورت‌های I/O، به‌طور مستقل قابل‌برنامه‌ریزی هستند. بااین‌حال دسترسی به این پورت‌ها تنها به‌صورت یک کلمه کامل (32 بیتی) امکان‌پذیر است. بدین معنی که نمی‌توان تنها به نصف کلمه یا یک بایت از آن دسترسی داشت. رجیسترهای Set/Reset برای هر پورت، امکان دسترسی خواندن/تغییر رجیسترهای GPIO به‌صورت Atomic را می‌دهد، به این معنی که خطر رخ دادن وقفه در بازه زمانی دسترسی و تغییر رجیسترها وجود نخواهد داشت.

در شکل زیر دیاگرام ساختار سخت‌افزار نمونه یک پایه GPIO نشان داده‌شده است. در این شکل اجزایی از قبیل دیودهای محافظ، مدارهای pull-up،pull-down،‌ push-pull، مدارهای فعال‌سازی/غیر فعال‌سازی حالت خروجی (برای انتخاب ببین ورودی یا خروجی بودن) پایه و همچنین مدار Schmitt-trigger ورودی دیجیتال و آنالوگ، وجود دارند.

 

 

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

 

 

علاوه بر محدودیت‌های ولتاژ، برای جریان نیز حد مشخصی تعریف‌شده است. حداکثر جریانی که از پایه‌های خروجی کشیده می‌شود یا به آن‌ها هدایت می‌شود با توجه به دیتاشیت تعریف می‌شود. معمولاً میزان این جریان، نباید از 25mA تجاوز کند. پس این پارامتر نیز حتماً باید در دیتاشیت میکروکنترلر چک شود و در طراحی و کاربرد لحاظ گردد.

 

 

سرعت پایه‌های GPIO در STM32

برای پایه‌های GPIO در stm32 بسته به ورودی یا خروجی بودن آن‌ها، پارامتر سرعت نیز تعریف می‌شود.

 

سرعت پایه GPIO در حالت ورودی

برای هر پایه GPIO، زمانی که در حالت ورودی تنظیم‌شده باشد، اطلاعات حاضر روی پایه، با هر کلاک بأس (APB2) نمونه‌برداری شده و در Input Data Register نوشته خواهد شد. پس برای پایه‌ها ورودی، سرعت نمونه‌برداری، به‌وسیله سرعت کلاک بأس APB2 تعیین می‌شود.

 

سرعت پایه GPIO در حالت خروجی

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

 

 

در میکروکنترلرهای دیگر، ممکن است سرعت‌های متفاوتی برای پایه‌های خروجی، قابل تنظیم باشد. به‌عنوان‌مثال در میکروکنترلر STM32L432KC، با استفاده از رجیستر کنترل سرعت، می‌توان سرعت پایه‌های خروجی را در 4 حالت سرعت‌پایین، سرعت متوسط، سرعت‌بالا و سرعت خیلی بالا تنظیم نمود. این 4 حالت سرعت بسته به پارامترهایی نظیر مقدار VDDio و مجموع ظرفیت خازنی موجود در پایه موردنظر، محدوده‌های فرکانسی زیر هستند:

سرعت پایین: حدود 10MHz

سرعت متوسط: حدود 50MHz

سرعت بالا: حدود 100MHz

سرعت خیلی بالا: حدود 180MHz

 

 

انجام عملیات بیتی Atomic روی پایه‌های GPIO

در ابتدای متن اشاره شد که عملیات Atomic این امکان را به وجود می‌آورند که بدون نیاز به غیرفعال کردن وقفه‌ها، مقدار بیت‌های رجیسترها را صفر یا یک کنیم. به‌عنوان‌مثال به‌جای مقداردهی به رجیستر  GPIOx_ODR برای تغییر وضعیت پایه‌ها، می‌توان با یک دسترسی Atomic به APB2، وضعیت یک یا چند بیت را تغییر داد. این عمل از طریق نوشتن مقدار 1 منطقی در بیت موردنظر در رجیستر Set/Reset یعنی GPIOx_BSRR یا رجیستر Reset یعنی GPIOx_BRR صورت می‌گیرد.
 

استفاده از وقفه خارجی GPIO در STM32

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

انتخاب پایه‌های دستگاه‌های جانبی (Peripheral Pin Select)

در میکروکنترلرهای STM32، به‌منظور استفاده بهینه از تعداد پایه‌ها در پکیج‌های متفاوت و همچنین بهره‌گیری از قابلیت‌های دستگاه‌های جانبی مختلف میکروکنترلر، امکان نگاشت یا Remap کردن پایه‌ها وجود دارد. بدین‌صورت که برای هر پایه مالتی پلکسری وجود دارد که از میان چندین کارکرد و Peripheral مختلف، عملکرد موردنظر را برای پایه انتخاب کرد. به این طریق و با برنامه‌ریزی رجیستر مربوطه، امکان این وجود دارد که عملکرد بعضی Peripheral ها را روی پایه‌های متفاوتی نگاشت کرد. مزیت این امر در کاربردهایی است که می‌خواهیم با توجه به پکیج و پایه‌های در دسترس طراحی خاصی انجام دهیم و یا از دستگاه‌های جانبی به‌خصوصی بهره بگیریم، بدین‌وسیله ممکن است مسیر کشی بسیار راحت‌تر صورت گیرد.. همچنین درصورتی‌که یک PCB با میکروی متفاوتی طراحی‌شده باشد و بخواهیم میکروکنترلر مورداستفاده را تغییر بدهیم، به این طریق ممکن است بتوانیم تغییرات موردنیاز در PCB را به حداقل برسانیم. مزیت مهم‌تر این قابلیت درجایی است که بخواهیم مثلاً مسیر یک سیگنال پرسرعت را جوری تغییر بدهیم که در معرض نویز کمتری قرار بگیرد، که به‌وسیله قابلیت توضیح داده‌شده، می‌توان مسیر مناسب‌تر برای سیگنال موردنظر، ایجاد کرد.

 

مکانیزم قفل GPIO در STM32

در ابتدای متن اشاره شد که در میکروکنترلرهای STM32، برای هر پورت معمولاً یک رجیستر 32 بیتی قفل نیز وجود دارد. مکانیزم قفل درجایی که کاربرد دارد که بخواهیم تنظیمات پایه‌های IO را “قفل” کنیم. یعنی اینکه در صورت اعمال آن، تنظیمات مربوط به پایه موردنظر تا انجام ریست بعدی، قابل‌تغییر و دست‌کاری نخواهد بود.

 

تنظیمات GPIO

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

تنظیم پایه به عنوان خروجی
  • خروجی به صورت Open-Drain
  • خروجی به صورت Push-Pull
تنظیم پایه به عنوان ورودی
  • ورودی مدار باز یا فلوت (Hi-Z)
  • ورودی در حالت Pull-Up
  • ورودی در حالت Pull-Down
تنظیم در حالت عملکرد ثانویه (Alernate Function)
  • عملکرد ثانویه در حالت Push-Pull
  • عملکرد ثانویه در حالت Open-Drain
تنظیم در حالت آنالوگ
 
GPIO در stm32
 
حالت‌های active low و active high ‎  (‏Pull-up و Pull-down) برای پایه‌‎ها در حالت ورودی و خروجی.
 

جمع بندی نکات GPIO

  • همان‌طور که اشاره شد، همه‌ی پایه‌های GPIO تحمل ولتاژ 5v را ندارند و اکثر پایه‌ها تنها تا 3.3v را تحمل می‌کنند.
  • هر پورت GPIO را که بخواهیم در هرکدام از حالت‌های کاری مورداستفاده قرار دهیم، ضروری است که ابتدا کلاک آن را فعال کنیم.
  • گفته شد که برای پایه‌هایی که در حالت خروجی تنظیم‌شده باشند، سرعت تغییرات یا سوییچ، قابل تنظیم است. این سرعت معمولاً در سه حالت سرعت‌پایین، سرعت متوسط و سرعت‌بالا قابل تنظیم است.
  • برای پایه‌های ورودی اشاره شد سرعت بأس APB2، تعیین‌کننده نرخ نمونه‌برداری تمامی پایه‌های GPIO تنظیم‌شده در حالت ورودی است.
  • برای پایه GPIO، امکان قطع کردن (یا High impedance) کردن پایه وجود دارد. بدین منظور، پایه به‌عنوان ورودی و در حالت Hi-Z تنظیم می‌شود.
  • هنگامی‌که در یک پروژه می‌خواهیم تنظیمات پایه‌های GPIO، بعد از راه‌اندازی سیستم، قابل‌تغییر نباشد، می‌توان با استفاده از مکانیزم قفل، تنظیمات پایه‌های موردنظر را ثابت نگه داشت.
  • در مورد وقفه خارجی، گفته شد که برای تمامی پورت‌ها و پایه‌های GPIO، این نوع وقفه از بخش EXTI، قابل فعال‌سازی است.
 

API های GPIO در HAL

APIهای HAL اصلی و پراستفاده‌ای که برای GPIO تعریف شده‌اند، عبارت‌اند از:

• HAL_GPIO_Init() / HAL_GPIO_DeInit()
• HAL_GPIO_ReadPin() / HAL_GPIO_WritePin()
• HAL_GPIO_TogglePin ()

این API ها به ترتیب برای راه‌اندازی و غیر فعال‌سازی، خواندن ورودی و نوشتن در خروجی، و معکوس کردن حالت پین (از یک به صفر و از صفر به یک)، کاربرد دارند.

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

تنظیم پایه GPIO در حالت خروجی و ارسال سیگنال دیجیتال

در این بخش می‌خواهیم یک پایه GPIO در stm32 را در حالت خروجی تنظیم کنیم و سپس به‌وسیله صفر و یک کردن ولتاژ آن، یک LED را خاموش و روشن کنیم.
 

ایجاد پروژه GPIO Output

مانند روالی که برای ایجاد و پیکربندی پروژه گفتیم، یک پروژه جدید ایجاد می‌کنیم و تنظیمات دیباگ و کلاک آن را مطابق تصاویر زیر انجام می‌دهیم:

 
 
 
همان‌طور که در شکل‌ها نشان داده‌شده است، دیباگ در حالت Serial wire و کلاک سیستم در حالت کریستال تنظیم‌شده‌اند. اکنون یک پایه دلخواه را در حالت خروجی تنظیم می‌کنیم. ما برای این منظور پایه PC13 را انتخاب می‌کنیم که به LED روی بورد متصل است.
 
 
GPIO در stm32
 
سپس از تب Clock Configuration، کلاک سیستم را روی 72MHz تنظیم می‌کنیم؛
 
 
 
اکنون وارد فایل main.c می‌شویم تا کد پروژه را بنویسیم.
 

نوشتن کد پروژه برای کنترل پایه خروجی

در کتابخانه HAL، تابع تعریف‌شده برای تغییر پایه‌های خروجی، GPIO_WritePin نام دارد که در داکیومنت کتابخانه به‌صورت زیر تعریف‌شده است:

 

 

همان‌طور که می‌بینیم، این تابع سه پارامتر ورودی دارد. ورودی اول پورت GPIO مورداستفاده، ورودی دوم پین موردنظر و ورودی سوم حالتی (منطق صفر یا یک) است که می‌خواهیم به آن پایه اعمال کنیم.

اکنون از این دستور برای صفر و یک کردن پایه متصل به LED، یعنی PC13 استفاده می‌کنیم. در تابع int main(void) و قبل از حلقه (1) while کد زیر را می‌نویسیم:

در این کد، ابتدا ولتاژ پایه PC13 را صفر کرده‌ایم. زیرا LED متصل به این پایه به‌صورت Active-low و با سیگنال صفر روشن می‌شود. سپس بعد از 1.5 ثانیه ولتاژ پایه را 1 و درنتیجه LED را خاموش می‌کنیم. بعد از نوشتن کد، از پروژه Build می‌گیریم و سپس برنامه خروجی را روی میکرو Download می‌کنیم. بدین منظور کلید Run () را می‌زنیم یا اینکه از منوی Run، گزینه Run را انتخاب می‌کنیم.

درصورتی‌که همه مراحل گفته‌شده را به‌درستی طی کرده باشیم، مشاهده می‌کنیم که پس از ریست شدن و شروع کار میکروکنت، LED موجود روی بورد برای مدت کوتاهی (1.5 ثانیه) روشن و پس‌ازآن خاموش می‌شود.

 

تنظیم پایه GPIO در حالت ورودی و دریافت سیگنال دیجیتال

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

 

تنظیم پروژه GPIO Input

به‌جای تشکیل یک پروژه جدید، می‌توانیم همان پروژه قبلی را با اعمال تغییراتی برای اضافه شدن ورودی، تنظیم کنیم. مانند شکل زیر یک پایه دیگر GPIO (مثلاً PB12) را در حالت ورودی و به‌صورت Pull-up قرار می‌دهیم:

 

GPIO در stm32

 

پس از تنظیم پایه ورودی، مجددا به سراغ کد میرویم.

 

نوشتن کد پروژه برای خواندن پایه ورودی

در کتابخانه HAL، تابع تعریف‌شده برای تغییر پایه‌های خروجی، GPIO_WritePin نام دارد که در داکیومنت کتابخانه به‌صورت زیر تعریف‌شده است:

 

 

همان‌طور که می‌بینیم، این تابع دو پارامتر ورودی دارد. ورودی اول پورت GPIO مورداستفاده و ورودی دوم پین موردنظر است.

اکنون از این دستور خواندن وضعیت کلید متصل شده به پایه ورودی، یعنی PB12 استفاده می‌کنیم. در تابع int main(void) و در بدنه حلقه (1) while کد زیر را می‌نویسیم:

در این کد، ابتدا شرط فعال بودن (صفر بودن) کلید بررسی می‌شود و درصورتی‌که کلید فعال باشد، LED برای مدت 250 میلی‌ثانیه، روشن و برای 250 میلی‌ثانیه خاموش می‌ماند. سپس در صورت فعال ماندن کلید این فرآیند تکرار خواهد شد. اکنون بعد از نوشتن کد، از پروژه Build می‌گیریم و سپس برنامه خروجی را روی میکرو Download می‌کنیم.

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

در این قسمت از سری آموزش STM32 با توابع HAL، اولین برنامه را توسعه دادیم و با عملیات ابتدایی GPIO در stm32 آشنا شدیم. در قسمت بعدی می‌خواهیم در مورد جزییات بیشتر از GPIO که در این بخش بیان نشدند، صحبت کنیم. با ما همراه باشید.

 
 
 

2 نفر

پــــســنــدیـده انـد

توجه

سیاوش
سیاوش

کارشناس ارشد الکترونیک دیجیتال، علاقه‌مند به یادگیری

دیدگاه ها

0 دیدگاه

پر بحث ترین ها

مسابقه دوم : چالش برنامه نویسی به زبان C

مسابقه دوم : چالش برنامه نویسی به زبان C

مسابقه اول سیسوگ (مسابقه اول: درک سخت افزار) انتقادهای زیادی رو در پی داشت تا جایی که حتی خودمم به نتیجه مسابقه...

Zeus ‌ Zeus ‌
  • 3 سال پیش
راه اندازی LCD گرافیکی Nokia 1661

راه اندازی LCD گرافیکی Nokia 1661

LCD گرافیکی یکی از مهم ترین پارامترهای موجود در طراحی انواع مدارات الکترونیکی پیچیده و حتی ساده است ، نمایش وضعیت و...

Zeus ‌ Zeus ‌
  • 4 سال پیش
ریموت کدلرن و چکونگی دکد کردن آن به همراه سورس برنامه

ریموت کدلرن و چکونگی دکد کردن آن به همراه سورس برنامه

ریموت کنترل امروزه کاربرد زیادی پیدا کرده است؛ از ریموت‌های درب بازکن تا ریموت‌های دزدگیر و کنترل روشنایی همه از یک اصول اولیه پیروی می‌کنند و آن‌هم ارسال اطلاعات به‌صورت بی‌سیم است....

Zeus ‌ Zeus ‌
  • 5 سال پیش
همه چیز درباره ریموت کنترل‌های هاپینگ

همه چیز درباره ریموت کنترل‌های هاپینگ

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

Zeus ‌ Zeus ‌
  • 5 سال پیش
مسابقه سوم: استخراج داده از رشته ها در زبان C

مسابقه سوم: استخراج داده از رشته ها در زبان C

نزدیک به 5 ماه از مسابقه دوم سیسوگ می‌گذره و فکر کردم که بد نیست یک چالش جدید داشته باشیم! البته چالش‌ها...

Zeus ‌ Zeus ‌
  • 2 سال پیش
مسابقه ششم: بزن میکروکنترلر را بسوزون!

مسابقه ششم: بزن میکروکنترلر را بسوزون!

بزنم میکروکنترلر را بسوزونم اونم تو  این شرایط!، طراحی مسابقه از اون چیزی که به نظر می‌رسه سخت‌تر است، باید حواست باشه...

Zeus ‌ Zeus ‌
  • 12 ماه پیش
آموزش قدم به قدم راه اندازی NRF24L01

آموزش قدم به قدم راه اندازی NRF24L01

آموزش قدم به قدم راه اندازی +NRF24L01  با کتابخانه سازگار با انواع میکروکنترلرها و کامپایلرها قبل از اینکه قسمت بشه با ماژول...

رسول خواجوی بجستانی رسول خواجوی بجستانی
  • 3 سال پیش
کار با ماژول تمام عیار mc60 – قسمت دوم – راه اندازی OpenCPU

کار با ماژول تمام عیار mc60 – قسمت دوم – راه اندازی OpenCPU

در قسمت اول به یکسری اطلاعات کلی ماژول mc60 پرداختیم، با نرم افزار QNavigator کار کردیم و یک هدربرد هم برای کار...

Mahdi.h   Mahdi.h  
  • 3 سال پیش
ساخت ماینر با FPGA و ARM

ساخت ماینر با FPGA و ARM

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

Zeus ‌ Zeus ‌
  • 3 سال پیش
مسابقه چهارم: کدام حلقه سریع‌تر است؟

مسابقه چهارم: کدام حلقه سریع‌تر است؟

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

Zeus ‌ Zeus ‌
  • 2 سال پیش
سیـــســـوگ

مرجع متن باز آموزش الکترونیک