Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > Внешние прерывания


Автор: supercelt 31.7.2016, 19:25
И снова здравствуйте! Помогите с внешними прерываниями.
Совсем запутался, потмогие плз. Везде в уроках рассматривают прерывания на 0, максимум 1 пинах, но если надо повесить на пины больше 10, уже путанница.
Надо зажигать светодиод, когда на пинах PB11, 12,13,14 лог 1.

Код

void EXTI3_IRQHandler(void)
{
GPIOD->ODR ^= 0x4;
EXTI->PR |= EXTI_PR_PR11;
}
void EXTI4_IRQHandler(void)
{
GPIOD->ODR ^= 0x4;
EXTI->PR |= EXTI_PR_PR11 | EXTI_PR_PR12 | EXTI_PR_PR13 | EXTI_PR_PR14;
}
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPDEN; //PORT D CMD
  GPIOD->CRL &= ~GPIO_CRL_CNF2_0;
  GPIOD->CRL |= GPIO_CRL_MODE2_1;
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
GPIOB->CRH &= ~(GPIO_CRH_CNF11_0 | GPIO_CRH_CNF12_0 | GPIO_CRH_CNF13_0 | GPIO_CRH_CNF14_0);//Scan Pins: PB11, PB12, PB13, PB14.
GPIOB->CRH |= GPIO_CRH_CNF11_1 | GPIO_CRH_CNF12_1 | GPIO_CRH_CNF13_1 | GPIO_CRH_CNF14_1;                 //Input Push-down.
GPIOB->CRL &= ~(GPIO_CRL_CNF5_0 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0);      //Generate Pins: PB5, PB6, PB7, PB8.
GPIOB->CRH &= ~GPIO_CRH_CNF8_0;
GPIOB->CRL |= GPIO_CRL_MODE5_1 | GPIO_CRL_MODE6_1 | GPIO_CRL_MODE7_1;           //Output Push-pull.
GPIOB->CRH |= GPIO_CRH_MODE8_1;

GPIOB->BSRR |= 0x1E0;
//-------Setup EXTI-------------------------------
AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI11_PB;
AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI12_PB | AFIO_EXTICR4_EXTI13_PB | AFIO_EXTICR4_EXTI14_PB | AFIO_EXTICR4_EXTI15_PB;
EXTI->RTSR |= EXTI_RTSR_TR11 | EXTI_RTSR_TR12 | EXTI_RTSR_TR13 | EXTI_RTSR_TR14;
EXTI->IMR |= EXTI_IMR_MR11 | EXTI_IMR_MR12 | EXTI_IMR_MR13 | EXTI_IMR_MR14;
NVIC_EnableIRQ(EXTI3_IRQn);
NVIC_EnableIRQ(EXTI4_IRQn);
//------------------------------------------------
while(1){
__NOP();
}
}


