реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Внешние прерывания, STM32F103VB
Jenya7
сообщение Jul 27 2014, 06:35
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Я пытаюсь включить внешние прерывания в свою программу на STM32F103VB.
CODE
void ExtIntInit(void)
{
// enable clock for Alternate Function
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

//BUT - PE0
GPIOE->CRL &= ~GPIO_CRL_MODE0; //Configure as input
GPIOE->CRL &= ~GPIO_CRL_CNF0;
GPIOE->CRL |= GPIO_CRL_CNF0_1; //input with pull-up/pull-down resistor
GPIOE->BSRR |= GPIO_BSRR_BS0; //set pull-up
//ENC1 - PE1
GPIOE->CRL &= ~GPIO_CRL_MODE1; //Configure as input
GPIOE->CRL &= ~GPIO_CRL_CNF1;
GPIOE->CRL |= GPIO_CRL_CNF1_1; //input with pull-up/pull-down resistor
GPIOE->BSRR |= GPIO_BSRR_BS1; //set pull-up
//ENC2 - PE2
GPIOE->CRL &= ~GPIO_CRL_MODE2; //Configure as input
GPIOE->CRL &= ~GPIO_CRL_CNF2;
GPIOE->CRL |= GPIO_CRL_CNF2_1; //input with pull-up/pull-down resistor
GPIOE->BSRR |= GPIO_BSRR_BS2; //set pull-up

//interrupt source PE
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PE; //PE0 - BUT
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI1_PE; //PE1 - ENC1
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI2_PE; //PE2 - ENC2
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI3_PE; //PE3 - ENC3

//interrupt edge
EXTI->RTSR |= 0; //EXTI_RTSR_TR0; //rising
EXTI->FTSR |= EXTI_FTSR_TR0; //falling
EXTI->FTSR |= EXTI_FTSR_TR1; //falling
EXTI->FTSR |= EXTI_FTSR_TR2; //falling
EXTI->FTSR |= EXTI_FTSR_TR3; //falling

//enable ext interrupt
EXTI->IMR |= EXTI_IMR_MR0;
EXTI->IMR |= EXTI_IMR_MR1;
EXTI->IMR |= EXTI_IMR_MR2;
EXTI->IMR |= EXTI_IMR_MR3;

NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI2_IRQn);
NVIC_EnableIRQ(EXTI3_IRQn);
}

И обработчик
CODE
void EXTI0_IRQHandler(void) //button pressed
{
EXTI->PR = EXTI_PR_PR0; //clear flag???
TIM4->CNT = 0;
TIM4->CR1 |= TIM_CR1_CEN;
//but_int = true;
//NVIC_EnableIRQ(TIM7_IRQn);

}
void EXTI1_IRQHandler(void) //encoder1
{
EXTI->PR = EXTI_PR_PR1; //clear flag???
enc1_int = 1;
if(DIR1)
{ mot1_position++; }
else
{
if(mot1_position > 0)
{ mot1_position--; }
}
}

void EXTI2_IRQHandler(void) //encoder2
{
EXTI->PR = EXTI_PR_PR2; //clear flag???
if(DIR2)
{ mot2_position++; }
else
{
if(mot2_position > 0)
{ mot2_position--; }
}
}

void EXTI3_IRQHandler(void) //encoder3
{

EXTI->PR = EXTI_PR_PR3; //clear flag???
if(DIR3)
{ mot3_position++; }
else
{
if(mot3_position > 0)
{ mot3_position--; }
}
}

До этого кода все работает нормально. После включения этого куска кода камень умирает и не реагирует ни на что. Я уже пару дней бьюсь над проблемой. Читаю документацию вдоль и поперек не могу понять где проблема.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 27 2014, 06:55
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



GPIO затактировать забыли?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 27 2014, 07:25
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(AHTOXA @ Jul 27 2014, 11:55) *
GPIO затактировать забыли?

нет, я тактирую порты в другой функции
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jul 27 2014, 10:02
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



выясните для начала, нет ли ситуации что "камень" не снимает запрос на прерывание - поставьте ногодрыг в обработчики прерывания от изменения порта - всё ли нормально? А вообще смотрите вот: http://188.134.5.254/browser/hfreceiver/trunk/pio.c#L122
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 27 2014, 10:16
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Genadi Zawidowski @ Jul 27 2014, 16:02) *
выясните для начала, нет ли ситуации что "камень" не снимает запрос на прерывание - поставьте ногодрыг в обработчики прерывания от изменения порта - всё ли нормально? А вообще смотрите вот: http://188.134.5.254/browser/hfreceiver/trunk/pio.c#L122


Я так понимаю что EXTI->PR = EXTI_PR_PR0; сбрасывает запрос.
Спасибо за код.
Go to the top of the page
 
+Quote Post
smk
сообщение Jul 27 2014, 12:33
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(Jenya7 @ Jul 27 2014, 13:16) *
Я так понимаю что EXTI->PR = EXTI_PR_PR0; сбрасывает запрос.
Спасибо за код.


EXTI->PR = EXTI_PR_PR0; - как-то странно выглядит.
Вот пример обработчика. Может поможет чем.

