|
Работа с ногами AVR на С++, Проблема переноса с IAR на WinAVR |
|
|
|
Nov 7 2009, 19:19
|

Местный
  
Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470

|
Цитата Ну и нормально Только #if defined (PORTA) - лишнее, ибо не будет вызываться, пока вы не определите Pin<'A'...>. В этом прелесть шаблонов Да? А я ведь сначала без этих излишеств написал. У меня WinAVR тогда ругается Код 'PORTE' was not declared in this scope ну и действительно такого порта нет в восьмой меге например. А компилятор всетаки анализирует весь текст видимо. Может я чтото не так сделал? С другой стороны для порта A дейсвительно это лишняя проверка, потомучто этот порт есть у всех авр-ок  По поводу режима ноги - для сложных случаев я оставил режим BIDIR. Можно еще режимов напридумывать. Я ж ведь ради чего это делаю - чтобы не париться с инициализацией ножек. Хочется чтоб это все делал конструктор. Вот кстати непонятка: если обьявление Pin<'A'...> сделано НЕ внутри какойто функции, то куда вставит компилятор код конструкторов? Цитата А вы, похоже, смотрели вариант для stm32? Да. Но я просмотрел всю тему. Полезного почерпнул не только из последнего поста.
|
|
|
|
|
Nov 7 2009, 22:17
|

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

|
Цитата(Waso @ Nov 8 2009, 00:19)  У меня WinAVR тогда ругается Код 'PORTE' was not declared in this scope Хм. Действительно. Надо подумать  Цитата По поводу режима ноги - для сложных случаев я оставил режим BIDIR. Можно еще режимов напридумывать. Я ж ведь ради чего это делаю - чтобы не париться с инициализацией ножек. Хочется чтоб это все делал конструктор. Зачем плодить сущности? Пусть её инициализирует конструктор, но не конструктор ножки, а конструктор объекта, которому принадлежит ножка. Ну хотя дело конечно ваше  Цитата Вот кстати непонятка: если обьявление Pin<'A'...> сделано НЕ внутри какойто функции, то куда вставит компилятор код конструкторов? В глобальную инициализацию. Обычно после обнуления секции BSS. Цитата Но я просмотрел всю тему. Полезного почерпнул не только из последнего поста.  Это хорошо  Просто мне показалось, что вариант MSP больше подходит для AVR.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 24 2009, 18:19
|

Местный
  
Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470

|
Продолжу задавать вопросы по плюсам в этой теме. Предыстория та-же. Написал класс клавиатуры MtxKeyboard со статическими переменными и функциями. Не забыл добавить в него виртуальные функции, которые будут и у наследников. Наследники такие: Код template<int row, int col> class MtxButton : public MtxKeyboard { public: /*virtual /*inline*/ uint8_t Get() { return State[(col-1)]&(1<<(row-1));} /*virtual /*inline */ uint8_t Pressed() { return (Get()&&(Ticks>=KEYPRES_TRESHOLD))? 1 : 0;} /*virtual /*inline */ uint8_t Locked() { return (Get()&&(Ticks>=KEYLOCK_TRESHOLD))? 1 : 0;} }; Простенькая тестовая прога: Код MtxButton<1,1> Key_Num1; MtxButton<1,2> Key_Num2; MtxButton<1,3> Key_Num3; MtxButton<1,4> Key_Num4; //========== еще 16 кнопок
class Client_c {public: Client_c(MtxKeyboard * pB):pButton(pB){}; MtxKeyboard * pButton;};
Client_c Client_1(&Key_Num1); Client_c Client_2(&Key_Num2); Client_c * pClient[]={&Client_1,&Client_2};
int main(void){ for(;;) { Keys.Scan(); if (Key_Num1.Pressed())pin1.Toggle(); if (Client_1.pButton->Pressed())pin2.Toggle(); } return 0;} на максимальной оптимизации в WinAVR130309 компилится в 500+ байт кода и около 10байт ОЗУ. Но вот как только я делаю функции наследников виртуальными - таже прога компилится в 3000+ байт кода и 230байт ОЗУ. Я в курсе про таблицу вызова виртуальных процедур, но 2 тыщи слов она не сожрет. В чем проблема? По сгенеренному асму не могу понять.. Какбудто оптимизация отключается. На всякий случай приложил исходники.
|
|
|
|
|
Nov 24 2009, 18:44
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Как только функции стали виртуальными у класса MtxButton<> появились собственные данные - указатель на таблицу виртуальных методов. Соответственно появились конструкторы, что бы эти данные проинициализировать. Далее, т.к. объекты статические и с конструктором, появились вызовы конструкторов до main, что потянуло всю run-time поддержку для вызова таких конструкторов и деструкторов. Можно спросить - нафига наследовать MtxButton от MtxKeyboard , которая по жизни должна быть одна на всех, да еще и с виртуальными функциями, что вообще нонсенс. Такое наследование логически породит столько клавиатур, сколько будет создано кнопок. Если уж хочется приткнуть куда нибудь клавиатуру, сделай так: Код class BtnBase { protected: static MtxKeyboard keyboard; };
template<int row, int col> class MtxButton : public BtnBase { public: uint8_t Get() { return keyboard.State[(col-1)]&(1<<(row-1));} uint8_t Pressed() { return (Get()&&(keyboard.Ticks>=KEYPRES_TRESHOLD))? 1 : 0;} uint8_t Locked() { return (kGet()&&(keyboard.Ticks>=KEYLOCK_TRESHOLD))? 1 : 0;} };
|
|
|
|
|
Nov 25 2009, 06:16
|

Местный
  
Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470

|
Цитата Можно спросить - нафига наследовать MtxButton от MtxKeyboard , которая по жизни должна быть одна на всех, да еще и с виртуальными функциями, что вообще нонсенс. Ну я сделал все члены класса MtxKeyboard статическими, так что этот класс не должен размножаться при появлении дочерних классов. Но ваша запись со вложенным статическим классом более грамотна, спасибо. Виртуализовать функции кнопок я хочу чтобы была возможность загонять указатели на них в массивы и потом динамически перебирать в цикле. Хотя это и не всегда надо и всегда можно обойти, но если есть возможность без огромных неоправданных затрат использовать красивости плюсов - я хочу их использовать. Просто я только начинаю осваивать плюсы и могу легко сваять слона из мухи по неопытности. Такчто не раздражайтесь пожалуйста сильно по этому поводу.
|
|
|
|
|
Nov 26 2009, 07:19
|

Местный
  
Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470

|
Ладно, чтобы не смотрели на меня косо, открою карты. =) Мне надо написать прогу для работы пульта оператора, к которому подключается до 20 панелей клиентов. Для каждого клиента на пульте есть кнопка и двухцветный светик. Поведение всех клиентов описывается одной машиной состояний (StateMachine). Я задумал описать класс клиента, который содержит статус, процедуру обработки состояний, и ссылки на свои кнопку и светик, которые инициализируются в конструкторе. Кнопки и светики описаны в отдельных классах с интерфейсом "Нажата?", "Включить красный", "Выключить" и тп.. В main будет цикл, который будет перебирать массив указателей на классы клиентов и запускать процедуру обработки очередного клиента. Одна виртуальная функция добавляет 50байт кода для каждой кнопки или светика. Умножаем на кол-во кнопок и светиков, и еще на колво виртуальных методов и получаем много килобайт, невлезаем. Вот я и думаю как бы поизящнее решить эту проблему, чтобы поменьше писанины и пооптимальнее код.
От виртуальных функций можно избавиться, избавившись от шаблонов и заплатив парой байт ОЗУ на каждую кнопку и светик - помнить номер строки и столбца не как параметр шаблона, а как константу.
Интересно как решали такую проблему другие. =)
|
|
|
|
|
Nov 26 2009, 08:09
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(Waso @ Nov 26 2009, 10:19)  Одна виртуальная функция добавляет 50байт кода для каждой кнопки или светика. Это не виртуальная функция добавляет, а шаблонный класс. Для такого применения шаблоны не годятся. Цитата Вот я и думаю как бы поизящнее решить эту проблему, чтобы поменьше писанины и пооптимальнее код. От виртуальных функций можно избавиться, избавившись от шаблонов и заплатив парой байт ОЗУ на каждую кнопку и светик - помнить номер строки и столбца не как параметр шаблона, а как константу. Именно так. Пара констант (не обязательно в ОЗУ, кстати) займут много меньше кода, чем 3 функции. Цитата Интересно как решали такую проблему другие. =) Можно вообще отказаться от констант, если передавать их в качестве параметра (или глобала) в цикле в main. Такое решение позволит съэкономить память, но идет вразрез с ООП. (Собственно при таком подходе это будет обычная, не ООП программа)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|