Код не работает(

И что значит элемент массива EXTICR[2]. Всмысле почему одни там ставят 0, а другие 1 и так далее.?

Автор: xvr 31.7.2016, 22:31
Цитата(supercelt @  31.7.2016,  19:25 Найти цитируемый пост)
И что значит элемент массива EXTICR[2].


А Reference Manual на камень почитать не судьба?  smile 

В камне есть 4 регистра (EXTICR1/2/3/4), расположенные последовательно в адресном пространстве. Вот их и описали как массив из 4х элементов. Каждый регистр содержит флаги для 4х входных пинов. В EXTICR1 (он же EXTICR[0]) для EXTIO0/1/2/3, в следующем (EXTICR2 или EXTICR[1]) для EXTIO4/5/6/7 ну и т.д.

Собственно идентификаторы для ножек прерывания (AFIO_EXTICR4_EXTI13_PB например) на это намекают - бит EXTI13 в регистре EXTICR4 (в этом месте у вас правильно написано)
Вот только смущает AFIO->EXTICR[3] |= . Почему бы не просто присвоить? AFIO->EXTICR[3] = 

Автор: supercelt 1.8.2016, 21:02
Нашёл пару ошибок, подправил

Код

void EXTI3_IRQHandler(void)
{
GPIOD->ODR ^= 0x4;
EXTI->PR |= EXTI_PR_PR11;
}
void EXTI4_IRQHandler(void)
{
GPIOD->ODR ^= 0x4;
EXTI->PR |=  EXTI_PR_PR12 | EXTI_PR_PR13 | EXTI_PR_PR14;
}
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPDEN; //PORT D CMD
  GPIOD->CRL &= ~GPIO_CRL_CNF2_0;
  GPIOD->CRL |= GPIO_CRL_MODE2_1;
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
GPIOB->CRH &= ~(GPIO_CRH_CNF11_0 | GPIO_CRH_CNF12_0 | GPIO_CRH_CNF13_0 | GPIO_CRH_CNF14_0);//Scan Pins: PB11, PB12, PB13, PB14.
GPIOB->CRH |= GPIO_CRH_CNF11_1 | GPIO_CRH_CNF12_1 | GPIO_CRH_CNF13_1 | GPIO_CRH_CNF14_1;                 //Input Push-down.
GPIOB->CRL &= ~(GPIO_CRL_CNF5_0 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0);      //Generate Pins: PB5, PB6, PB7, PB8.
GPIOB->CRH &= ~GPIO_CRH_CNF8_0;
GPIOB->CRL |= GPIO_CRL_MODE5_1 | GPIO_CRL_MODE6_1 | GPIO_CRL_MODE7_1;           //Output Push-pull.
GPIOB->CRH |= GPIO_CRH_MODE8_1;
GPIOB->BSRR |= 0x1E0;
//-------Setup EXTI-------------------------------
AFIO->EXTICR[2] = AFIO_EXTICR3_EXTI11_PB;
AFIO->EXTICR[3] = AFIO_EXTICR4_EXTI12_PB | AFIO_EXTICR4_EXTI13_PB | AFIO_EXTICR4_EXTI14_PB;
EXTI->RTSR |= EXTI_RTSR_TR11 | EXTI_RTSR_TR12 | EXTI_RTSR_TR13 | EXTI_RTSR_TR14;
EXTI->IMR |= EXTI_IMR_MR11 | EXTI_IMR_MR12 | EXTI_IMR_MR13 | EXTI_IMR_MR14;
NVIC_EnableIRQ(EXTI3_IRQn);
NVIC_EnableIRQ(EXTI4_IRQn);
//------------------------------------------------
while(1){
__NOP();
}
}


Но всё-равно не работает. В отладчике, при нажатии кнопки и соответственно смены фронта с 0 на 1 на пинах 11,12,13,14  (кеил5) в периферии, в NVIC, в регистрах  ISPR1 и ICPR1 появляется значение 0x100. На этом всё (

Автор: xvr 1.8.2016, 22:52
Глобально прерывания разрешили ( __enable_irq() ) ?

Автор: supercelt 1.8.2016, 23:00
У меня кстати прерывание на таймер работало и без этой строчки. Вставил, для проверки. Всё-равно не работает(

Автор: xvr 2.8.2016, 22:10
Тогда увы - идеи кончились. Надо вдумчиво курить PM на камень. 
Хотя одна идея осталась - не надо ли на EXTI3_IRQHandler и EXTI4_IRQHandler написать какие нибудь прагмы, что бы компилятор сделал из них обработчики прерываний?

Автор: supercelt 8.8.2016, 20:02
кому пригодиться. Решение проблемы:

Код

void EXTI15_10_IRQHandler(void)
{
EXTI->PR |= EXTI_PR_PR11 | EXTI_PR_PR12 | EXTI_PR_PR13 | EXTI_PR_PR14;
GPIOD->ODR ^= 0x4;
}



Поменять местами строчки. Сначало сбрасывать PR, потом делать всё остальное. Это баг ARM, о котором все молчат © 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)