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

C++ и ООП для микроконтроллеров AVR

Возможно, вы имели в виду объектное программирование? Т.е. использование классов/объектов? Или именно ООП?

Я именно имел в виду объектно-ориентированный подход к проетированию пограммы, конечно с использованием классов. Но классоы это лишь инструмент. Для меня в свое время это была настоящая ломка перейти к идеологии ООП (с С на С++), но это сугубо личные впечатления. У нас в конторе было чуть ли не табу на использование ++ и ООП для программирования МК, пока мы с напарником за почти два года на собственных примерах (проектах) не сломали этот стереотип.

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


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

Я именно имел в виду объектно-ориентированный подход к проетированию пограммы, конечно с использованием классов.

Хм, интересно... Ну, а вот на примере, скажем. Вот пусть есть дивайс, который выполняет какие-то функции: измеряет температуру на объекте, управляет нагревательным элементом, опрашивает органы управления (кнопки, энкодер и т.п.), выводит соответствующую индикацию, общается с терминалом и т.д. Вот где тут применить ООП?

 

Не, я понимаю, конечно, что "за уши" можно все притянуть - например, создать самый базовый класс TSomething, от него родить класс TInput, от которого родить классы TTempGauge, TButton, TEncoder, от TSomthing родить TOutput, от которого TIndicator и т.п. Но это как-то не выглядит адекватным и логичным, потому что нативной связи между всеми этими классами просто нет. И нет необходимости (да и возможности) рулить поведением объектов производных классов через интерфейс базового.

 

Вот просто создать классы, описывающие составные функциональные части проекта, - это да, правильно и логично. Тут есть смысл, и это даст эффект. Только это не ООП, а объектный подход.

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


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

Мущщины! Вы бы сначала определились в терминах. :) Что вы понимаете под ООП, например? (Hint: классы С++ как таковые - не ООП; шаблоны - не ООП; перегрузка операций - тоже не ООП; и еще много чего в С++ - не ООП :) ).

 

Под ООП я подразумеваю:

1. Инкапсуляцию.

2. Наследование.

3. Полиморфизм.

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


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

Хм, интересно... Ну, а вот на примере, скажем. Вот пусть есть дивайс, который выполняет какие-то функции: измеряет температуру на объекте, управляет нагревательным элементом, опрашивает органы управления (кнопки, энкодер и т.п.), выводит соответствующую индикацию, общается с терминалом и т.д. Вот где тут применить ООП?

Не, я понимаю, конечно, что "за уши" можно все притянуть - например, создать самый базовый класс TSomething, от него родить класс

Ну на AVR конечно не просто, хотя...

Но вот на Sam7 OOП легко...

Допустим "главный" обмен данными ведется через протокол Modbus.

Ну и есть

1,2,3 Uart

1 USB(CDC, типа виртуальный USB-485 переходник прямо в девайсе)

1,2 CAN(мост Modbus <-> CAN)

 

У меня есть структура ModbusInterface и есть наследуемуе от нее структуры UsbInterface, Rs485Interface, итд...

В ModbusInterfect определена общая для всех интерфейсов функциональность, все остальное делается

через общие процедуры SendMessage(), ReceiveMessage(), итд

 

Так же каждый объект может быть мастером или слейвом.

Для всех интерфейсов общая функция таймаута на интерфейсах...

 

Это ООП ?

 

Но оно фсе написанно на чистом С... :laughing:

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


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

У меня есть структура ModbusInterface и есть наследуемуе от нее структуры UsbInterface, Rs485Interface, итд...

В ModbusInterfect определена общая для всех интерфейсов функциональность, все остальное делается

через общие процедуры SendMessage(), ReceiveMessage(), итд

 

Так же каждый объект может быть мастером или слейвом.

Для всех интерфейсов общая функция таймаута на интерфейсах...

 

Это ООП ?

 

Но оно фсе написанно на чистом С... :laughing:

SendMessage(), ReceiveMessage() где определены? И если в ModbusInterface, то как реализовна подмена? И как выполняется наследование на чистом С?

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


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

SendMessage(), ReceiveMessage() где определены? И если в ModbusInterface, то как реализовна подмена?

Определены в ModbusInterface как указатели на функции.

Подмена в момент инициализации объекта.

И как выполняется наследование на чистом С?

Первое поле в структуре потомка ModbusInterface, дальше свои оригинальные поля

ну и приведение типа в функциях ModbusTimeot, ModbusAutomat, итд...

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


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

Определены в ModbusInterface как указатели на функции.

Подмена в момент инициализации объекта.

 

Первое поле в структуре потомка ModbusInterface, дальше свои оригинальные поля

ну и приведение типа в функциях ModbusTimeot, ModbusAutomat, итд...

Ну да, в таком виде похоже на ООП. :) Только это "закат Солнца вручную". :) Почему бы не использовать для этого более адекватные средства - писанины меньше, места для ошибок меньше, наглядности и элегантности больше. Тем более, что эти средства имеются под рукой в полном объеме.

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


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

Ну да, в таком виде похоже на ООП. :) Только это "закат Солнца вручную". :) Почему бы не использовать для этого более адекватные средства - писанины меньше, места для ошибок меньше, наглядности и элегантности больше. Тем более, что эти средства имеются под рукой в полном объеме.

Просто довольно большой проект в котором ООП имеет смысл всего лишь в 2-3 местах,

часть кода моя часть других программистов, все написано на С,

мешать С с плюсами не хотелось.

 

Да и писанины не многим больше чем в плюсах, на самом OO подходе уже большая экономия для этой части.

А что касаемо ошибок, дык приведение типов всего один раз на функцию, а в остальном от плюсов мало в чем отличие.

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


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

