Kindle Fire Coupon Kindle Fire Coupon 2012 Kindle DX Coupon 2012 Kindle Fire 2 Coupon Amazon Coupon Codes 2012 Kindle DX Coupon PlayStation Vita Coupon kindle touch coupon amazon coupon code kindle touch discount coupon kindle touch coupon 2012 logitech g27 coupon 2012 amazon discount codes
Facebook RSS Reset

Hướng dẫn cách lập trình điều khiển GPIO trên Raspberry pi bằng C++

Bài viết này giới thiệu cách làm thế nào để truy xuất GPIO bằng C++ trên kit RPI . Có 2 cách để thực hiện điều này :

– Cách thứ nhất là tác động trực tiếp tới các thanh ghi GPIO trên RPI giống như phương pháp lập trình vi điều khiển thông thường mà không có hệ điều hành (OS) . Ưu điểm của phương pháp này là hoàn toàn bỏ qua hệ điều hành, các chân GPIO sẽ được truy xuất rất nhanh. Tuy nhiên cách này không an toàn và có thể gây ra xung đột bởi sự truy xuất cùng lúc của nhiều quá trình đến các thanh ghi vật lý trên RPI.

– Cách thứ hai : Sử dụng cách truy xuất GPIO an toàn thông qua driver đã được xây dựng sẵn trên Linux OS. Về cơ bản nó xem mỗi thuộc tính của mỗi chân GPIO như là 1 tập tin. Công việc của ta là thao tác với các tập tin này để điều khiển GPIO. Đây là phương pháp được ưu tiên để truy xuất GPIO .

Bài viết này sẽ trình bày theo cách thứ hai. Mô hình kết nối như sau :

RasberryPiGPIO1

Mục đích của lớp GPIOClass là cho phép điều khiển từng chân GPIO. Lớp này được thiết kế sao cho GPIO pin number được xác định thông qua hàm khởi tạo của lớp GPIOClass. file header “GPIOClass.h” được cung cấp bên dưới :

#ifndef GPIO_CLASS_H
#define GPIO_CLASS_H
#include <string>
using namespace std;
/* GPIO Class
* Purpose: Each object instantiated from this class will control a GPIO pin
* The GPIO pin number must be passed to the overloaded class constructor
*/
class GPIOClass
{
public:
   GPIOClass();  // tạo 1 GPIO object để điều khiển GPIO4 (mặc định)
   GPIOClass(string x); // tạo 1 GPIO object để điều khiển GPIOx, x được truyền vào thông qua hàm khởi tạo
   int export_gpio(); // exports GPIO
   int unexport_gpio(); // unexport GPIO
   int setdir_gpio(string dir); // Set GPIO Direction
   int setval_gpio(string val); // Set GPIO Value (putput pins)
   int getval_gpio(string& val); // Get GPIO Value (input/ output pins)
   string get_gpionum(); // trả về chỉ số GPIO tương ứng với 1 object
private:
   string gpionum; // GPIO number : lưu trữ chỉ số của gpio 
};
#endif

Mỗi object GPIOClass có các hàm thành viên cho phép ta export hoặc unexport GPIO pins, set direction của GPIO pins cũng như get value của GPIO pins. object GPIOClass có 1 biến private để lưu chỉ số GPIO pin.
Dưới đây là nội dung file “GPIOClass.cpp” :

