GPIO ustawiam:
GPIOA->CRL &= ~GPIO_CRL_CNF0_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF0_1;Puszczam zegar do EXTI (w tym procku AFIO):
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;Zdejmuję maskę z interesujących pinów:
EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR2 | EXTI_IMR_MR3 | EXTI_IMR_MR4;Ustawiam reakcję na zbocze narastające:
EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR2 | EXTI_RTSR_TR3 | EXTI_RTSR_TR4;Dodaję priorytety przerwania i uruchamiam przerwania (tu tylko po jednym żeby nie mnożyć):
NVIC_SetPriority(EXTI0_IRQn, 1);
NVIC_EnableIRQ(EXTI0_IRQn);Przykładowe przerwanie:
__attribute__((section(".after_vectors"))) void EXTI0_IRQHandler()
{
printf("++ \r\n");
EXTI->PR |= EXTI_PR_PR0;
}
Co bym nie robił tak działa tylko jedno przerwanie i to z PA2. Wiązać pinów z EXTI niby nie muszę (po resecie akurat się zgrywają), ale robię to dla pewności, nie widzę już gdzie szukać. W komentarzu dla czytelności wrzucam cały kod okrojony do obsługi EXTI.
Co mogę robić źle albo gdzie szukać? Do debugowania mam UART i LEDa ( ͡° ͜ʖ ͡°)
#stm32 #embedded #programowanie #baremetal
static void gpio_init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// BUT_CANC (PA0)
GPIOA->CRL &= ~GPIO_CRL_CNF0_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF0_1;
// (PA1)
GPIOA->CRL &= ~GPIO_CRL_CNF1_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF1_1;
// (PA2)
GPIOA->CRL &= ~GPIO_CRL_CNF2_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF2_1;
// (PA3)
GPIOA->CRL &= ~GPIO_CRL_CNF3_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF3_1;
// (PA4)
GPIOA->CRL &= ~GPIO_CRL_CNF4_0; // floating input to pull-down
GPIOA->CRL |= GPIO_CRL_CNF4_1;
}
static void exti_init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR2 | EXTI_IMR_MR3 | EXTI_IMR_MR4;
EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR2 | EXTI_RTSR_TR3 | EXTI_RTSR_TR4;
// connect pin to interrupt
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA;
AFIO->EXTICR[1] |= AFIO_EXTICR1_EXTI1_PA;
AFIO->EXTICR[2] |= AFIO_EXTICR1_EXTI2_PA;
AFIO->EXTICR[3] |= AFIO_EXTICR1_EXTI3_PA;
AFIO->EXTICR[0] |= AFIO_EXTICR2_EXTI4_PA;
NVIC_SetPriority(EXTI0_IRQn, 1);
NVIC_SetPriority(EXTI1_IRQn, 2);
NVIC_SetPriority(EXTI2_IRQn, 2);
NVIC_SetPriority(EXTI3_IRQn, 1);
NVIC_SetPriority(EXTI4_IRQn, 1);
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI2_IRQn);
NVIC_EnableIRQ(EXTI3_IRQn);
NVIC_EnableIRQ(EXTI4_IRQn);
}
__attribute__((section(".after_vectors"))) void EXTI0_IRQHandler()
{
EXTI->PR |= EXTI_PR_PR0;
}
__attribute__((section(".after_vectors"))) void EXTI1_IRQHandler()
{
EXTI->PR |= EXTI_PR_PR1;
}
__attribute__((section(".after_vectors"))) void EXTI2_IRQHandler()
{
EXTI->PR |= EXTI_PR_PR2;
}
__attribute__((section(".after_vectors"))) void EXTI3_IRQHandler()
{
EXTI->PR |= EXTI_PR_PR3;
}
__attribute__((section(".after_vectors"))) void EXTI4_IRQHandler()
{
EXTI->PR |= EXTI_PR_PR4;
}
Mam nadzieję, że formatowanie przetrwa.
Nie zeby to cos zmienilo (bo to wszystko sa zera) ale EXTI0...3 sa w AFIO->EXTICR[0] a EXTI4 w AFIO->EXTICR[1].
W ramach debugowania sprobuj wywolac przerwanie programowe ustawiajac bity w rejestrze EXTI->SWIER. To pomoze Ci znalezc czy problem jest po stronie EXTI / NVIC / CPU czy konfiguracji GPIO. Sprawdz tez, prosta petla, czy czytanie pinu GPIO i pokazywanie go na LEDzie dziala dla wszystkich pieciu. Najgorzej jest spedzic wieczor debugujac program jak problem jest sprzetowy.
To kara za obsługę przycisków na przerwaniach ( ͡° ͜ʖ ͡°)
Zaloguj się aby komentować