А что касаемо ошибок, дык приведение типов всего один раз на функцию, а в остальном от плюсов мало в чем отличие.

 

Еще забыли инициализацию руками (как указателей, так и полей самой базовой структуры, что делается автоматом в ++) в каждом объекте. Тут внимательность нужна - легко не то прописать. Особенно, когда что-то добавляешь/модифицируешь после заметного перерыва в работе над проектом. Писанины все-таки заметно больше - много деталей реализации, которые просто скрыты при использовании рассчитанных на это средств. Исходник больше загроможден "технологическими" деталями.

 

 

Что касается совместной работы, то это не пролема - свою часть держать в отдельных файлах, для взаимодействия с сишной частью написать интерфейс в виде extern "C" функций-оберток. Но вам виднее. :)

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


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

Еще забыли инициализацию руками (как указателей, так и полей самой базовой структуры, что делается автоматом в ++) в каждом объекте. Тут внимательность нужна - легко не то прописать. Особенно, когда что-то добавляешь/модифицируешь после заметного перерыва в работе над проектом.
Здесь я полность согласен с Вами, инициализация таки ручками...

Писанины все-таки заметно больше - много деталей реализации, которые просто скрыты при использовании рассчитанных на это средств. Исходник больше загроможден "технологическими" деталями.
Кроме инициализации там практически нет "лишнего" кода.

Фишек типа присвоить одному объекту значение другого там просто нет за ненадобностью, да и перегрузки операторов нафиг не нужны,

а насчет "технологических" деталей, вот они как раз часто раздувают код в плюсах при неправильном использовании

Что касается совместной работы, то это не пролема - свою часть держать в отдельных файлах, для взаимодействия с сишной частью написать интерфейс в виде extern "C" функций-оберток. Но вам виднее. :)

В этом проекте связок другого кода с моим ООП кодом слишком много(так уж получилось исторически...),

поэтому делать обертки для всего просто не эфективно... потому что придется делать реальные обертки на вызовы коротких функций.

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


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

Люди, поднял тему в связи с глубокой заинтересованностью. Только попытаюсь перенаправить диалог в несколько другое русло. Положим взвесив все "За" и "Против" я сделал выбор в пользу C++ на микроконтроллерах. Пусть даже без STL, как тут уже было сказано "Си с классами", ведь даже так это достаточно мощный инструмент. Мне интересен уже вопрос реализации. Вот, положим, есть задача: пусть мне надо собирать данные с датчиков, подключенных к шине CAN к моему устройству по протоколу CanOpen, обрабатывать эти данные и передавать скажем по GPRS открывая соединение с телнет сервером. По какой логике формировать классы и как создавать объекты? Как быть обработчиками прерываний?

 

Пока я рассуждаю так: в программе я создаю несколько классов: класс мастера протокола CANopen, он будет наследовать класс драйвера CAN, который будет уже привязан к железу; класс\сборщик данных с тензодатчиков, наследующий свойства класса протокола CANopen (раз уж датчики подключены к этой шине); класс тензодатчиков будет наследовать уже верхний класс приложения, которое по определенному алгоритму будет считывать эти данные, этот же класс будет наследовать класс для работы с GPRS модемом. Экземпляр этого то класса и будет создаваться в main() и он будет запускать в работу всё приложение.

 

У меня нет идей как быть с прерываниями, как их обработчики закладывать в классы драйверов? Как все это дело привязвать к RTOS? Вообщем буду очень признателен за любые комментарии по теме.

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


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

Во-первых, ООП вы напрасно определяете через термины C++. Классическое определение: ООП - это объекты обменивающиеся сообщениями. Цитата из вики: Object-oriented programming (OOP) is a programming paradigm that represents the concept of "objects" that have data fields (attributes that describe the object) and associated procedures known as methods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.

То, что предлагает C++ изрядно запутывает программистов. Я бы посоветовал сначала хорошо изучить Си, а потом уже потихоньку залезать в С++, если так хочется.

 

ТС рекомендую не углубляться в архитектуру наследования. Гораздо проще сделать так:

1. Выделить сущности в отдельные модули. Пускай датчик будет в отдельном модуле.

2. Если сущность бывает в единственном экземпляре, то можно оставить как есть - модуль с экспортируемыми функциями. Если вы большой любитель классов, то можно обернуть в синглтон.

3. Если сущность может существовать в нескольких экземплярах, то оборачивайте в класс. Например, датчиков может быть много - делаем класс датчиков.

4. Не заморачивайтесь с наследованием. Сделайте разные датчики копипастой. Когда всё заработает, одинаковый код можно вынести в базовый класс.

5. Чтобы единообразно обрабатывать разные датчики, можно сделать для них общий интерфейс. Когда у вас все датчики будут написаны, общий интерфейс написать будет тривиально.

6. Без динамической памяти писать будет больно. Поля в классах нужно инициализировать руками. Инкапсуляция работает хреново потому как приватные поля светятся в заголовках модулей. Подумайте ещё раз, надо ли вам это, потому что Си гораздо гуманее, чем С++.

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


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

Во-первых, ООП вы напрасно определяете через термины C++...

 

Спасибо за методику! А как быть с обработчиками прерываний? Вот я хочу сделать класс драйверов, как туда засунуть обработчик? И что значит "Поля в классах нужно инициализировать руками", можно на примере это пояснить, если не затруднит?

 

У меня есть работы на голых Сях под RTOS. Относительно хороший. О плюсах и минусах процедурного программирования я более-менее имею представление. Основной недостаток - продолжительное время разработки. Я хочу "на своей шкуре" испытать плюсы и минусы С++. И плюс, про который все твердят - он помогает использовать старый код вновь гораздо легче, чем просто Си. Это то я и хочу проверить.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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