24.02.2017, 15:08
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Обработчик внешних прерываний
stm32f10xx. Дано, 4 пина, на которые повесил EXTI. Прикол в том, что по условию, пины должны иметь возможность меняться. То есть в башке (h) файле, дефайнами задаются пины и порты. И поэтому например инициализация gpio выглядит так:
Код:
|
#define KEYB_COL1_PORT GPIOB
#define KEYB_COL2_PORT GPIOB
#define KEYB_COL3_PORT GPIOB
#define KEYB_COL4_PORT GPIOB
#define KEYB_COL_PIN1 11
#define KEYB_COL_PIN2 12
#define KEYB_COL_PIN3 13
#define KEYB_COL_PIN4 14 |
Код:
|
#define GPIO_INI_PIN(PORT, PIN, MODE) (PIN › 7) ? \
(PORT-›CRH = (PORT-›CRH & (~((uint32_t)0x0F ‹‹ (((PIN) & 0x07) ‹‹ 2)))) | (((uint32_t)(MODE) & 0x0F) ‹‹ (((PIN) & 0x07) ‹‹ 2))) : \
(PORT-›CRL = (PORT-›CRL & (~((uint32_t)0x0F ‹‹ (((PIN) & 0x07) ‹‹ 2)))) | (((uint32_t)(MODE) & 0x0F) ‹‹ (((PIN) & 0x07) ‹‹ 2))) |
Код:
|
GPIO_INI_PIN(KEYB_COL1_PORT, KEYB_COL_PIN1, GPIO_MODE_COLS); //Pin 11 Input mode with PushPull
GPIO_INI_PIN(KEYB_COL2_PORT, KEYB_COL_PIN2, GPIO_MODE_COLS); //Pin 12 Input mode with PushPull
GPIO_INI_PIN(KEYB_COL3_PORT, KEYB_COL_PIN3, GPIO_MODE_COLS); //Pin 13 Input mode with PushPull
GPIO_INI_PIN(KEYB_COL4_PORT, KEYB_COL_PIN4, GPIO_MODE_COLS); //Pin 14 Input mode with PushPull
KEYB_COL1_PORT-›BSRR = (1 ‹‹ KEYB_COL_PIN1); //PullUp 11, 12, 13
KEYB_COL2_PORT-›BSRR = (1 ‹‹ KEYB_COL_PIN2);
KEYB_COL3_PORT-›BSRR = (1 ‹‹ KEYB_COL_PIN3);
KEYB_COL4_PORT-›BSRR = (1 ‹‹ KEYB_COL_PIN4); //PullUp 14 |
И вот дошла очередь до обработчика прерываний. По идее я как бы знаю, вижу по коду, что я выбрал такие пины, что нэндлер будет таков :
Код:
|
void EXTI15_10_IRQHandler(void){
} |
Но по условию, порты и пины могут быть любыми, тогда логично предположить, что можно написать все хэндлеры, с 0 по 4, потом объеденённый 9_5, ну и 15_10. Но а если другие хэндлеры используются совсем в другом месте программы...уже не катит...Так вот если ли способ, исходя из настройки пинов дефайнами прописать нужный хэндлер. То есть как бы вместо красного подставить нужное. Ну и конечно если пины будут 0, 4, 8, 15, то и сгенерить соответственно 4 обработчика.
Код:
|
void EXTI15_10_IRQHandler(void){ |
|
|
|
|
24.02.2017, 19:56
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Обработчик внешних прерываний
Хм... скажем так... На все случаи жизни универсального кода не напишешь. А как только захочется сменить серию МК с F1 на другую, то все ваши усилия полетят нафик - там другая структура GPIO. Да и клавиатура может быть другой. Не всегда же 4х4.
А создавая разувесистые макросы, теряется легкость чтения кода, текст непомерно разрастается, последующая адаптация его тоже усложняется.
Так же, нельзя дважды в разных местах текста написать один и тот же обработчик. При компиляции будет выдана ошибка.
Я тоже раньше пытался писать универсальные на все случаи жизни библиотеки. Потом понял - нафик надо. Универсальным может быть только общий, аппаратно независимый код, типа фукнции siprintf, она работает на любой архитектуре.
Применительно к клавиатуре - должно быть два уровня. Низший уровень - чисто аппаратнозависимый код, который работает с портами, прерываниями и прочей лабуденью. И тут быстрее руками поправить, чем писать замудренные макросы. Потому что сегодня вы используете внешние прерывания, а завтра вы встроите вызов клавиатуры по системному таймеру, и вам вообще не понадобятся эти навороты.
Кстати, интересно, вот чем думали конструкторы F1xx серии, выдумав такую неудобную структуру GPIO???
|
|
|
Сказали "Спасибо" NewWriter
|
|
|
24.02.2017, 20:09
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
|
Re: Обработчик внешних прерываний
Если я правильно понял вашу задачу, то можно создать некую универсальную функцию (универсальный обработчик всех EXTI прерываний).
И из всех EXTIXYZ_IRQHandler обработчиков вызывать эту универсальную функцию.
А в универсальном обработчике смотреть какие биты pending - и выполнять соотв. действия.
Последний раз редактировалось dgrishin; 24.02.2017 в 20:13.
|
|
|
|
24.02.2017, 21:41
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Обработчик внешних прерываний
Один чел это реализовал
http://we.easyelectronics.ru/blog/STM32/3206.html
Но я не понимаю, как у него это работает...
|
|
|
|
26.02.2017, 15:56
|
|
Прописка
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Обработчик внешних прерываний
Сообщение от NewWriter
|
Кстати, интересно, вот чем думали конструкторы F1xx серии, выдумав такую неудобную структуру GPIO???
|
Чем она неудобная?
|
|
|
|
26.02.2017, 22:44
|
|
Гражданин KAZUS.RU
Регистрация: 01.09.2007
Сообщений: 898
Сказал спасибо: 278
Сказали Спасибо 57 раз(а) в 54 сообщении(ях)
|
Re: Обработчик внешних прерываний
Да уже давно пора компиляторы с распознаванием речи делать... Говоришь ему хочу что бы у меня работало USB, а он тебе под любую линейку МК сразу код рабочий выдает... )))
Кому не удобно, есть много других линеек МК...
|
|
|
|
27.02.2017, 14:37
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Обработчик внешних прерываний
Чем неудобная? Так вот как раз компоновкой регистров и неудобная. Я до сих пор в табличку подглядываю, как биты поставить.
Для сравнения посмотрите младший F0 или наоборот, более старшие.
|
|
|
|
27.02.2017, 20:46
|
|
Гражданин KAZUS.RU
Регистрация: 12.10.2009
Сообщений: 576
Сказал спасибо: 30
Сказали Спасибо 138 раз(а) в 110 сообщении(ях)
|
Re: Обработчик внешних прерываний
Сообщение от supercelt
|
Так вот если ли способ, исходя из настройки пинов дефайнами прописать нужный хэндлер.
|
Способ есть и достаточно очевидный:
#define EXTI_PIN_HANDLER EXTI15_10_IRQHandler
............
void EXTI_PIN_HANDLER(void){
Но если данный обработчик прерывания будет в программе еще где-то, то будет ошибка. В этом случае надо вынести обработку всех exti в одну общую функцию и там разбираться, что с ними делать.
|
|
|
|
08.01.2018, 08:06
|
|
Почётный гражданин KAZUS.RU
Регистрация: 03.01.2007
Адрес: Россия,Иркутская обл.
Сообщений: 2,579
Сказал спасибо: 351
Сказали Спасибо 315 раз(а) в 193 сообщении(ях)
|
Re: Обработчик внешних прерываний
Подскажите для чего Event mask и Pulse generator ? какое применение его при работе с внешними прерываниями 103 серии ?
__________________
Глаза боятся,а руки делают.
|
|
|
|
08.01.2018, 17:04
|
|
Прописка
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 145
Сказал спасибо: 39
Сказали Спасибо 29 раз(а) в 22 сообщении(ях)
|
Re: Обработчик внешних прерываний
Event / Событие - это почти прерывание.
Используется по большей части для перевода контроллера в режим энергосбережения, и выхода из него по событию без возникновения прерывания (инструкция WFE вместо WFI).
В чём разница.
Как мне удалось понять из референса - СОБЫТИЕ возникает всегда, если разрешено на уровне периферии. Событие - может вывести ядро контроллера из ожидания (WFE) и исполнение инструкций будет продолжено так, словно инструкция __WFE(); была пустой (asm("nop") .
Прерывание - возникает независимо от входа в режим ожидания прерывания, но только если разрешено в NVIC и произошло СОБЫТИЕ, которое должно прервать работу программы и вызвать обработчик.
Простой пример:
Контроллер настраивает периферию на ожидание события с линии EXTI2. Допустим, по переднему фронту на пине PC2.
Контроллер разрешает работу периферии, но не разрешает прерывание от EXTI2
Контроллер вызывает инструкцию __WFE() и ядро засыпает.
Через какое-то время порт регистрирует передний фронт импульса на пине PC2 и ядро запускается, продолжая выполнение кода и, например, уходит в бесконечный цикл.
Новый фронт импульса на PC2 не вызовет новых изменений в работе ядра.
Теперь то же самое, но с прерыванием.
Контроллер настраивает EXTI2 и разрешает прерывание от него.
Контроллер вызывает инструкцию __WFI(); и уходит в сон.
Приходит передний фронт импульса на PC2. Возникает СОБЫТИЕ, которое переходит в прерывание и ядро просыпается и выполняет переход на обработчик прерывания. Затем - выходит из обработчика (предварительно очистив бит одидающего прерывания) и продолжает работу.
Приходит НОВЫЙ передний фронт импульса на PC2, и контроллер останавливает выполнение кода, записывает в стэк данные регистров, и снова вызывает обработчик прерывания.
Прерывание будет возникать по каждому переднему фронту (потому что в примере я выбрал передний фронт) импульса и только затем возвращаться к прерваной программе.
Надеюсь, описал ясно.
Грубое сравнение:
Событие: Прозвонил будильник. Можно просто на него забить (позвенит и выключится сам через минуту)
Прерывание: Будильник упал на лицо и игнорировать его сложно - нужно его выключить и поставить обратно на столик с которого он сверзился.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:59.
|
|