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

برای اینکه در اجرای ایین مرحله با مشکل مواجه نشوید نکات زیر را رعایت فرمایید:

  1. بر روی BreadBoard اقدام به نصب PushButton کنید.
  2. پین مورد نظر را به ترمینال PushButton متصل کنید.
  3. ولتاژ 3.3v از برد را با توحه به شماتیک پین ها به PushButton متصل کنید، می توانید از رگلاتور ولتاژ جهت تبدیل سطح  5v به 3.3v نیز استفاده نمایید.
  4. برای پایدار کردن مقدار ورودی استفاده از مقاومت Pull-down توصیه می شود، در این شرایط پین مورد نظر در دو منطقی صفر و یک، پایدار خواهد بود.
مدار راه اندازی gpio و led

تعیین پین به عنوان ورودی

با 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
  1. این خط برای اسکریپت shell الزامیست.
  2. $1 مربوط به آرگومان پین است.
  3. به جای استفاده از نام پین، از آرگومان بعنوان شماره پین استفاده کرده است.
  4. آرگومان مورد نظر در تمامی خطوط به جای 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
0 پاسخ

دیدگاه خود را ثبت کنید

تمایل دارید در گفتگوها شرکت کنید؟
در گفتگو ها شرکت کنید.

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

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