Код
void EXTI0_IRQHandler (void)                        
{
    EXTI->PR |= (1UL<<0);       // Сбросить флаг EXTI0  

}


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 27 2014, 12:46
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(smk @ Jul 27 2014, 16:33) *
EXTI->PR |= (1UL<<0); // Сбросить флаг EXTI0

Так точно делать нельзя.
Бит в EXTI->PR сбрасывается записью в него единицы. Операция "|=" сбросит все установленные биты.
Go to the top of the page
 
+Quote Post
smk
сообщение Jul 27 2014, 14:04
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(adnega @ Jul 27 2014, 15:46) *
Так точно делать нельзя.
Бит в EXTI->PR сбрасывается записью в него единицы. Операция "|=" сбросит все установленные биты.

Но ведь не сбрасывает же.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 27 2014, 14:09
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(smk @ Jul 27 2014, 18:04) *
Но ведь не сбрасывает же.

Может и лишнего сбросить.
Цитата
EXTI->PR = EXTI_PR_PR0;

- годная конструкция.
Из кода не понятна судьба ноги PE3 - ее, вроде, не инициализоровали?
Go to the top of the page
 
+Quote Post
smk
сообщение Jul 27 2014, 14:39
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(adnega @ Jul 27 2014, 17:09) *
Может и лишнего сбросить.

- годная конструкция.
Из кода не понятна судьба ноги PE3 - ее, вроде, не инициализоровали?

Код
#define  EXTI_PR_PR0                         ((uint32_t)0x00000001)        /*!< Pending bit for line 0 */

Тогда уже
Код
EXTI->PR |=EXTI_PR_PR0;

Хотя конечно если принять во внимание что сброс записью единицы...


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 27 2014, 16:00
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(smk @ Jul 27 2014, 20:39) *
Код
#define  EXTI_PR_PR0                         ((uint32_t)0x00000001)        /*!< Pending bit for line 0 */

Тогда уже
Код
EXTI->PR |=EXTI_PR_PR0;

Хотя конечно если принять во внимание что сброс записью единицы...

Вставив метку я обнаружил что камень не выходит из прерывания, причем что так
Код
EXTI->PR =EXTI_PR_PR0

что так
Код
EXTI->PR |=EXTI_PR_PR0

ничего не помогает

По моему я нашел в чем проблема. У меня на этих ногах сидит синус частотой 41.5 Мгц. Буду разбираться как он там появился.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 27 2014, 16:45
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата
что так что так

В таком случае предлагаю попробовать еще один "рабочий" вариант EXTI->PR |= 0 wink.gif
И оставить в итоге EXTI->PR = EXTI_PR_PR0, когда синус с этих ног уйдет.
Во всем остальном соглашусь с smk - код очень странный из-за смеси SPL и доступа к регистрам.
Куда читабельнее записать просто EXTI->PR = (1 << 0)

PS. В cortex-m хорошо, что прерывания защелкиваются в противном случае потери из-за "|=" были бы гарантированы.
PS2. По хорошему еще нужно проверять есть ли условие
Код
void EXTI9_5_IRQHandler(void)
{
    cnt1++;
    if(EXTI->PR & (1 << 6))
    {
        cnt2++;
        EXTI->PR = (1 << 6);
    }
}

Без этого никак при консолидированных обработчиках сразу от нескольких источников. И в некоторых случаях возможно повторное вхождение в прерывание - данную тему затрагивали на форуме, и некоторые участники, можно сказать, ощутили это явление на "собственной шкуре" (я в их числе).
Например, попробуйте на высоких уровнях оптимизации очищать флаг в самом конце прерывания без предварительной проверки условия.
Есть мнение, что cnt1 и cnt2 будут сильно отличаться даже при единственном источнике EXTI6...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 27 2014, 19:20
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(adnega @ Jul 27 2014, 19:45) *
Например, попробуйте на высоких уровнях оптимизации очищать флаг в самом конце прерывания без предварительной проверки условия.
Есть мнение, что cnt1 и cnt2 будут сильно отличаться даже при единственном источнике EXTI6...
Чтобы этого не происходило надо добавить после сброса флага инструкцию DSB().


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 27 2014, 19:22
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата
PS. В cortex-m хорошо, что прерывания защелкиваются в противном случае потери из-за "|=" были бы гарантированы.


Можно чуть подробнее что есть защелкиваются?
Потери от |= появляются в следствие того, что если в самом регистре уже стоят еще какие то флаги, то вы им их сбросите. Это старая и разжеванная тема почему прерывания надо сбрасывать через равно, а не через |= &= (для сбросов нулем)

Цитата
Есть мнение, что cnt1 и cnt2 будут сильно отличаться даже при единственном источнике EXTI6...

ЧуднО это как-то, может это связано с обработкой 6 прерывания в функции с именем 5? Ну то есть есть еще какое-то объяснение? А то как так может быть что вы попадаете в прерывание от единственного источника, при этом флага этого прерывания не стоит?

Ай... ну вот Сергей уже и ответил sm.gif
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 27 2014, 20:18
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Если использовать EXTI не самоцель, то для получения положения энкодера в STM32 очень хорошо подходит таймер.
Без прерываний по каждому изменению положения - полностью аппаратно.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 09:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016