juvf 10 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Может я отстал от поезда, но объясните: какой смысл такой "экономии на спичках"? есть программисты, которым подавай boost, stl, и т.п..... которые передают по каналам связи джейсон... 1 бит состояния хранят как "Масляный выключатель Включен" и "Масляный выключатель Выключен". те ни когда не опустятся ниже прикладного уровня Linux/Windows. Есть которые опускаются ниже, но не любят тесноты.... им подавай запас под их "красивый и легко читаемый код".... А есть проекты, где нужно сделать хороший функционал на дешевом процессоре. Тут спорить бессмысленно. "Не хочу, не буду" Прикладной программист для ПК не возмется за программирование stm32f100. Я не возьмусь за программирование СУБД.... Каждому своё. ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Мы тут о крутизне спорим, да? О чем вы? если результат хуже, чем стандартное применение дефайнов? Не хочу с вами спорить, т. к. я прошел через оба варианта, начинал с вашего исполнения на дефайнах. Но остался на том, что сейчас. Вот простой пример работы со светодиодом, никакой дополнительной инициализации и никакого дополнительного кода: #include "Pin.hpp" main() { LedOpenDrain<RB0> ledRed; .... ledRed.on(); .... ledRed.off(); .... } есть программисты, которым подавай boost, stl, и т.п..... (С) "Я ему про Фому, а он мне про Ерёму" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Вот простой пример работы со светодиодом, никакой дополнительной инициализации и никакого дополнительного кода:на дефайнах этот код не менее прост и понятен. #include "MyInclude.h" main() { initRedLed(); .... ledRedOn(); .... ledRedOff(); .... } а что вашего кода касательно.... с ходу.... не очень понятно что такое RB0? Не загялнув в инклуде не понятно, хотя может у вашего процессора есть порт RB0? У стм обычно PB0. и второе.... вижу ledRed - это объект класса LedOpenDrain. Т.е. ledRed в будещем нельзя изменить и сделать как OutPullUp? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба тысячные партии изделия, при низкой стоимости самого изделия Ну вот всё и встало на места. Разные условия - разные подходы. ЗЫ Тысячи это совсем мало. Размер партии слегка кастомного решения для средне размерного клиента. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба К сожалению, gcc их не умеет. А было бы удобно, конечно. Правда, в случае 32-битных регистров удобство уже сомнительно, но с 8/16 все ОК. Умеет. Да и чего бы ему не иметь, если это одно из его обычных расширений https://gcc.gnu.org/onlinedocs/gcc/Binary-c...inary-constants . Кстати умеет в чистом С. Только не забудьте ему ключик указать, чтобы он расширения включил. P.S. Позабавили меня рассуждения последних нескольких страниц - столько внимания пину, можно подумать контроллер помощнее выбирался, чтобы ногами дрыгать через С++ классы :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба на дефайнах этот код не менее прост и понятен. #include "MyInclude.h" main() { initRedLed(); .... ledRedOn(); .... ledRedOff(); .... } Где ж он короче? А содержимое initRedLed, ledRedOff, ledRedOn кто за вас писать будет? Вася Пупкин? Иначе прога не соберется. У меня Pin.hpp не зависит от проекта, он вообще вынесен в отдельный каталог к соотв. либе для соотв. семейства. Общий для всех проектов. В него лазить и тем более править нет нужды, отладил и забыл. а что вашего кода касательно.... с ходу.... не очень понятно что такое RB0? Описка, должно быть PB0. Вообще, это самый простой пример, который собирается именно в таком виде без всяких доп. функций и т.п. А в реальном коде этот PB0 "забит" дефайном в одном месте в файле настроек проекта (StaticSettings.hpp): // LEDS #define PIN_LED_GREEN (PB6) #define PIN_LED_RED (PB5) и второе.... вижу ledRed - это объект класса LedOpenDrain. Т.е. ledRed в будещем нельзя изменить и сделать как OutPullUp? Почему же нельзя? Конечно, можно, но это будет неправильно - нарушается логичность кода (какой смысл в runtime делать такие странные вещи - изменять схему подключения пина), лучше использовать для этого другой класс со своим функционалом: DigitalOutputPin Или вообще, просто Pin, но тогда придется вызывать вручную несколько методов, которые настроят пин на нужные параметры (подтяжка, направление, альтернативные функции и т. п.). Вообще, LedOpenDrain у меня выглядит так (файл Pin.hpp): template <PIN pin> class LedOpenDrain : public PinBase { public: LedOpenDrain(void) : PinBase(pin) { setAsDigitalOutput(); setAsOpenDrain(); setOutputSpeed2MHz(); off(); } void on(void) { setToLow(); } void off(void) { setToHigh(); } }; подумать контроллер помощнее выбирался, чтобы ногами дрыгать через С++ классы :) Подумать можно все что угодно, но в действительности все как раз наоборот - C++ используется потому что, проекте толстый и компилятор нормальный. Ногодрыг на классах - лишь удобный довесок к куче других С++ полезностей, а вовсе не наоборот. зы. Вот щас посматриваю в сторону С++ исключений, но пока просто изучаю матчасть, смотрю, что это дает, а что отбирает в МК ... По этой же причине пока не использую кучу или что-то, что ее заменяет. Осторожничаю ))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба На момент создания всего этого у меня было две задачи: убрать кучу кода инициализации пинов, спратав это внутрь одного файла (Pin.hpp), сохранить скорость работы ногодрыга. Оптимизация - это вторично. Главное - user-код изолирован от реализации Pin, который впоследствии можно безболезненно переделать. Какую кучу инициализации? Вы что бредите? Я пишу свой файл local где детально описываю все ноги, включая неиспользуемые. Описываю оборудование применяемое на ногах. Но не потому, что нет другого выхода. Потому что это способ сразу видеть схему, глазами программиста. Даже через несколько лет, я смогу восстановить схему, с точки зрения программиста. Это очень удобно, в том числе при отладке. То есть этот подход ничего общего не имеет к стилю написания, а имеет прямое отношение к стилю проектирования. Порты инициализирую сразу, а не попиново, но инициализация всё равно имеет мнемонику пинов, что не ухудшает переносимость. "Куча кода инициализации портов" получается 5/6 регистров на порт. Плюс не более 20 макросов управления ногодрыгом. И это на 144 ножный корпус. Причём макросы это не обязательно ногодрыг. Например подключен АЦП на SPI. DIN/DOUT(RDY). Я передаю, потом переключаю линию разрешаю прерывания по готовности и так далее. То есть это уже к класу ногодрыга не совсем относится, но по логике работы общая. Я не ратую за макросы. Сейчас это не рекомендуется. Можно оформить процедурами либо классами. Но зачем увязывать это с портами? И главное, мне не ответили в чём выигрыш? Если класс получается непереносимый, и его нельзя заимствовать? Зачем? Вот главный вопрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба кстати.... эти ваши плюсы.... вот на порту РА нужно проинитить пины 0, 1, 6, 7 как выход... на Led или на CS.... не важно. с SPL или си-стаил инит не такой красивый, но там инитятся порты все хором за раз (в stm32). Теперь допустим надо 0 и 6 выствить в "0", а 1 и 7 выставить в 1. через регистр BRRS это делается за 1 команду си/с++ (вроде как в асме выходит 3 команды). AHTOXА, Forger, Reflector - в ваших юСтайлах сколько строк дизасемблера занимает инит 4-х портов, и сколько переключение? если инит одного порта будет вызван 4 раза.... то в итоге... код будет вызываться один и тот же 4 раза. Но допустим, функция - зашли в неё и проинитили 4 порта, потом выставили на них значение - сколько машинных тактов будет крутиться код при ините и при переключении? А если не 4 пина, а 13 пинов и все на РА? Если с парой светодиодов работать именно как с пинами, то нельзя их выставить в 0 одной командой. Будет две записи в BSRR, разница лишь в том, что для второго светодиода базовый адрес уже будет загружен и вместо 3 команд на ассме получим 2. Теоретически можно сделать такой метод, который бы принимал разные пины и инитил за раз, но особой необходимости в этом не вижу... Если же мы изначально выбираем работу с группой пинов, то при установке значений все равно будет одна запись в BSRR и получим практически или такой-же по размеру код, как и для одного пина. То же самое будет происходить если переключать группу пинов с входа на выход и т.п., т.е. частичную переинициализацию можно выполнять достаточно эффективно. При полной инициализации уже вызывается функция инициализации, для группы пинов она достаточно тяжелая, там в цикле считается двойная маска, я просто выбрал вариант с меньшим размером кода. Начальная инициализация выполняется один раз и скорость там не важна. и второе.... вижу ledRed - это объект класса LedOpenDrain. Т.е. ledRed в будещем нельзя изменить и сделать как OutPullUp? У меня был такой-же вопрос. Скорее всего можно переключать и в другие состояния тоже, но выглядит это действительно странно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Я пишу свой файл local где детально описываю все ноги, включая неиспользуемые. Описываю оборудование применяемое на ногах. А я не пишу никаких local файлов. Пример выше собирается без доп. файлов. Нужно лишь указать путь к Pin.hpp в настройках проекта. Но не потому, что нет другого выхода. Потому что это способ сразу видеть схему, глазами программиста. Именно поэтому всю привязку пинов я выношу в отдельный файл, просто ряд дефайнов, чтобы уйти от PA7, PB3 и т.п. на человеческие имена, соотв. схеме. И главное, мне не ответили в чём выигрыш? В переносимости и читаемости кода не в момент написания, а вообще, в любое время. Я настраиваю пины именно в тех модулях, которым они принадлежат. У меня проект построен по модульному принципу. Модули имею логическое разделение, и делится не по периферии/портам и т.п., а по смыслу. Некоторые модули стартуют с задержкой и нельзя инициализировать их пины раньше инициализации железа, на котором они висят. Мне важно контроллировать порядок и инициализации железа. Для отладки удобно вообще отключать некоторые модули (два символа //) Раньше все было свалено в кучу и создавала кучу проблем, теперь все разбито на логически независимые модули, которые можно переносить из проекта в проект, при этом править приходит только то, что относится к этим модулям. Мне сложно вам это объяснить, я до этого дорастал долго и мучительно, но обратно уже не вернусь. Тем более на груду макросов/дефайнов, раскиданных по всему коду )) Покажу примером (Application.cpp): #include "Kernel.hpp" #include "Application.hpp" void Kernel::initializeModules() { WatchDog::getInstance().initialize(); Communication::getInstance().initialize(); .... MotionControl::getInstance().initialize(); Leds::getInstance().initialize(); Settings::getInstance().initialize(); } void Kernel::runModules() { WatchDog::getInstance().run(); Communication::getInstance().run(); ..... MotionControl::getInstance().run(); Leds::getInstance().run(); Settings::getInstance().run(); } void Kernel::initializeHardware(void) { ... настраивается максимум тактирование ядра и шин } В каждом таком модуле может быть несколько задач (потоков) или вообще не быть. Пины и периферия "принадлежат" модулям, там же инициализируются и настраиваются. Прерывания тоже сделаны в виде классов (долго мудохался, но добился своего), никаких extern "C" irq и т.п. Функция main скрыта в библиотеки rtos, ее не нужно реализовывать, достаточно лишь подключить соотв. lib файл и Kernel.hpp Никаких глобальных объектов, все обращение модулей друг другу ТОЛЬКО через соотв. открытые методы. Если класс получается непереносимый, и его нельзя заимствовать? Откуда такие выводы? Все как раз наоброт! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Почему же нельзя? Конечно, можно, но это будет неправильно - нарушается логичность кода (какой смысл в runtime делать такие странные вещи - изменять схему подключения пина), лучше использовать для этого другой класс со своим функционалом: DigitalOutputPin Этот DigitalOutputPin, его же можно заставить работать и на вход? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Этот DigitalOutputPin, его же можно заставить работать и на вход? :) Да, можно. Но это можно сделать лишь нарочно, т. е. сознательно ставить палки в колеса. Мазохизм в чистом виде :) Если бы этот код уходил в виде библиотеки для имбицилов-программеров, то он выглядел бы совсем иначе. Где подобные "фокусы" не работали бы... Но это - уход от темы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Да, можно. Но это можно сделать лишь нарочно, т. е. сознательно ставить палки в колеса. Мазохизм в чистом виде :) Если бы этот код уходил в виде библиотеки для имбицилов-программеров, то он выглядел бы совсем иначе. Где подобные "фокусы" не работали бы... Но это - уход от темы. Есть у меня один экранчик, там ноги тача совмещены с данными, соответственно они могут работать как цифровые входы/выходы или как аналоговый вход. Какой класс пина нужно выбрать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Где ж он короче? я не говорю, что он короче. в данном контексте я сказал что он также понятен и прост. Не залазия в хидер всё понятно. А содержимое initRedLed, ledRedOff, ledRedOn кто за вас писать будет? Вася Пупкин? тот же кто напишет Pin.hpp какой смысл в runtime делать такие странные вещи - изменять схему подключения пинаЕсть 1Wire, програмный i2c, can..... Или вообще, просто Pin, но тогда придется вызывать вручную несколько методов, которые настроят пин на нужные параметры (подтяжка, направление, альтернативные функции и т. п.). я менял один бит в соответствующем регистре. например.... динамическая индикация 4-х 7-ми сегментников с точкой. в прерывании от таймера нужно 8 портов выкл/откл, плюс общие катоды (4 шт). можно конечно вашими классами это сделать, проскочить по всем пинам и дернуть у всех On() или Off(). сколько вы просидите в прерывании? И если на остальное времени не хватит... то вы "не будете втаптывать код".... попросите вагон спичек, ну чтоб не экономить. а это можно сделать одной командой GPIOA->BSRR = indicator[++curentNumber&3]; //где uint32_t indicator[4] - выставляется код каждого символа в основном потоке да я согласен, что с++ рулит на мк. но не всегда и не везде. И ваш Pin.hpp не имеет отношения к использованию b. оно может жить и вместе и порознь. вкус и цвет.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Есть у меня один экранчик, там ноги тача совмещены с данными, соответственно они могут работать как цифровые входы/выходы или как аналоговый вход. Какой класс пина нужно выбрать? Просто Pin, от которого наследуются более узкоспециализированные (появились сравнительно недавно, так оказалось удобнее). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Порты инициализирую сразу, а не попиново, но инициализация всё равно имеет мнемонику пинов, что не ухудшает переносимость. Код в студию :) Я приводил пример инициализации портов для FSMC двумя строками, но также видел людей которые делали то же самое и код занимал страницу, при этом они гордились тем, как у них все подробно и понятно расписано :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться