ps. Ага, мы битман портов вручную создаем и он будет ассоциирован с нашими пинами? Громоздкий C++ это все автоматически при компиляции делает, мне такое даже с голову сразу не пришло ) Хотя все равно не понятно... Если пина 3, а порт 1, то в битмапе портов будет один порт, но читать все равно нужно не GPIOx->IDR, который volatile, а значение уже прочитанное из него. Нужен рабочий пример )
Не думал что такой примитивный вопрос вызовет затруднения.....
ps. Ага, мы битман портов вручную создаем и он будет ассоциирован с нашими пинами? Громоздкий C++ это все автоматически при компиляции делает
Пример можно чего там наделает си++? Так, чтобы даже на минимальном уровне оптимизации было не более, чем в том листинге, что я привёл? Пример в студию!
Неужели Вы не видите, что это бред? Или в Вашем мк есть третий вариант результата проверки !GPIOA->IDR & (1 << 5) ? Какая религия запрещает написать Flag.VOL_minus = !(GPIOA->IDR & (1 << 5)); (я молчу про #define)
Компания MEAN WELL пополнила ассортимент своей широкой линейки светодиодных драйверов новым семейством XLC для внутреннего освещения. Главное отличие – поддержка широкого спектра проводных и беспроводных технологий диммирования. Новинки представлены в MEANWELL.market моделями с мощностями 25 Вт, 40 Вт и 60 Вт. В линейке есть модели, работающие как в режиме стабилизации тока (СС), так и в режиме стабилизации напряжения (CV) значением 12, 24 и 48 В.
jcxz Если кнопки выведены на разные порты то "поштучного" чтения не избежать. Таковы условия к примеру для тех же адуринко нано/про-мини. В принципе не столь уж и проблема. Да и схемотехника/топология более удачного размещения компонентов порой свои условия диктует. Это не есть проблема или "некорректность" в данном случае.
aleksey chilov может пока разбирается с примитивом кнопок - каждая только свою фиксированную функцию выполнаяет (минимальный функционал типа настройки параметров -"влево/вправо" и "+/-"). Посему это всего лишь "простейшие кнопы" с минимальным алгоритмом:
по истечении интервала антидребезга (системные часы)
считал ЛВК привел данные к единообразию (собрал в байт) сверил с прошлым значением (буфер прошлого значения)
ЕСЛИ
совпало идем к функции исполнения (switch/case согласно текущего кода комбинации ЛВК )
не совпало заносим текущие данные в буфер прошлого значения и выход по фальстарту
А дальше по интересам (для менюшки посолиднее и/или "псевдовиндовс" на символьном двустрочнике придется заметно больше поизвращаться).
... а я бы всё-таки начал с того, что сохранил бы необходимую информацию в обработчике прерывания и сбежал бы из него от греха подальше. Впрочем, у меня с армами небогатый опыт, может, там прощается многое.
void f() { #if BTN_PORT_MAP & 1 << 0 uint iA = GPIOA->IDR; #endif #if BTN_PORT_MAP & 1 << 1 uint iB = GPIOB->IDR; #endif #if BTN_PORT_MAP & 1 << 2 uint iC = GPIOC->IDR; #endif ///... повторять по количеству портов в МК }}
Не, не, не. Так не честно ) Тут всего 3 пина, но при использовании приходится дублировать чтение IDR из десятка портов и это даже не весь код, а только собственно чтение из порта в переменные ) На C++ будет 2 строки:
Код:
Pins<PA_7, PA_6, PA_5> buttons;
void f() { buttons.write(~bt::read()); }
Читаем значения наших трех пинов, инвертируем, атомарно записываем обратно не трогая оставшиеся пины. Выхлоп:
Какое отношение это имеет к теме опроса ног - вообще непонятно.... Также очевидно, что ноги подключенные к кнопкам, настроены на ввод. Какой смысл в них что-то писать? Что это даст?
Выложили какую-то галиматью...... Мой код имеет точно тот же результат (просто чтение GPIO->IDR), но всего в одну команду. Вместо 5-и у вас.
Работа с флагами - заведомо тупиковая. Это хорошо для одиночных управляющих кнопок. Для группы кнопок при перспективе обработки комбинации нескольких одновременно нажатых (актуально для небольшого количества кнопок "джойстикового" типа и "оконного меню") такой подход только усложнит программу. (как нибудь в котуинке положу тестовый "псевдовиндовс" на референсе Си для адуринок под АВР и жирненький "двустрочник").
aleksey chilov, уже получше. Но запинаю - в таком виде это всё равно бессмысленно. Зачем лишние флаги, если GPIOA->IDR уже куда-то сохранён? И потом, если флаги Flag.SET_Ok и прочие разместить в том же порядке, в котором биты порта, то весь этот case опять заменяется на Flags.All = GPIOA->IDR; притом, так отловится и одновременное нажатие. Вы же в курсе по указатели, структуры, объединения, битовые поля?
Имеется в виду, что даже для всего лишь трех пинов придется написать 30 строк только для чтения IDR в переменные.
jcxz писал(а):
А где код? Верить на слово? Очевидно что фраза про "2 строки" - ложь.
Очевидно, что я посчитал число строк исключая "f() {}", то есть только строки где идет работа с пинами. Код не мой, писал товарищ, могу спросить можно ли его выложить, надо? Впрочем, я его понимаю на 90%, большинство остальных поймут на 10% ) Ваша недооценка возможностей C++ пропорциональна его незнанию, еще и помноженная на скептицизм, в таком случае за подобной сложности код можно даже и не браться.
jcxz писал(а):
код этот ваш делает следующую операцию:
Код:
u32 *p = ...; p[6] = ~p[4] & 0xE0 | 0xE00000;
Какое отношение это имеет к теме опроса ног - вообще непонятно.... Также очевидно, что ноги подключенные к кнопкам, настроены на ввод. Какой смысл в них что-то писать? Что это даст?
Это же пример, скучно просто читать с порта ) Естественно пины были сконфигурированы на вывод. В данном случае у нас 3 подряд идущих пина, а может быть 30, с разных портов, в любом порядке, и этот мой код продолжит работать без никаких модификаций. То что результат выглядит как простое чтение из порта с накладыванием маски и записью обратно лишь подтверждает оптимизирующую природу используемого алгоритма, либа научена искать подобные маски которыми можно выделить побольше бит и сдвинуть их за раз в нужные позиции. Даже эти три пина после чтения оказываются в трех младших битах результата, просто write() все сдвинула обратно и оптимизатор сдвиги вообще убрал )
Зарегистрирован: Вс мар 27, 2022 09:38:17 Сообщений: 160
Рейтинг сообщения:0
Добрый день! Хочу продолжить тему кнопочек. Я подумал, и что-то придумал. Наверное опять будете меня закидывать помидорами и оскорблять но всё же, посмотрите что я сделал и скажите что-то. Ведь если ругают значит есть повод подумать и устранить ошибки.
void EXTI9_5_IRQHandler(void){ EXTI->PR = (EXTI_PR_PR5|EXTI_PR_PR6|EXTI_PR_PR7); // Сбросить флаг прерывания! asm("nop"); // Пропуск для установки флага asm("nop"); // Пропуск для установки флага Flag.Butoon = true; // Нажата одна из кнопок }
Вот тут в этом хендлере флагу "Flag.Butoon" присваивается true. Этот флаг будет использоваться в функции которая будет обрабатывать кнопки. Если флаг будет false то когда в обработчике дойдёт очередь до этой функции, в неё зайдёт и сразу выедет тем самым сократится количество манипуляций. Если true тогда обработает и присвоит код кнопки переменной которая была нажата 1,2,3 и в конце сбросит флаг "Flag.Butoon".
if(!(GPIOA->IDR & (1 << 5))){ *key_kod = 3; } *Survey = false; // Сбросить после обработки } } Собственно сама функция, тут в ней обработка кнопок. Через указатели дотягиваемся до флага и переменной и изменяем их если нужно.
Этот хендлер для таймера. Таймер настроен на 100Гц. Собственно там вызываются 2 функции. Первая это для кнопок а вторая вычисляет и усредняет данные от ADC через DMA для стабильной работы.
Всё. Пока что вот так сделал. Теперь критика ваша, жду...
Посмотрите, это форум. Ни у кого нет цели оскорблять. Только направление на размышление даем. Напр. смотрю на собственный код из прошлом и задаюсь вопросом: так ли я ето написал? Если рядом был человек, то он мог бы дать направление, и путь будет "короче". Если нет человека, то в интернете, или со своим опытом. Но второй способ происходит значительно медленнее. Так что как решите, так и делайте. Цель одна - сокращенный, чистый код, который впоследствии пригодится вам в других проектах. МК не интересует способ составления алгоритма. Для небольших проектов будет ОК. А вот в больших проектах (и при максимальном использовании ресурсов) будет от: медленного режима до невозможности работы. А когда меняешь начина построяния в коде на другой принцип, алгоритм, вдруг все ОК. (частично использую переводчика) ---
прочитали статус порта 3 раза. Если статус изменился во время чтения? (спомните проблем bounce для кнопки). Как вариант: прочитайте порт раз, присвойте значение переменной, затем отфильтруйте ее значение по кнопок.
прочитали статус порта 3 раза. Если статус изменился во время чтения? (спомните проблем bounce для кнопки).
В текущей реализации ТС из-за дребезга можно прочитать одни единички и пропустить нажатие вообще, даже с одной кнопкой. В нормальном случае, со счетчиком для отдельной кнопки или для всех сразу, без разницы сколько раз читать с портов, три чтения GPIOA->IDR ничем не отличаются от чтения GPIOA->IDR + GPIOB->IDR + GPIOC->IDR, если кнопки будут на разных портах.
неужели не видно, что опять можно просто присвоить key_kod`у состояние трёх битов GPIOA->IDR (с маской) за один раз? Более того, они ведь даже подряд идут, если очень хочется, можно даже сделать сдвиг всех трёх и получить 1, 2, 3, если это жизненно важно. Зачем делать три условия? печально всё это...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения