2017-09-27 122 views
1

已有4天了,我正在努力在STM32上設置外部中斷,並且我經歷了大量閱讀和其他人的代碼纔得到它。但沒有運氣。 我有兩個按鈕,當按下其中一個按鈕時,我希望點亮一個LED,這個例子只是爲了讓它工作,我想在繼續和構建代碼的其餘部分之前有一些功能。 如果代碼有點雜亂,我很抱歉,但我正在努力提高我的編碼技能。 我已經通過手冊和數據表,但似乎沒有任何幫助。STM32L1上的外部中斷設置現在不運行ISR

這裏是我的main.c

#include "stm32l1xx_hal.h" 
#include "buttons.h" 

static void MX_GPIO_Init(void); 

bool RightButtonFlag = 0; 
bool LeftButtonFlag = 0; 


int main(void) 
{ 
    HAL_Init(); 
    SystemClock_Config(); 
    controls_Interrupt_Init(); 
    MX_GPIO_Init(); 

    while (1) 
    { 
     if(RightButtonFlag){ 
      Blue_ON(); 
     } 
     if(LeftButtonFlag){ 
      Green_ON(); 
     } 
    } 

} 
static void MX_GPIO_Init(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 

    /* GPIO Ports Clock Enable */ 
    __HAL_RCC_GPIOC_CLK_ENABLE(); 


    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; 
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
{ 

其次stm32l1xx_it.c

#include "stm32l1xx_hal.h" 
#include "stm32l1xx.h" 
#include "stm32l1xx_it.h" 
#include "buttons.h" 

extern volatile uint8_t RightButtonFlag; 
extern volatile uint8_t RightButtonFlag; 

void EXTI15_10_IRQHandler(void) 
{ 
    if(GPIOC->IDR & GPIO_IDR_IDR_10){ 
     RightButtonFlag = 1; 
     EXTI->PR |= EXTI_PR_PR10; 
    } 

    if(GPIOC->IDR & GPIO_IDR_IDR_11){ 
      LeftButtonFlag = 1; 
      EXTI->PR |= EXTI_PR_PR11; 
    } 
} 

buttons.c

void controls_Interrupt_Init(void){ 

    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; /* Enable System Configuration Register */ 


    SYSCFG->EXTICR[3] |= SYSCFG_EXTICR3_EXTI11_PC; /* Set up External Interrupt for Pin 11 Port C */ 
    SYSCFG->EXTICR[3] |= SYSCFG_EXTICR3_EXTI10_PC; /* Set up External Interrupt for Pin 10 Port C */ 

    EXTI->IMR |= EXTI_IMR_MR11; 
    EXTI->IMR |= EXTI_IMR_MR10; 

    EXTI->FTSR |= EXTI_FTSR_TR11; /* Falling trigger Selection Reg. Trigger 11 */ 
    EXTI->FTSR |= EXTI_FTSR_TR10; /* Falling trigger Selection Reg. Trigger 10 */ 

    NVIC_SetPriority(EXTI15_10_IRQn,1); /* Set Interrupt priority for pins 10-15 */ 
    NVIC_EnableIRQ(EXTI15_10_IRQn); /* Enable NVIC for Pins Between 10-15 */ 


} 

和buttons.h

void controls_Interrupt_Init(void); 

#define Blue_ON()   (HAL_GPIO_WritePin(BLUE_LED_PORT, BLUE_LED_PIN, 1)) 
#define Green_ON()   (HAL_GPIO_WritePin(GREEN_LED_PORT, GREEN_LED_PIN, 1)) 
的一部分

我對編碼相當陌生,而且我的經驗很差,我期望把它搞砸得很簡單。

+0

從哪裏調用MX_GPIO_Init()?當你在'EXT15_10_IRQHandler()'上設置一個斷點時,當你按下按鈕時斷點會被觸發嗎? – kkrambo

+0

哦,是的!對不起!它在main()函數中被調用,我通過刪除很多與這個問題無關的東西來縮短這段代碼,但是我必須在事故中刪除MX_GPIO_Init(),但它實際上包含在代碼中。我要編輯這個以避免混淆。 –

+0

我在調試器中注意到在內存視圖中,相應引腳的PR(掛起寄存器)中的位始終爲0,當我嘗試將其設置爲1時,它仍然爲0。 –

回答

3

您必須將標誌聲明爲volatile。這是編譯器的一個暗示,即變量可以隨時改變,與正常的程序流程無關。

volatile bool RightButtonFlag = 0; 
volatile bool LeftButtonFlag = 0; 

當沒有volatile存在,編譯器可以假定國旗從未在主循環改變,優化這樣的說法,這兩個變量將只加載一次,在循環之前。

聲明它們volatile只在中斷處理程序的範圍內沒有好處,因爲優化仍將發生在main(),其中volatile聲明不可見。

將聲明移動到頭文件是一個很好的做法,並且在引用該變量的所有位置都包含該頭。然後編譯器可以檢查這些類型是否確實兼容。

UPDATE

中斷處理程序沒有什麼意義。您設置EXTI檢測到下降邊緣,然後檢查輸入是否爲。由於機械按鈕的彈跳效應,檢查GPIO數據寄存器是不可靠的。

您應該在處理程序中檢查EXTI->PR,並使用簡單賦值而不是|=來重置待處理位,否則可能會意外清除另一個待處理位。

void EXTI15_10_IRQHandler(void) 
{ 
    if(EXTI->PR & EXTI_PR_PR10){ 
     RightButtonFlag = 1; 
     EXTI->PR = EXTI_PR_PR10; 
    } 

    if(EXTI->PR & EXTI_PR_11){ 
     LeftButtonFlag = 1; 
     EXTI->PR = EXTI_PR_PR11; 
    } 
} 

您仍然可以檢查的地方,如果GPIOC->IDR實際上反映了按鈕的狀態,以消除可能的硬件問題。

您也可以嘗試從調試器或代碼中設置EXTI->SWIER來模擬按鈕按下。

+0

感謝您的迴應。我添加了易失性前綴,它並沒有幫助,無論出於何種原因,我試圖用於EXTI的兩個引腳的PR(掛起寄存器)位不會重置爲1,我想它應該設置爲1以等待外部中斷事件。我會深入研究調試器,看看我是否找到其他的東西。 –

+0

您對閱讀'GPIO-> IDR'絕對正確!最重要的是,我將'PUPDR'設置爲雙引腳上拉,並期望它讀取'1',但當按下按鈕以使其工作時,我需要從'GPIO-> IDR'讀'0'。我嘗試在'EXTI-> SWIER'中設置位,並且ButtonFlag成功切換到1,但使用外部中斷運行它仍然沒有運氣。我會深入一點,看看還有什麼不對... –

+0

我發現它!它是'SYSCFG-> EXTICR [x]',其中'EXTICR3'的'x'應該是2。我一直在通過調試器進行挖掘,並且發現我在「EXTICR4」中設置了位,而不是在「EXTICR3」中。就像我提到的那樣,這是一個簡單的菜鳥錯誤。謝謝你的幫助!我實際上通過試圖解決這個問題學到了很多東西。 –