Перейти к содержанию
    

Как ПРАВИЛЬНО программировать на С++

Добрый день. Учусь программировать на С++.

И иногда возникают вопросы в правильном проектировании классов.

Сейчас описываю класс для работы с последовательными регистрами 74HC595.

Уже есть класс для работы с SPI.

Где инициализировать SPI блок AT Mega 168 в классе работы с регистром или же глобально во всей программе.

Сейчас SPI будет использоваться только в регистрах.

Но в будущем планирую параллельно регистрам подключить еще и FLASH память (еще один класс по работе с памятью FLASH) на SPI.

 

Что посоветуете?

 

Вдогонку PS

И как правильно писать классы для регистров и FLASH наследовать от SPI или же внутри классов объявлять член класса SPI?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

нет. как-то це-крест-крест не сильно прижился у эмбеддеров.

 

Да нет, нормально прижился. Просто тут ИМХО вопросы не конкретно эмбеддерские, а уровня проектирования.

Я так понимаю, у вас стоит вопрос расширивания общего ресурса между несколькими потребителями?

Это обычно решается с помощью драйвера устройства. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где инициализировать SPI блок AT Mega 168 в классе работы с регистром или же глобально во всей программе.

 

Поскольку к SPI могут обращаться разные устройства, то объект класса SPI надо сделать глобальным. В конструкторы объектов dataflash, HC595, DAC, ADC, которые висят на SPI, в этом случае надо передавать ссылку на класс SPI.

 

И как правильно писать классы для регистров и FLASH наследовать от SPI или же внутри классов объявлять член класса SPI?

 

Наследовать в этом случае нельзя, а то получится по экземпляру SPI в каждом из объектов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо все заработало. Что бы не плодить тем буду в будущем писать сюда по вопросам проектирования.

Жаль что мне самому не пришла идея использовать указатель на SPI.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну оно "так и надо по теории". Сама флешка не есть вариантом интерфейса SPI или там контроллера SPI, она только пользуется SPI как транспортом, класс флешки есть пользователем класа SPI, поєтому должен получать его для использования.

Если теперь две одинаковых флешки будут висеть на разных контроллерах SPI (один аппаратный, другой программный или один из них на соответствующем режиме USART), то просто два экземпляра одного и того же класса флешки получат по каналу SPI (по указателю или ссылке) для работы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Наследовать в этом случае нельзя, а то получится по экземпляру SPI в каждом из объектов.

А не покатит сделать то, что "глобальное", статическим членом класса? Тогда все унаследуется нормально, без лишних сущностей. Или не?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А не покатит сделать то, что "глобальное", статическим членом класса? Тогда все унаследуется нормально, без лишних сущностей. Или не?

Объекты от статических членов не будут дублироваться только в случае создавание объектов от одного класса. В случае создания объектов от разных классов, объект SPI будет продублирован.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть некоторые интересные наработки на Си плюс плюс под АВР.

Например, виртуальные порты. Можно объединить от одной до 16 произвольно взятых ножек в такой виртуальный порт и манипулировать им как одним целым.

Кому интересно спрашивайте, раскажу подробнее.

 

typedef PinList<Pa1, Pa2, Pa3, Pb3, Pb4, Pb5> pins;

 

int main()

{

pins::DirWrite(0xff);

pins::Write(0xff);

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приведите для интереса asm листинг того, во что это скомпилится:

typedef PinList<Pa1, Pa2, Pa3, Pb3, Pb4, Pb5> pins;

pins::Write(0xff);

Мысль сама по-себе очень удачная. Вы молодец!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть некоторые интересные наработки на Си плюс плюс под АВР.

Кому интересно спрашивайте, раскажу подробнее.

Интересно :rolleyes:

Выложите пожалуйста реализацию

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для

typedef PinList<Pa1, Pa2, Pa3, Pb3, Pb4, Pb5> pins;
pins::Write(0xff);

листинг не очень интересный - всё заоптимизировалось в доску :) поскольку все значеня известны на момент компиляции:

in    r24, 0x1b; 27
ori    r24, 0x0E; 14
out    0x1b, r24; 27

in    r24, 0x18; 24
ori    r24, 0x38; 56
out    0x18, r24; 24

 

Гораздо интереснее вот так:

typedef PinList<Pa1, Pa2, Pa3, Pb3, Pb4, Pb5> pins;
pins::Write(PORTC);

Вместо PORTC можно подставить любое выражение невычисляемое на этапе компиляции.

in    r18, 0x15; 21

in    r25, 0x1b; 27
mov    r24, r18
add    r24, r24
andi    r24, 0x0E; 14
andi    r25, 0xF1; 241
or    r24, r25
out    0x1b, r24; 27

in    r24, 0x18; 24
andi    r18, 0x38; 56
andi    r24, 0xC7; 199
or    r18, r24
out    0x18, r18; 24

 

Как-то так. Если различных портов в списке будет больше и ножки в них не будут упорядочены, то листинг соответственно будет больше.

 

Пример 1

Пример побольше

Реализация

 

Всё это реализовано на основе списков типов и с помощью очень злой и черной шаблонной магии :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Объекты от статических членов не будут дублироваться только в случае создавание объектов от одного класса. В случае создания объектов от разных классов, объект SPI будет продублирован.

Нифига не понял. Вот пример:

 

#include <iostream>

class A
{
  public:
  static int X;
  void printx() {std::cout << X << std::endl;};
  void setx(int x) {X=x;};
};
int A::X=0;


class B : public A
{
  public:
  void printx() {std::cout << X << std::endl;};
  void setx(int x) {X=x;};
};

class C : public A
{
  public:
  void printx() {std::cout << X << std::endl;};
  void setx(int x) {X=x;};
};


int main()
{
  A a;
  B b;
  C c;

  a.setx(10);
  a.printx();
  b.printx();
  c.printx();

  b.setx(20);
  b.printx();
  a.printx();
  c.printx();

  return 0;
}

 

Одна статическая переменная в базовом классе. От базового наследуются 2 класса, каждый видит одну и ту же переменную, так же, как если бы она была глобальной. Как бывает еще?

 

Ответ проги:

10

10

10

20

20

20

 

 

 

 

 

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нифига не понял.

Если вы посмотрите на sizeof(A) и наследуемые классы, то увидите, что int Х в них нет. А если уберете static, то размер классов увеличится.

 

Вот об этом и разговор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...