#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include "GPIOClass.h"
using namespace std;
GPIOClass::GPIOClass()
{
   this->gpionum = "4"; //GPIO4 is giá trị mặc định cho hàm khởi tạo không có tham số truyền vào
}
GPIOClass::GPIOClass(string gnum)
{
   this->gpionum = gnum;  // hàm khởi tạo có thông số truyền vào cho gpionum là gnum
}
int GPIOClass::export_gpio()
{
   string export_str = "/sys/class/gpio/export";
   ofstream exportgpio(export_str.c_str()); // Thực hiện mở file "export" . Convert C++ string to C string. Required for all Linux pathnames
   if (exportgpio < 0){
       cout << " OPERATION FAILED: Unable to export GPIO"<< this->gpionum <<" ."<< endl;
       return -1;
   }
   exportgpio << this->gpionum ; //write GPIO number to export
   exportgpio.close(); //close export file
   return 0;
}
int GPIOClass::unexport_gpio()
{
   string unexport_str = "/sys/class/gpio/unexport";
   ofstream unexportgpio(unexport_str.c_str()); //Open unexport file
   if (unexportgpio < 0){
       cout << " OPERATION FAILED: Unable to unexport GPIO"<< this->gpionum <<" ."<< endl;
       return -1;
   }
   unexportgpio << this->gpionum ; //write GPIO number to unexport
   unexportgpio.close(); //close unexport file
   return 0;
}
int GPIOClass::setdir_gpio(string dir)
{
   string setdir_str ="/sys/class/gpio/gpio" + this->gpionum + "/direction";
   ofstream setdirgpio(setdir_str.c_str()); // open direction file for gpio
       if (setdirgpio < 0){
           cout << " OPERATION FAILED: Unable to set direction of GPIO"<< this->gpionum <<" ."<< endl;
           return -1;
       }
       setdirgpio << dir; //write giá trị direction đến direction file (là 'in' hoặc 'out')
       setdirgpio.close(); // close direction file
       return 0;
}
int GPIOClass::setval_gpio(string val)
{
   string setval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
   ofstream setvalgpio(setval_str.c_str()); // open value file for gpio
       if (setvalgpio < 0){
           cout << " OPERATION FAILED: Unable to set the value of GPIO"<< this->gpionum <<" ."<< endl;
           return -1;
       }
       setvalgpio << val ;//write value to value file
       setvalgpio.close();// close value file
       return 0;
}
int GPIOClass::getval_gpio(string& val){
   string getval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
   ifstream getvalgpio(getval_str.c_str());// open value file for gpio
   if (getvalgpio < 0){
       cout << " OPERATION FAILED: Unable to get value of GPIO"<< this->gpionum <<" ."<< endl;
       return -1;
           }
   getvalgpio >> val ;  //read gpio value
   if(val != "0")
       val = "1";
   else
       val = "0";
   getvalgpio.close(); //close the value file
   return 0;
}
string GPIOClass::get_gpionum(){
return this->gpionum;
}

Để open hoặc close file trong C++ ta sử dụng các class ifstream/ofstream (ifstream cho nhập (đọc) từ một file, ofstream cho xuất (ghi) tới một file) và fstream cho nhập/xuất (đọc/ghi) tới một file).
Viết một class để test có tên là “GPIOtest1.cpp” như sau :

#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "GPIOClass.h"
 
using namespace std;
 
int main (void)
{
 
    string inputstate;
    GPIOClass* gpio4 = new GPIOClass("4"); //create new GPIO object to be attached to  GPIO4
    GPIOClass* gpio17 = new GPIOClass("17"); //create new GPIO object to be attached to  GPIO17
 
    gpio4->export_gpio(); //export GPIO4
    gpio17->export_gpio(); //export GPIO17
 
    cout << " GPIO pins exported" << endl;
 
    gpio17->setdir_gpio("in"); //GPIO4 set to output
    gpio4->setdir_gpio("out"); // GPIO17 set to input
 
    cout << " Set GPIO pin directions" << endl;
 
    while(1)
    {
        usleep(500000);  // wait for 0.5 seconds
        gpio17->getval_gpio(inputstate); //read state of GPIO17 input pin
        cout << "Current input pin state is " << inputstate  <<endl;
        if(inputstate == "0") // if input pin is at state "0" i.e. button pressed
        {
            cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
                usleep(20000);
                    cout << "Checking again ....." << endl;
                    gpio17->getval_gpio(inputstate); // checking again to ensure that state "0" is due to button press and not noise
            if(inputstate == "0")
            {
                cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
                gpio4->setval_gpio("1"); // turn LED ON
 
                cout << " Waiting until pin is unpressed....." << endl;
                while (inputstate == "0"){ 
                gpio17->getval_gpio(inputstate);
                };
                cout << "pin is unpressed" << endl;
 
            }
            else
                cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;
 
        }
        gpio4->setval_gpio("0");
 
    }
    cout << "Exiting....." << endl;
    return 0;
}

Chương trình GPIOtest1.cpp khá đơn giản. Đầu tiên nó khởi tạo hai đối tượng GPIOClass để truy xuất đến GPIO4 và GPIO17 (gpio4 và gpio17) trên header 26 chân .Chú ý tên object được đặt tượng trưng cho tên gpio nhưng ta vẫn có thể đặt tên khác.
Các chân GPIO sau đó được export, GPIO4 set thành output và GPIO17 set input. Vòng lặp vô hạn sẽ đọc trạng thái đầu vào tại chân GPIO17. Nếu trạng thái của chân này là ‘0’ nghia là button có thể đã được nhấn. Trạng thái của chân GPIO17 được kiểm tra lại một lần nữa để chắc chắn rằng điều này là đúng và thực hiện set gpio4 lên mức ‘1’ để bật LED. Một vòng lặp khác được thực hiện để kiểm tra rằng nếu GPIO17 vẫn còn đang nhấn thì LED trên GPIO4 vẫn tiếp tục sáng đến khi nào thả nút nhấn trên GPIO17.

Leave a comment

No comments yet.

Leave a Comment