|
прерывания STM32F4, должно работать, но не хочет... |
|
|
|
Aug 23 2014, 16:06
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Вроде все настроил, платка F4Discovery, а работать по нажатию на кнопку не хочет. Может кто подскажет что не так ему? Код void EXTI0_IRQHandler(void) { on (LED_Blue); EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания } Код void main() { InitPeriph(); // тут лампочка описана и дефайн кнопки // настройка ноги на прерывание PA0 GPIOA->MODER &= ~GPIO_MODER_MODER0; //input GPIOA->OTYPER &= ~GPIO_OTYPER_OT_0; //Output push-pull GPIOA->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR0; //40 MHz GPIOA->PUPDR &=~GPIO_PUPDR_PUPDR0; //No pull-up, pull-down // настройка внешнего прерывания на PA0 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA; EXTI->IMR |= EXTI_IMR_MR0; EXTI->RTSR |= EXTI_FTSR_TR0; NVIC_EnableIRQ(EXTI0_IRQn); NVIC_SetPriority(EXTI0_IRQn, 1); while(1) { } }
|
|
|
|
|
 |
Ответов
(1 - 47)
|
Aug 23 2014, 17:17
|

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

|
Почему не работает не скажу, но при таком способе сброса запросов на прерывание сброшены будут все имеющиеся, а не только EXTI_PR_PR0. Надо так: Код EXTI->PR = EXTI_PR_PR0; Проверьте, что с инициализацией - вот образец точно работающего: http://188.134.5.254/browser/hfreceiver/trunk/pio.c#L362Программирование вывода на ввод не здесь. У Вас - вне не только дефайн кнопки, но и инициализация регистров? Порт "А" включаете? Вы везде предполагаете что в регистрах до Вас только нули были. Вы задаёте proprity - а как сконфигурирована система прерываний? Реакция на вашу "1" от этого зависит.
Сообщение отредактировал Genadi Zawidowski - Aug 23 2014, 17:25
|
|
|
|
|
Aug 23 2014, 17:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Цитата(Genadi Zawidowski @ Aug 23 2014, 21:17)  Почему не работает не скажу, но при таком способе сброса запросов на прерывание сброшены будут все имеющиеся, а не только EXTI_PR_PR0. Надо так: Код EXTI->PR = EXTI_PR_PR0; разве у меня по-другому? он не заходит в прерывание, раз LED не поджигает. До сброса не доходит дело.
|
|
|
|
|
Aug 23 2014, 17:29
|

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

|
Я напимсал, что увиденная ошибка не влияет. Но потом помешает. Цитата разве у меня по-другому? У Вас: Код EXTI->PR |= EXTI_PR_PR0; У меня: Код EXTI->PR = EXTI_PR_PR0; В чём отличия понятно? Инициализацию кнопки покажите. Или убедитесь, что её видно из программы. hint: На discovery кнопка зажимает в "0" вход.
Сообщение отредактировал Genadi Zawidowski - Aug 23 2014, 17:28
|
|
|
|
|
Aug 23 2014, 17:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
вот InitPeriph(); здесь Код #ifndef HARDWARE_H__ #define HARDWARE_H__
#define LED_Green GPIOD, GPIO_Pin_12, H #define LED_Orange GPIOD, GPIO_Pin_13, H #define LED_Red GPIOD, GPIO_Pin_14, H #define LED_Blue GPIOD, GPIO_Pin_15, H
#define RS232_BAUDRATE 38400 #define SYS_CLK (32000000LL) // частота шины #define TIM6_PRESCALER (0x3E8LL) // предделитель системной частоты (делим на 1000) #define TIM6_COMPARE(ARR) MS // до скольки считает счетчик и прерывается
#define MS SYS_CLK / TIM6_PRESCALER / 1000 // сколько итераций цикла надо на одну миллисекунду #define MKS MS / 1000 // на микросекунду в 1000 раз меньше void InitPeriph(void) { SysTick_Config(SystemCoreClock/8/1000); // системный таймер -из файла exel видно, что он делится на 8 от тактовой частоты RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOAEN; // Включаем тактирование порта D GPIOD->MODER |= GPIO_MODER_MODER12_0; //output GPIOD->OTYPER &= ~GPIO_OTYPER_OT_12; //Output push-pull GPIOD->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR12; //40 MHz GPIOD->PUPDR &=~GPIO_PUPDR_PUPDR12; //No pull-up, pull-down GPIOD->MODER |= GPIO_MODER_MODER13_0; //output GPIOD->OTYPER &= ~GPIO_OTYPER_OT_13; //Output push-pull GPIOD->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR13; //40 MHz GPIOD->PUPDR &=~GPIO_PUPDR_PUPDR13; //No pull-up, pull-down GPIOD->MODER |= GPIO_MODER_MODER14_0; //output GPIOD->OTYPER &= ~GPIO_OTYPER_OT_14; //Output push-pull GPIOD->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR14; //40 MHz GPIOD->PUPDR &=~GPIO_PUPDR_PUPDR14; //No pull-up, pull-down
GPIOD->MODER |= GPIO_MODER_MODER15_0; //output GPIOD->OTYPER &= ~GPIO_OTYPER_OT_15; //Output push-pull GPIOD->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR15; //40 MHz GPIOD->PUPDR &=~GPIO_PUPDR_PUPDR15; //No pull-up, pull-downown }
#endif // HADRWARE_H__
|
|
|
|
|
Aug 23 2014, 17:45
|

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

|
Проверьте видимость кнопки чтением регистра GPIOA->IDR. Вне прерываний. Так же, как проверяли on(LED_BLUE) Вы включаете pull-down, на плате стоит pull-up... Предположу, что напряжение на входе кнопки меняется от 0 до 0.8 вольта. Код for (;;) { if ((GPIOA->IDR & 0x0001) != 0) on(LED_BLUE); else off(LED_BLUE); } А потом поменяйте условие на обратное.
Сообщение отредактировал Genadi Zawidowski - Aug 23 2014, 17:50
|
|
|
|
|
Aug 23 2014, 17:57
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
так нет реакции Код { if ((GPIOA->IDR & 0x0001) != 0) on(LED_Blue); else off(LED_Blue); } так Код { if ((GPIOA->IDR & 0x0001) != 0) off(LED_Blue); else on(LED_Blue); } загорелась сразу и горит. ничего не нажимал
|
|
|
|
|
Aug 23 2014, 18:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Код if ( is_bit_active(KEY) ) { on (LED_Blue); } все работает- зажигается вот дефайн Код #define _setL(port,bit) do { port -> BSRRH = bit; } while(0) #define _setH(port,bit) do { port -> BSRRL = bit; } while(0) #define _clrL(port,bit) do { port -> BSRRL = bit; } while(0) #define _clrH(port,bit) do { port -> BSRRH = bit; } while(0) #define _cpl(port,bit,val) { if ((port -> ODR) & bit) _clr##val(port, bit); else _set##val(port, bit); } #define _bitL(port,bit) (!((port -> IDR) & bit)) #define _bitH(port,bit) ((port -> IDR) & bit)
|
|
|
|
|
Aug 23 2014, 18:21
|

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

|
Сорри, посмотрел схему... На PA0 кнопка подает "1". Тогда смотрите? вообще работают ли прерывания. Таймерное. Закомментируйте NVIC_SetPriority Цитата все работает- зажигается Я про свой код спросил. Он реагирует на кнопку? Цитата все работает- зажигается Интересует, гаснет ли при отпускании кнопки.
Сообщение отредактировал Genadi Zawidowski - Aug 23 2014, 18:35
|
|
|
|
|
Aug 23 2014, 18:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
провел эксперимент: в цикле зеленый LED мигает, прерывания разрешены. как только нажимаю на кнопку, зеленый LED прекращает мигать и останавливается в одном из положений. ??? Цитата(Genadi Zawidowski @ Aug 23 2014, 22:21)  Сорри, посмотрел схему... На PA0 кнопка подает "1". Тогда смотрите? вообще работают ли прерывания. Таймерное. Закомментируйте NVIC_SetPriority
Я про свой код спросил. Он реагирует на кнопку? нет, не реагирует никак. в одном случае горит, во втором случае не горит.
|
|
|
|
|
Aug 23 2014, 21:37
|

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

|
Цитата еще раз- что изменили, чтобы заработало? 1 - включил в проект файл стартапа (это додумался в последнюю очередь) 2 - закомментировал всё в настройке GPIOA кроме MODER (думаю, не повлияло) 3 - сделал сброс запросов прерывания правильным 4 - аккуратнее с RAISE/FALL - там что-то было с именами. Сравните. 5 - убрал содержимое цикла из main. До того у меня там мигалка была. 6 - убрал установку приоритета прерывания. Цитата на 7.2 работает У меня вообще 6.7
Сообщение отредактировал Genadi Zawidowski - Aug 23 2014, 21:39
|
|
|
|
|
Aug 23 2014, 21:43
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
да, я видел, что 6.7 ваш код обработчика работает Код void EXTI0_IRQHandler(void) { uint32_t pr = EXTI->PR & EXTI_PR_PR0; EXTI->PR = pr; //сбросили бит прерывания cpl (LED_Blue); } а мой почти такой же нет. самое интересное, а почему, когда мигалку вставляю, он не мигает? попробуйте с мигалкой мигалка работает, если задержка for (i=0;i<2000000;i++){} а если как у меня на системном таймере- то не хочет. как-то они конфликтуют по прерываниям
|
|
|
|
|
Aug 23 2014, 22:06
|

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

|
Что-то намудрили с использованием системных тиков. Не происходят прерывания от системного таймера. Я вот такое использовал: Код #include "stm32f4xx.h" #include "stm32f4xx_gpio.h"
#include "gpio_ascold.h" #include "hardware.h" #include "delay.h"
void EXTI0_IRQHandler(void) { uint32_t pr = EXTI->PR & EXTI_PR_PR0; EXTI->PR = pr; //сбросили бит прерывания cpl (LED_Green); }
#define KEY GPIOA, GPIO_Pin_0, H
void stall(int an) { volatile int n = an; while (an --) ; }
void main() { InitPeriph();
// настройка ноги на прерывание PA0 GPIOA->MODER &= ~GPIO_MODER_MODER0; //input //GPIOA->OTYPER &= ~GPIO_OTYPER_OT_0; //Output push-pull //GPIOA->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR0; //40 MHz //GPIOA->PUPDR &=~GPIO_PUPDR_PUPDR0; //No pull-up, pull-down
//// // настройка внешнего прерывания на PA0 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; SYSCFG->EXTICR [0] |= SYSCFG_EXTICR1_EXTI0_PA; // Connect EXTI line 4 to PB EXTI->IMR |= EXTI_IMR_MR0; // какую линию выбираем из 23-х (у нас 4-я) = EXTI4 EXTI->FTSR |= EXTI_FTSR_TR0; // настройка реакции на спад //EXTI->RTSR |= EXTI_RTSR_TR0; // настройка реакции на нарастание NVIC_EnableIRQ(EXTI0_IRQn); // NVIC_DisableIRQ(EXTI0_IRQn); //NVIC_SetPriority(EXTI0_IRQn, 1); //приоритет // for (;;) { cpl (LED_Red); stall(10000000); } } После пары незначительных правок delay.c заработало... Откатил назад - работает. Возможно Rebuild поможет. Деление на 8 в Вашем случае лишнее. Вы же предделитель таймера не программируете на 8? __IO - это личная собственность библиотеки. В своих программах лучше использовать volatile
|
|
|
|
|
Aug 23 2014, 22:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
а если мне точно надо время мерять? на другом проце, да и на этом с этим таймером все норм. работает, пока др. прерывания не происходят да, убрал деление на 8, заработало! давайте спать пойдем уже) И спасибо большое за помощь!
|
|
|
|
|
Aug 24 2014, 14:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Вот что странно: обработчик Код void EXTI0_IRQHandler(void) { cpl (LED_Blue); EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания } не работает лампа а так Код void EXTI0_IRQHandler(void) { EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания cpl (LED_Blue); } работает. Очень странно. Я на STM32L152 именно так и писал, и все работало. А почему тут не хочет? Почему сначала бит надо сбрасывать?
|
|
|
|
|
Aug 24 2014, 15:11
|

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

|
Цитата Вот что странно: обработчик Код EXTI->PR |= EXTI_PR_PR0; Вы понимаете, что приеденный Вами код сбросит ВСЕ имеющиеся запросы на прерывание, а не только 0-й?
|
|
|
|
|
Aug 24 2014, 15:57
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Цитата(Genadi Zawidowski @ Aug 24 2014, 19:11)  Код EXTI->PR |= EXTI_PR_PR0; Вы понимаете, что приеденный Вами код сбросит ВСЕ имеющиеся запросы на прерывание, а не только 0-й? почему все? я маскирую только тот бит, что EXTI_PR_PR0 т.е. я делаю EXTI->PR = EXTI->PR | EXTI_PR_PR0; т.е. я в регистре PR не меняя его, делаю ИЛИ по биту одному, т.е. если PR= 0100 EXTI_PR_PR0= 0001 результат будет 0101 или что не так? читаю отличия) получается, что дважды прерывание вызывается? Т.к. если просто зажигать LED, то он зажигается.
|
|
|
|
|
Aug 24 2014, 19:55
|

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

|
Цитата я хочу сбросить прерывание EXTI_PR_PR0, т.е. должен записать в PR 0x00000001 Да, именно так (написано в даташите). Сбросится только этот бит. Примечания и условные обозначения в reference manual RM0090 смотрите. DocID018909 Rev 7, страница 383 - про его состояние при чтении: Цитата 0: No trigger request occurred 1: selected trigger request occurred This bit is set when the selected edge event arrives on the external interrupt line. This bit is cleared by programming it to ‘1’.
Сообщение отредактировал Genadi Zawidowski - Aug 24 2014, 20:06
|
|
|
|
|
Aug 24 2014, 20:43
|

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

|
Цитата так мы накладываем маску 0x00000001 и стираем т.о. только нулевой бит EXTI->PR |= EXTI_PR_PR0; стирает всё. EXTI->PR = EXTI_PR_PR0; Стирает только нулевой бит. Я такой немного "извращённый" способ использую (с маскированием интересующих и записью обратно) как шаблон для случая нескольких разных обработчиков на одной функции прерывания. Цитата нигде же не сказано, чтобы беречь другие биты. Если не хотите обрабатывать в других функциях - можно не беречь. Предположим у Вас ещё 4_9 биты установлены - для другого случая. Если вы их здесь сбросите, обработчик 4_9 уже не вызовется.
Сообщение отредактировал Genadi Zawidowski - Aug 24 2014, 20:47
|
|
|
|
|
Aug 24 2014, 20:58
|

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

|
Цитата PR= 0x00000001 Так не потеряете. А как Вы писали - Цитата PR |= 0x00000001 Потеряете. По операциям: t = PR; // 9 t = t | 1; // 9 PR = t; // 9
Сообщение отредактировал Genadi Zawidowski - Aug 24 2014, 21:04
|
|
|
|
|
Aug 24 2014, 21:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
увидел свою ошибку- при | я в регистр запишу полностью значение 0x00000009 что и приведет к очистке всех бит да, еще раз спасибо за разъяснения
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|