2017-01-03 29 views
2

我有一個我爲Arduino寫的使用中斷的類。目前我需要在主要的Arduino草圖中創建一個ISR實例,然後將其傳遞給類的初始化函數,該函數運行「attachInterrupt」。這是非常糟糕的風格(爲什麼用戶應該知道我甚至使用了中斷?),所以我希望整個事情被包含在類的頭文件和源文件中。如何在Arduino類中創建ISR?

我試圖讓ISR成爲一個靜態的朋友函數,但它不能到達任何類的非靜態成員。所以現在我對這種方法的工作應該是什麼也不應該是靜態的有點困惑。我試圖做看起來就像這樣(源文件和頭在這裏結合,爲方便閱讀)

class myClass{ 
    friend void ISR(); 
    void init(){attachInterrupt(ISR,..,..);} 
} 

static void ISR(){ 
    all sort of stuff using myClass.members; 
} 

但是,編譯罵我在一個靜態函數使用非靜態成員。 我真的很感謝在理解我如何使它工作方面的一些幫助。

+0

「爲什麼要用戶知道,我甚至使用中斷嗎?」因爲你正在使用微控制器的獨特功能,所以他需要知道它,所以他可以計劃如何管理它。如果您針對一個引腳使用電平變化中斷,並且不希望他看到該引腳,那麼他將無法使用每個引腳上的電平變化中斷,因爲ISR已經實現由你。只需創建一個他必須在ISR中調用的函數,或者將宏寫入ISR並請求他將其寫入主代碼 – frarugi87

回答

0

中斷必須是靜態函數(如果它們是成員函數)才能正常工作,所以如果要使用非靜態成員,則需要獲取實例。你可以切實做到的唯一方法就是使用全局變量。

這裏是你如何能做到這一點草圖:

class MyClass { 
    static MyClass *instance; 

    void init() { 
     instance = this; 
     attachInterrupt(...) 
    } 

    // Forward to non-static member function. 
    static void ISRFunc() { 
     instance->ISR(); 
    } 

    // Do your work here. 
    void ISR() { 
     // ... 
    } 
} 

這是很多的方式來設置此一個,但你無法迴避的事實,即中斷本質上是全球性的。在上面的實現中有一些「陷阱」,我忽略了,希望你知道這些。

P.S.還要注意「靜態」有多重含義。它在聲明類成員時有一個含義,而在類之外聲明時則有完全不同的含義(如在聲明static void ISR()中)。在第二種情況下,現代C++編碼風格傾向於使用匿名命名空間而不是static

+0

將「instance」定義爲靜態成員意味着它由MyClass類型的所有對象共享,所以沒有MyClass ::實例,我可以分配給每個MyClass對象 – shayelk

+0

@shayelk:你是說你不能添加靜態成員變量到你的類?爲什麼不? –

+0

我可以添加一個靜態成員變量,但它將成爲該類的所有實例共享的單個變量。我需要該類的每個實例都有自己的中斷函數,它可以更改自己的成員 – shayelk

0

正如@DietrichEpp所說,中斷必須是靜態函數。但是,這是通過在一個類中使用繼承的另一種方法。

步驟1 - 創建一個具有虛擬純InterServ()函數的中斷基類和基於一組枚舉的實例數組。

class IntBase { 
public: 
    virtual void InterServ() = 0; 
}; 

enum eIntNum { 
    INT_DEV1 = 0, 
    INT_DEV2, 
    // ... 
    INT_MAX 
}; 

static IntBase *tInstance[INT_MAX]; 

步驟2 - 每次使用級的中斷將擁有:

  • 構造來存儲實例,
  • 靜態函數ISRFunc()奉獻給該類
  • 一個虛函數InterServ(),從靜態ISRFunc()調用。

class IntDev1編號爲INT_DEV1

class IntDev1 : public IntBase { 
public: 
    IntDev1() { 
     tInstance[INT_DEV1] = this; 
     // attachInterrupt(...) 
    } 
    virtual void InterServ() { 
     // access to local members 
    } 
    static void ISRFunc() { 
     tInstance[INT_DEV1]->InterServ(); 
    } 
};