GPIO چیست؟
GPIO یا ورودی/خروجی عمومی (general-purpose input/output) پین سیگنال دیجیتال غیرمستقیم در یک مدار مجتمع یا الکترونیکی است که رفتار ورودی یا خروجی آن توسط کاربر در زمان اجرا کنترل می شود و معمولا به صورت پیش فرض غیر فعال اند. عملکرد GPIOها به این صورت است که کاربر با تغییر وضیعت پین ها از عملکرد های در دسترس آن مثل ورودی یا خروجی یا پروتکل های ارتباطی و.. بر حسب نیاز استفاده می کند.
یک درگاه GPIO از گروهی از پین ها تشکیل یافته است، در سری های میکروکنترلر AVR معمولا این درگاه ها 8 تایی هستند ولی در میکروپروسسور های مختلف متفاوت است. به پورت اسامی از حروف اختصاص می یابد و پین ها با اعداد از 0 به بالا شماره گذاری می شوند.
پیکربندی GPIO در برد های Allwinner
ماژول راه انداز GPIO در هسته ی سیستم عامل بایستی با خط CONFIG_GPIO_SUNXI=y پیکربندی شود، این پیکربندی به صورت توکار به همراه سیستم عامل یا به صورت ماژول خارجی انجام می شود. اگر پیکربندی به صورت CONFIG_GPIO_SUNXI=m باشد ماژول مورد نظر در سیستم عامل موجود است ولی نکته ی مهم اینست که بایستی ماژول ها قبل استفاده با دستور modprobe Module_Name بارگذاری شوند.
توجه به این نکته ضروری است که این آموزش مربوط به سری sunxi می باشد، بنابرین تعاریف برای برد های مشابه قابل استفاده نیست ولی ساختار مشابهی دارد.
نمونه ای از تعریف GPIO در فایل Config (این فایل قبل از کامپایل هسته برای برد sunxi مورد استفاده می گیرد) و بستگی به تعریف، تعدادی از اجزا همراه هسته و یا به صورت ماژول به آن افزوده می شوند.
# # Memory mapped GPIO drivers: # CONFIG_GPIO_SUNXI=m
بارگذاری ماژول در هسته لینوکس
دستور modprobe برای بارگذاری ماژول استفاده می شود. ماژول های قابل بارگذاری را می توان در فایل /etc/conf.d/modules تعریف کرد تا آنها را در طول فرآیند init بارگذاری کند، دستور زیر برای بارگذاری استفاده می شود:
# modprobe module_name
جدا سازی ماژول از هسته لینوکس
برای جدا سازی (از دسترس خارج کردن) ماژول ها، مطابق دستور زیر عمل می کنیم:
# modprobe -r module_name
همچنین برای جلوگیری از بارگیری ماژول، آن را به یک فایل در /etc/modprobe.d/ اضافه کنید، در کادر زیر آدرس به همراه محتوای نمونه نمایش داده شده است:
/etc/modprobe.d/blacklist.conf blacklist module_name_spi blacklist module_name_i2c
پیکربندی GPIO و انتقال به برد
تبدیل فایل اسکریپت به فایل Fex توسط ابزار sunxi-tools در بخش آموزش قرار داده شده است. برای ادامه بایستی توسط ویرایشگر متن، فایل اسکریپت برای پیکربندی GPIOها ویرایش شود. بخش [gpio_para] را در فایل اسکریپت بیابید. اگر چنین قسمتی در فایل وجود ندارد، می توانید در انتهای فایل این قسمت را با توجه به قرار داد های فایل Fex ایجاد کنید، به عنوان نمونه:
[gpio_para] gpio_used = 1 gpio_num = 4 gpio_pin_1 = port:PH10<1><0> gpio_pin_2 = port:PH20<1><0> gpio_pin_3 = port:PB03<0> gpio_pin_4 = port:PH22<1><0>
پیکربندی gpio_para
در قسمت [gpio_para]، با تغییر دادن مقدار gpio_used به 1، استفاده از واحد gpio را فعال می کنیم، در قسمت gpio_num تعداد پین هایی که بایستی به عنوان gpio شناخته شوند را با عدد مشخص می کنیم، بعد از پیکربندی بایستی مطابق قرار داد های فایل Fex به تعریف ویژگی های gpio بپردازیم:
port:
بعنوان مثال:
gpio_pin_3 = port:PB03<0>
تولید فایل script.bin و انتقال به برد
اکنون می بایست فایل متنی Fex را توسط sunxi-tools به فایل باینری تبدیل کرده و در سیستم عامل (با توجه به اینکه سیتم عامل بر روی حافظه nand یا sdcard نصب شده است) با فایل باینری قبلی جایگزین کنید، بعد از ریست سیستم پیکربندی جدید در سیستم اعمال می گردد.
دقت کنید که ولتاژ کاری بورد های ARM در محدوده ی 3.3 ولت است، بنابرین ولتاژ اعمالی به پین ها نباید بالاتر از 3.3 ولت باشد. همچنین از پین های خروجی در حالت HIGH، ولتاژ 3.3v قابل مشاهده خواهد بود. این قاعده مربوط به پین های تغذیه ی موجود در کنار PIN ها نمی شود، زیرا این پین ها در ارتباط به پردازنده نبوده و مستقیما به منبع ورودی 5 ولت GND و.. وصل شده اند. برخی برد های توسعه مانند برد های Odroid سطح ولتاژ پایین تری دارند. بنابرین قبل از استفاده از واسط IO اطلاعات فنی کامل مطالعه شود.
فضای کاری GPIO
لینوکس با استفاده از sysfs توانایی وارد کردن کنترل و وضعیت GPIO برای استفاده در برنامه های کاربردی را داراست. در آن صورت هیچ راه انداز دیگری نمی تواند به GPIO مورد استفاده دسترسی داشته باشد. از ابزارهای ساده مانند cat و echo می توان برای خواندن مقدار فعلی ورودی GPIO یا تنظیم سطح خروجی GPIO استفاده کرد.
فعال کردن GPIO در فضای کاری
با دستور زیر می توانید در ترمینال لینوکس، تمام GPIO ها با وضیعت export مشاهده نمایید:
$ sudu su $ cd /sys/class/gpio/ $ ls $ export gpiochip1 unexport
در دایرکتوری GPIO می توانید پین های export شده را ببینید، ولی فعلا موردی برای export انتخاب نشده است:
$ echo 1 > /sys/class/gpio/export
این دستور به معنی فراخوانی gpio_pin_1 که در لیست فایل Fex یا در لیست GPIO های برد مورد نظر بعنوان اولین پین تعریف شده است می باشد، دستور export پین مورد نظر را آماده ی اجرا می کند، همچنین با تغییر این دستور و اعمال unexport می توانیم پین مورد نظر را از دسترس خارج کنیم، اگر از دستور مرحله قبل استفاده کنیم، با دستور ls، نام پین مورد نظر نمایش داده می شود:
$ ls $ export gpio1_ph10 gpiochip1 unexport
gpio1_ph10 نام اولین GPIO تعریف شده در فایل Fex یا در لیست GPIO های برد مورد نظر می باشد.
دستکاری GPIO در فضای کاری
این امکان وجود دارد که به ازای همه ی پین های تعریف شده این فراخوانی انجام شود، این درحالی است که عمل cd باعث انتقال شما به دایرکتوری ایجاد شده ی پین می شود، بعد از انتقال به این دایرکتوری شما می توانید عملگرهای موجود در این دایرکتوری را توسط دستور ls مشاهده کنید:
$ cd gpio1_ph10 $ ls $ active_low direction edge power subsystem uevent value
در نوشتن دستورات فرض بر این است که شما دایرکتوری فعلی نشان داده شده در خط ترمینال را تغییر نداده باشید و این دستورات را در مسیر اصلی /sys/class/gpio/ انجام دهید. بنابرین دستورات مربوط به هر پین در دایرکتوری فرعی مربوط به خود آن انجام می شود. برای تغییر پین انتخابی توسط دستور cd، می توانید به آدرس /sys/class/gpio/ برگشته و به دایرکتوری فرعی پین دیگری تغییر مسیر دهید.
تعیین جهت GPIO
برای اینکه تعیین کنید GPIO ورودی است یا خروجی، می توانید توسط دستور زیر انجام دهید:
$ echo out > direction
این دستور در دایرکتوری فرعی، جهت پین را به out تغییر می دهد و امکان استفاده از پین به عنوان output را فراهم می کند.
نوشتن مقدار در GPIO
برای نوشتن مقدار در خروجی دیجیتال، می توانیم مقدار 0 یا 1 را با دستور echo وارد کنیم:
$ echo 1 > value
دستور فوق مقدار منطقی 1 را به خروجی می فرستد.
دقت کنید که مقدار منطقی در این برد های توسعه لینوکس نظیر رسپری پای یا کوبی برد ولتاژ 3.3v است، بنابرین توسط ولت متر این مقدار در خروجی پین قابل رویت خواهد بود، برای جلوگیری از اشتباه و تعیین مکان دقیق پین مورد نظر در بورد از شماتیک سخت افزاری استفاده کنید.
همچنین برای تست 0 منطقی، کافیست از دستور زیر استفاده کنیم:
$ echo 0 > value
خواندن مقدار از GPIO
برای اینکه در اجرای ایین مرحله با مشکل مواجه نشوید نکات زیر را رعایت فرمایید:
- بر روی BreadBoard اقدام به نصب PushButton کنید.
- پین مورد نظر را به ترمینال PushButton متصل کنید.
- ولتاژ 3.3v از برد را با توحه به شماتیک پین ها به PushButton متصل کنید، می توانید از رگلاتور ولتاژ جهت تبدیل سطح 5v به 3.3v نیز استفاده نمایید.
- برای پایدار کردن مقدار ورودی استفاده از مقاومت Pull-down توصیه می شود، در این شرایط پین مورد نظر در دو منطقی صفر و یک، پایدار خواهد بود.
تعیین پین به عنوان ورودی
با export پین مورد نظر، با دستور cd به دایرکتوری پین مورد نظر بروید:
$ echo 1 > /sys/class/gpio/export $ ls $ export gpio1_ph10 gpiochip1 unexport $ cd gpio1_ph10 $ ls
هم اکنون می توانید جهت پین مورد نظر را با دستور زیر تعیین کنید:
$ echo in > direction
برای خواندن مقدار ورودی به پین، بایستی از دستور cat استفاده کنیم. این دستور محتوای پین را در ترمینال چاپ خواهد کرد. این دستور کاربرد های دیگری نیز دارد، ولی در این نمونه مقدار value مربوط به ورودی را چاپ می کند:
$ cat value
از دستوز cat می توانید متوالیاً برای مشاهده مقدار پین استفاده کنید و تغییرات ورودی را با تغییر مقدار چاپ شده به صورت 0 یا 1 مشاهده نمایید.
$ cat value 1
استفاده از shell scripts
اسکریپت shell فایلی است که شامل یک سری دستورات (مشابه دستورات نوشته شده برای کنترل پین با دریافت یا ارسال مقدار) است. به عنوان نمونه اسکریپت زیر را مشاهده کنید:
#!/bin/bash echo Exporting pin $1. echo $1 > /sys/class/gpio/export echo Setting direction to out. echo out > /sys/class/gpio/gpio$1/direction echo Setting pin high. echo 1 > /sys/class/gpio/gpio$1/value
- این خط برای اسکریپت shell الزامیست.
- $1 مربوط به آرگومان پین است.
- به جای استفاده از نام پین، از آرگومان بعنوان شماره پین استفاده کرده است.
- آرگومان مورد نظر در تمامی خطوط به جای 1$ قرار خواهد گرفت.
بعد نوشتن اسکریپت به صورت text، آنرا به صورت Name.sh ذخیره کنید و برای قابل اجرا کردن این اسکریپت باید از دستور chmod استفاده کنید:
$ chmod +x Name.sh
اکنون کافیست دستور مورد نظر در حالت Root اجرا شود، بنابرین بعد اجرای دستور sudo su می توانید اسکریپت را اجرا کنید:
$ sudu su $ ./Name.sh 10 Exporting pin Setting direction to out. Setting pin high.
علامت ./ قبل نام فایل نشان دهنده ی اجرای اسکریپت مورد نظر در دایرکتوری فعلی است.
کنترل GPIO با کد C
ارتباط با سخت افزار توسط زبان های برنامه نویسی همانند C و پایتون (یا زبان های رایج دیگر) از جمله نیاز کاربران در کنترل سخت افزار است. این نیاز وقتی جدی تر می شود که با سیستمی سر وکار پیدا می کنیم که بر پایه ی ارتباط با وسایل جانبی دیگر از جمله سنسور و موتور و دیگر برد ها قرار دارد، از این رو کار با محیط ترمینال تنها برای خطا یابی و تست کارکرد صحیح اینترفیس ها ضروریست ولی برای بهره برداری دائم و حرفه ای تر نیازمند پیاده سازی کد توسط زبان برنامه نویسی است.
#include "stdlib.h" #include "stdio.h" #include "gpio_lib.h" #define PD0 SUNXI_GPD(0) #define PD1 SUNXI_GPD(1) #define PD2 SUNXI_GPD(2) #define PD3 SUNXI_GPD(3) #define PD4 SUNXI_GPD(4) #define MISO SUNXI_GPE(3) #define MOSI SUNXI_GPE(2) #define SCK SUNXI_GPE(1) #define CS SUNXI_GPE(0) int main() { if(SETUP_OK!=sunxi_gpio_init()){ printf("Failed to initialize GPIO\n"); return -1; } if(SETUP_OK!=sunxi_gpio_set_cfgpin(PD01,OUTPUT)){ printf("Failed to config GPIO pin\n"); return -1; } int i; for(i=0;i<5;i++){ if(sunxi_gpio_output(PD01,HIGH)){ printf("Failed to set GPIO pin value\n"); return -1; } usleep(500000); if(sunxi_gpio_output(PD01,LOW)){ printf("Failed to set GPIO pin value\n"); return -1; } usleep(500000); } sunxi_gpio_cleanup(); return 0; }
این کد برای سری sunxi می باشد، برای برد هایی نظیر رسپری پای یا Odroid کد نمونه C بسیار ساده تر می باشد.
می توانید با دانلود مجموعه فایل های مورد نیاز از gpio، دستورات زیر را برای اجرا در ترمینال انجام دهید:
$sudo apt-get install gcc build-essential $tar -xf gpio.tar $cd gpio/ $gcc gpio_lib.c -c $gcc gpio.c -c $gcc gpio.o gpio_lib.o -o gpio $./gpio
دیدگاه خود را ثبت کنید
تمایل دارید در گفتگوها شرکت کنید؟در گفتگو ها شرکت کنید.