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

HD cách lập trình điều khiển GPIO trên Raspberry pi bằng C++ (Phần 2-kết hợp ngắt)

Nội dung cần xem trước :  http://hethongnhung.com/gioi-thieu-cach-lap-trinh-dieu-khien-gpio-tren-raspberry-pi-bang-c/

Tham khảo : http://man7.org/linux/man-pages/man2/sigaction.2.html

Có một lỗ hổng cơ bản trong chương GPIO ở bài trước.Thông thường khi chương trình đang chạy mà ta muốn thoát chương trình thì hay dùng thao tác đó là sử dụng tổ hợp phím Ctrl-C.Như zậy nếu với đoạn code trên thì chương trình sẽ thoát trực tiếp mà chưa hề được giải phóng bộ nhớ đã cấp cho 2 đối tượng gpio4 và gpio7. Có một cách để giải quyết vấn đề trến là viết hàm xử lý khi có tín hiệu đến (xử lý ngắt mềm) và gán nó đến sự kiện SIGINT (ctrl-C). Điều này cho phép chương trình sẽ nhảy đến signal handler này bất cứ khi nào ctrl-C được nhấn, thay vì thoát trực tiếp chương trình. Hàm xử lý ngắt sau đó có thể khởi tạo một phương pháp thoát chương trình tối ưu hơn ví dụ như giải phóng bộ nhớ và unexport các chân trước khi exit. Bắt đầu vào phân tích code, đầu tiên ta phải include :

 #include <signal.h>

Bước tiếp theo là khai báo và thiết lập một biến cấu trúc là sig_struct như sau :


Dòng đầu tiên mô tả tên của một biến cấu trúc kiểu sigaction có tên là sig_struct. Dòng thứ 2 gán tên của hàm xử lý mà khi có ngắt thì chương trình sẽ nhảy tới đó.Dòng thứ 3 với “sa_flags” mô tả tập hợp các cờ để set các trạng thái tín hiệu ngắt, ở đây mình không quan tâm, cứ set là 0. Dòng cuối cùng của đoạn code trên với sig_struct.sa_mask của cấu trúc sigaction sẽ được khởi tạo empty. sa_mask cho phép ta thiết lập thêm những tín hiệu nào sẽ bị chặn trong suốt quá trình xử lý ngắt.
Hàm sigaction sẽ được dùng để map “sig_struct” với tín hiệu SIGINT mỗi khi cấu trúc sig_struct được hoàn thành.

	if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
        cout << "Problem with sigaction" << endl;
        return -1;
    }

Ta cũng cần viết hàm xử lý ngắt “sig_handler”.Khi ctrl-C được nhấn, chương trình thực thi sẽ nhảy đến hàm xử lý ngắt và set cờ ctrl_c_pressed thành true. Một vòng lặp while trong hàm main sẽ kiểm tra cờ này.Nếu nó được set thành true bởi tín hiệu ngắt thì chương trình sẽ thực hiện các công việc cần thiết để giải phóng bộ nhớ và unexport các pin GPIO theo đúng các.

 void sig_handler(int sig)
{
    write(0,"nCtrl^C pressed in sig handlern",32);
    ctrl_c_pressed = true;
}
//phần kiểm tra ctrl-C :
if(ctrl_c_pressed)
{
    cout << "Ctrl^C Pressed" << endl;
    cout << "unexporting pins" << endl;
    gpio4->unexport_gpio();
    gpio17->unexport_gpio();
    cout << "deallocating GPIO Objects" << endl;
    delete gpio4;
    gpio4 = 0;
    delete gpio17;
    gpio17 =0;
    break;
 
}

Còn đây là toàn bộ code chương trình “GPIOTest2.cpp” . Lưu ý là chương trình phải được chạy dưới quyền user root.

#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "GPIOClass.h"
using namespace std;
 
void sig_handler(int sig);
 
bool ctrl_c_pressed = false;
 
int main (void)
{
 
    struct sigaction sig_struct;
    sig_struct.sa_handler = sig_handler;
    sig_struct.sa_flags = 0;
    sigemptyset(&sig_struct.sa_mask);
 
    if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
        cout << "Problem with sigaction" << endl;
        exit(1);
    }
 
    string inputstate;
    GPIOClass* gpio4 = new GPIOClass("4");
    GPIOClass* gpio17 = new GPIOClass("17");
 
    gpio4->export_gpio();
    gpio17->export_gpio();
 
    cout << " GPIO pins exported" << endl;
 
    gpio17->setdir_gpio("in");
    gpio4->setdir_gpio("out");
 
    cout << " Set GPIO pin directions" << endl;
 
    while(1)
    {
        usleep(500000);
        gpio17->getval_gpio(inputstate);
        cout << "Current input pin state is " << inputstate  <<endl;
        if(inputstate == "0")
        {
           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);
            if(inputstate == "0")
            {
                cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
                gpio4->setval_gpio("1");
 
                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");
 
         if(ctrl_c_pressed)
                    {
                        cout << "Ctrl^C Pressed" << endl;
                        cout << "unexporting pins" << endl;
                        gpio4->unexport_gpio();
                        gpio17->unexport_gpio();
                        cout << "deallocating GPIO Objects" << endl;
                        delete gpio4;
                        gpio4 = 0;
                        delete gpio17;
                        gpio17 =0;
                        break;
 
                    }
 
    }
    cout << "Exiting....." << endl;
    return 0;
}
 
void sig_handler(int sig)
{
    write(0,"nCtrl^C pressed in sig handlern",32);
    ctrl_c_pressed = true;
}

Cách biên dịch chương trình sử dụng g++:
g++ -fpermissive -Wall GPIOClass.cpp GPIOTest2.cpp -o outBin (với outBin là file thực thi được tạo ra sau khi biên dịch.
set quyền thực thi : chmod +x outBin
Chạy chương trình : ./outBin

Leave a comment

No comments yet.

Leave a Comment