2017-09-27 10 views
1

으로 실행되지 않습니다. STM32에서 외부 인터럽트를 설정하는 데 어려움을 겪고 있으며, 많은 독서를하고 다른 사람들의 코드를 사용하고 있습니다. 그러나 운이 없다. 두 개의 버튼이 있는데 둘 중 하나를 누르면 LED가 켜질 것으로 예상됩니다.이 예제는 작동시키기위한 것일뿐입니다. 진행하기 전에 기능을 갖추고 싶었고 나머지 코드를 빌드하고 싶었습니다. 코드가 약간 지저분한 경우 미안하지만 코딩 기술을 신경 쓰지 않도록 노력하고 있습니다. 설명서 및 데이터 시트를 살펴 보았지만 아무 도움도되지 않습니다. 여기 STM32L1의 외부 인터럽트 설정이 4 일 동안 ISR

는 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)) 
의 일부 얹는 내 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); 
{ 

입니다

코딩에 익숙하지 않고 불쌍한 경험으로 아주 간단한 것을 망쳐 놓을 것으로 예상됩니다.

+0

'MX_GPIO_Init()'는 어디에서 호출하나요? 'EXT15_10_IRQHandler()'에 중단 점을 설정하면 버튼을 누를 때 중단 점에 충돌합니까? – kkrambo

+0

오, 그래! 미안 해요! main() 함수에서 호출되었으며이 문제와 관련이없는 많은 항목을 제거하여이 코드를 줄였습니다. MX_GPIO_Init()를 사고로 제거해야합니다. 실제 코드에 포함되어 있습니다. 혼란을 피하기 위해 이것을 편집 할 것입니다. –

+0

메모리 뷰에서 해당 핀에 대한 PR (보류중인 레지스터)의 비트가 항상 0이며 디버거에서 1로 설정하려고 시도하면 디버거가 0으로 유지된다는 것을 알았습니다. –

답변

3

플래그를 volatile으로 선언해야합니다. 변수가 정상적인 프로그램 흐름과 관계없이 언제든지 변경 될 수 있다는 것을 컴파일러에게 알려주는 힌트입니다. 거기에는 volatile이없는 경우

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

, 컴파일러는 변수가 루프 전에 한 번만로드됩니다, 플래그는 메인 루프에서 변하지 않는 것으로 가정하고, 그 방법을 최적화 할 수 있습니다.

volatile 선언이 표시되지 않는 최적화가 여전히 main()에서 발생하므로 인터럽트 처리기의 범위에서만 volatile을 선언하면 좋지 않습니다.

선언을 헤더 파일로 옮기고 변수가 참조되는 모든 위치에 해당 헤더를 포함하는 것이 좋습니다. 그런 다음 컴파일러는 유형이 실제로 호환되는지 확인할 수 있습니다.

UPDATE

인터럽트 핸들러는 거의 의미가 있습니다. EXT를 설정하여 에지가 에지로 떨어지면 입력이 높음인지 확인하십시오. 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 (Pending Register) 비트가 1로 재설정되지 않고 1로 설정되어야한다고 생각합니다. 외부 인터럽트 이벤트를 기다려야합니다. 나는 디버거를 더 깊이 들여다보고 다른 것을 찾는다. –

+0

'GPIO-> IDR'을 읽는 것이 옳습니다! 그것의 꼭대기에 나는 'PUPDR'을 두 핀들을 풀 업 (pullup)하도록 설정하고 '1'을 읽을 것을 기대했지만 'GPIO-> IDR'에서 '0'을 읽을 필요가있었습니다. 'EXTI-> SWIER'에서 비트 설정을 시도했지만 ButtonFlag가 1로 성공적으로 전환되었지만 외부 인터럽트를 사용하여 실행하는 것은 여전히 ​​불행합니다. 나는 조금 더 깊은 것을 파헤 치고, 그 밖의 무엇이 잘못되었는지에 관해 알 것이다. ... –

+0

나는 그것을 발견했다! 그것은'SYSCFG-> EXTICR [x]'였습니다. 여기서'x'는'EXTICR3'에 대해 2가되어야합니다. 나는 디버거를 계속 파고 있었고'EXTICR3'과 반대로'EXTICR4'에서 비트를 설정하고있는 것을 보았습니다. 내가 언급 한 것처럼, 그것은 신참 간단한 실수였다. 당신의 도움을 주셔서 감사합니다! 나는이 문제를 해결하려고 노력하여 실제로 1 톤을 배웠다. –