реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Программирование на C++, А почему не С++?
KingGeorg
сообщение Oct 23 2004, 12:51
Сообщение #1





Группа: Свой
Сообщений: 9
Регистрация: 20-10-04
Пользователь №: 933



По идее, IAR должны были бы вместе с EC++ и стантдартными библиотеками предоставлять и библиотеки классов, описывающие микроконтроллеры, хотя бы тот же MSP430. Но я у них ничего подобного не нашёл, нет даже упоминаний. Интересно, кто-нибудь вообще в этом деле использует С++ как С++. Если да, давайте одсудим детали. Я (скромный такой rolleyes.gif ) за месяц с небольшим знакомства с предметной областью кое-что своё накарябал. Готов предъявить и получить заимечания.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Oct 23 2004, 13:20
Сообщение #2


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



У IAR вообще всё идёт довольно медленно, но не будем отзываться плохо об отсутствующих.
И тем не менее, даже у них был когда-то туториал (под AVR), где они реализовали таймер в виде базового класса. Странно, что начиная с версии 3.10, они подменили его совершенно никчемным примером с числами Фибоначчи.
Кстати, KingGeorg, давайте обсудим что у Вас есть.
Go to the top of the page
 
+Quote Post
KingGeorg
сообщение Oct 24 2004, 09:31
Сообщение #3





Группа: Свой
Сообщений: 9
Регистрация: 20-10-04
Пользователь №: 933



У меня есть классы:
clocking -- инкапсулирует систему тактирования

DAC12 -- инкапсулирует цифро-аналоговый преобразователь

flash -- инкапсулирует работу с флеш-памятью

abstract_port -- инкапсулирует работу с портами ввода-вывода
|
+-- read_only_port -- реализация порта только для ввода
|......|
|......+-- read_interrupt_port -- то же с обработкой прерываний
|
+---write_only_port -- реализация порта только для вывода

SVS -- инкапсулирует работу с супервайзером питания

timerA -- инкапсулирует таймер А

timerB -- инкапсулирует таймер В

WDT -- инкапсулирует сторожевой таймер
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Oct 24 2004, 10:29
Сообщение #4


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Неплохо, а где можно на реализацию взглянуть?
Go to the top of the page
 
+Quote Post
KingGeorg
сообщение Oct 27 2004, 14:54
Сообщение #5





Группа: Свой
Сообщений: 9
Регистрация: 20-10-04
Пользователь №: 933



Ну, напимер, сторожевой таймер:

Код

#ifndef __WDT_HPP__
#define __WDT_HPP__

#include "430.hpp"
// здесь typedef bit unsigned char
// typedef byte unsigned char, и описания регистров связанных с прерываниями
// от разных устройств (комментарий для сообщения в форум)


struct WDTCTL{
    bit WDTIS    : 2; /* Выбор интервала сторожевого таймера. Эти биты определяют интервал времени
             * сторожевого таймера, по истечении которого устанавливаетс
           * флаг WDTIFG и/или генерируется сигнал PUC.
           * 00 Частота источника тактирования сторожевого таймера / 32768
            * 01 Частота источника тактирования сторожевого таймера / 8192
           * 10 Частота источника тактирования сторожевого таймера / 512
           * 11 Частота источника тактирования сторожевого таймера / 64   */
    bit WDTSSEL  : 1; /* Выбор источника тактирования сторожевого таймера
           * 0 SMCLK    1 ACLK */
    bit WDTCNTCL : 1; /* Очистка счетчика сторожевого таймера.
          * Установкой WDTCNTCL=1 производится очистка счетчика до значения 0000h.
          * Бит WDTCNTCL автоматически сбрасывается.
          * 0 Действие не производитс
          * 1 WDTCNT = 0000h */
    bit WDTTMSEL : 1; /*a Выбор режима сторожевого таймера
          * 0 Сторожевой режим
          * 1 Режим интервального таймера */
    bit WDTNMI   : 1; /* Выбор NMI сторожевого таймера.
          * Этот бит позволяет установить режим функционирования вывода nonRST/NMI.
          * 0 Функция сброса
          * 1 Функция NMI */
    bit WDTNMIES : 1; /* Выбор фронта NMI сторожевого таймера. Этот бит позволяет выбрать
          * фронт прерывания для NMI прерывания при WDTNMI=1.
          * Изменение этого бита может вызвать NMI. Чтобы избежать
          * случайного запуска NMI следует изменять этот бит при WDTNMI=0.
          * 0 NMI прерывание происходит по переднему фронту
          * 1 NMI прерывание происходит по спаду */
    bit WDTHOLD  : 1; /* Останов сторожевого таймера. Этот бит останавливает сторожевой таймер.
          * Установка WDTHOLD=1, когда WDT не используется, позволяет снизить
          * энергопотребление.
          * 0 Сторожевой таймер не остановлен
          * 1 Сторожевой таймер остановлен  */
    byte WDTPW;       /* Пароль сторожевого таймера. Всегда читается как 069h.
          * Должен записываться как 05Ah, в противном случае будет сгенерирован PUC. */

    static const WDTCTL *address;         // адрес настоящего регистра управления WDT

    WDTCTL()                              // конструктор читает данные из настоящего регистра
    { *(int*)this = *(int*)address;    }

    void set(void)                        // установить данные в настоящий регистр
    {
  WDTPW = 0x5A;
  *(int*)address = *(int*)this;
    }
};

class WDT
{
public:
    static void reset(void)    //    сброс и рестарт сторожевого таймера
    {
 WDTCTL wdtctl;
 wdtctl.WDTCNTCL = 1;
 wdtctl.set();
    }

    static void turnOff(void)    //    выключение  сторожевого таймера
    {
 WDTCTL wdtctl;
 wdtctl.WDTHOLD = 1;
 wdtctl.set();
    }

    static void turnOn(void)    //    включение  сторожевого таймера
    {
 WDTCTL wdtctl;
 wdtctl.WDTHOLD = 0;
 wdtctl.set();
    }

    enum dividers{ d32768, d8192, d512, d64}; // значения делителя частоты ст. тайм.

    static void set_divider( const dividers divider) // установека значения делителя частоты
    {
 WDTCTL wdtctl;
 wdtctl.WDTIS = divider;
 wdtctl.set();
    }

    enum source{ SMCLK, ACLK}; // источники тактовой частоты ст. тайм.

    static void set_source( source sour) // установека источника частоты
    {
 WDTCTL wdtctl;
 wdtctl.WDTSSEL = sour;
 wdtctl.set();
    }

    enum modes{ watchdog, interval};    // режимы сторожевой-интервальный
    static void set_mode(modes mode)
    {
 WDTCTL wdtctl;
 wdtctl.WDTTMSEL = mode;
 wdtctl.set();
    }

    enum NMIs{ rst, NMI};
    static void setNMI( NMIs nmi)
    {
 WDTCTL wdtctl;
 wdtctl.WDTNMI = nmi;
 wdtctl.set();
    }

    enum fronts{ front, back};
    static void setNMI( fronts fr)
    {
 WDTCTL wdtctl;
 wdtctl.WDTNMIES = fr;
 wdtctl.set();
    }

    static int getWDTIFG(void)
    {
 return WDTIFG;
    }


};

#endif
Go to the top of the page
 
+Quote Post
KingGeorg
сообщение Nov 1 2004, 16:11
Сообщение #6





Группа: Свой
Сообщений: 9
Регистрация: 20-10-04
Пользователь №: 933



А вот код инкапсулирующий ЦАП
Код
#ifndef __DAC12_HPP__
#define __DAC12_HPP__
#include "430.hpp"

struct DAC12_CTL
{
    bit DAC12GRP   : 1; /* Группировка ЦАП12. Группируется DAC12_x с DAC12_х, имеющий следующий
                     * более высокий порядковый номер. 0 Нет группировки 1 ЦАП`ы сгруппированы */
    bit DAC12ENC   : 1; /* Включение преобразования ЦАП12. Этот бит включает модуль ЦАП12,
                     * когда DAC12LSELx>0. Когда DAC12LSELx=0, бит DAC12ENC игнорируется.
                     * 0 ЦАП12 выключен 1 ЦАП12 включен */
    bit DAC12IFG   : 1; /* Флаг прерывания ЦАП12 0 Прерывание не ожидается 1 Прерывание ожидается */
    bit DAC12IE    : 1; /* Разрешение прерывания от ЦАП12 0 Запрещено 1 Разрешено */
    bit DAC12DF    : 1; /* Формат данных ЦАП12 0 Натуральный двоичный 1 Формат с дополнением до двух */
    bit DAC12AMP   : 3; /* Настройка усилителя ЦАП12. Эти биты выбирают время установки в зависимости
                     * от потребляемого тока для входного и выходного усилителей ЦАП12
                     * DAC12AMPx  Входной буфер              Выходной буфер
                     *    000     Выключен ЦАП12 выключен,   выход в высокоимпедансном состоянии
                     *    001     Выключен ЦАП12 выключен,   на выходе 0В
                     *    010     Низкая скорость/ток        Низкая скорость/ток
                     *    011     Низкая скорость/ток        Средняя скорость/ток
                     *    100     Низкая скорость/ток        Высокая скорость/ток
                     *    101     Средняя скорость/ток       Средняя скорость/ток
                     *    110     Средняя скорость/ток       Высокая скорость/ток
                     *    111     Высокая скорость/ток       Высокая скорость/ток */
    bit DAC12IR    : 1; /* Входной диапазон ЦАП12.
                     * Этот бит устанавливает диапазон входного опорного напряжения и выходного напряжения.
                     * 0 Полный диапазон выходного напряжения ЦАП12 равен 3-х кратному опорному напряжению
                     * 1 Полный диапазон выходного напряжения ЦАП12 равен 1-но кратному опорному напряжению */
    bit DAC12CALON : 1; /* Включение калибровки ЦАП12. Этот бит инициирует последовательность калибровки
                     * смещения ЦАП12 и сбрасывается автоматически после завершения калибровки.
                     * 0 Калибровка не выполняетс
                     * 1 Инициирование калибровки / выполняется калибровка */
    bit DAC12LSEL : 2;  /* Выбор загрузки ЦАП12. Выбирается сигнал запуска загрузки защелки ЦАП12. Для обновлени
                     * ЦАП должен быть установлен DAC12ENC, за исключением случая, когда DAC12LSELx=0.
                     * 00 Загрузка в защелку ЦАП12 выполняется при записи в DAC12_xDAT
                     *     (DAC12ENC игнорируется)
                     * 01 Загрузка в защелку ЦАП12 выполняется при записи в DAC12_xDAT, или,
                     * когда используется группировка, при записи во все регистры DAC12_xDAT группы
                     * 10 Фронт сигнала c Таймера_А3.Выход1 (TA1)
                     * 11 Фронт сигнала c Таймера_B7.Выход2 (TB2) */
    bit DAC12RES   : 1; /* Выбор разрешения ЦАП12 0 12-разрядное разрешение 1 8-разрядное разрешение */
    bit DAC12SREF  : 2; /* Выбор опорного напряжения ЦАП12 00 VREF+ 01 VREF+ 10 VeREF+ 11 VeREF+ */
    bit reserved   : 1; /* Не используется */
};
__no_init volatile DAC12_CTL dac12_ctl[2] @ 0x01C0;

struct DAC12_DAT
{
    unsigned int data       :12; /* данные ЦАП */
    unsigned int reserved   : 4; /* Не используется */
};
__no_init volatile DAC12_DAT dac12_dat[2] @ 0x01C8;

class DAC12
{
    byte n;
public:
    DAC12(byte no) : n(no-1)
    {}

    enum grouping{ nogrp, grp};
    void group(grouping g){ dac12_ctl[n].DAC12GRP = grp; }    // группировка ЦАПов

    void on( void) { dac12_ctl[n].DAC12ENC = 1; }           // включение и

    void off(void) { dac12_ctl[n].DAC12ENC = 0; }           // выключение ЦАП

    bit is_interrupt(void){ return dac12_ctl[n].DAC12IFG; } // Флаг прерывания ЦАП12

    void enable_interrupt(){ dac12_ctl[n].DAC12IE = 1; }    // Разрешение прерывания от ЦАП12

    void disable_interrupt(){dac12_ctl[n].DAC12IE = 0; }    // Запрет прерывания от ЦАП12

    enum formats{ natural, up_to_two};
    void data_format( formats fmt){ dac12_ctl[n].DAC12DF = fmt; } // Формат данных ЦАП12

    /* не стал делать enum */
    void amp_cust( byte a){ dac12_ctl[n].DAC12AMP = a; }    // Настройка усилителя ЦАП12.

    enum ranges{ x3, x1};
    void range( ranges r){ dac12_ctl[n].DAC12IR = r; }      // Входной диапазон ЦАП12.

 void calibration(void){ dac12_ctl[n].DAC12CALON = 1; }  // Включение калибровки ЦАП12.

 enum run_signals{ DAC12_DAT, DAC12_DAT_or_group, A3_1, B7_2};
 void sel_loading(run_signals s) { dac12_ctl[n].DAC12LSEL = s; } // Выбор загрузки ЦАП12.

    enum permissions{ x12, x8};
 void permission( permissions p){ dac12_ctl[n].DAC12RES = p; }   // Выбор разрешения ЦАП12

 enum reference_voltages{ VREF, VREF_, VeREF, VeREF_ };
 void ref_volt( reference_voltages v){ dac12_ctl[n].DAC12SREF = v; } // Выбор опорного напряжения ЦАП12

 int operator =( int value)
 { return dac12_dat[n].data = value & 0x0FFF; }

};

#endif

Обеспокоен Вашим молчанием, господа unsure.gif. Хотелось бы узнать мнение компетентных специалистов.
Go to the top of the page
 
+Quote Post
lamerok
сообщение Nov 2 2004, 04:50
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Уважаемый KingGeorg

Я все таки так и не пойму, зачем все это делать через С++?????
Можете вы мне объяснить преимущества???? А то до сих пор пока не вижу никаких преимуществ. И никто толком объяснить не можем в чем фишка.
Все это можно, точно также лаконично, только без объявления класса описать на обысчном С и оформить в виде библиотеки....
Go to the top of the page
 
+Quote Post
KingGeorg
сообщение Nov 4 2004, 11:38
Сообщение #8





Группа: Свой
Сообщений: 9
Регистрация: 20-10-04
Пользователь №: 933



Фишка вот в чём. Всё это нет никакого резона писать не только на С++, но и на С. Можно на ассемблере. Если нужно только сбрасывать в цикле сторожевой таймер, или только передать одно значение на ЦАП.
А если программа достаточно сложная, должна принимать решения в зависимости не от 3 -10, а от 500 условий? Причём условий имеющих разную природу?
С++ нужен не для того, чтобы делать что-то через него. А для того, чтобы описать на нём предметную область, выделить в ней объекты-субъекты, определить что каждый из них может делать, и забыть об их внутреннем устройстве. Каждый из объектов теперь можно считать "чёрным ящиком", о котором мы знаем как он себя ведёт и собираем систему из них. Это и есть ООП.
Конечно, любую предметную область можно описать и на процедурно-ориентированном языке. При этом хочешь -- не хочешь существует суперобъект "ПРОГРАМА", который всё и делает. Но предметные области не состоят из единственного объекта. Не состоят они и из "действий", непонятно кем производимых, над "данными". Предметные области состоят из сущностей которые взаимодейтствуют, влияют друг на друга, изменяют состояния друг друга, и, тем самым изменяют состояние всей системы. Так что объектно-ориентированное описание получается более адекватным.
По поводу лаконичности:
Лаконичным должен быть исполняемый код. Как этого добиться -- проблемы компилятора. Справляется. А исходный код должен быть понятен хотябы автору, даже через неделю. Ну устроены мы так, что подавай нам избыточность.
Go to the top of the page
 
+Quote Post
-Tумблер-
сообщение Nov 5 2004, 13:32
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 4-11-04
Из: Московская область
Пользователь №: 1 040



Цитата(KingGeorg @ Nov 4 2004, 03:38 PM)
А если программа достаточно сложная, должна принимать решения в зависимости не от 3 -10, а от 500 условий? Причём условий имеющих разную природу?


Да - если это так, то на мой взгляд, выгоднее описывать
обьекты конечными автоматами. И программа будет структурно
выглядеть как совокупность автоматов (в том числе подчиненных).
А С++ тут ни при чем. По крайней мере - прямым образом.
Он дает выигрыш если нужно динамически создавать-уничтожать
большое кол-во однотипных обьектов. И вообше при создании
гигантских программных продуктов. (как MS Word)

O-кстати! Например, писать программаторы конечно лучше
всего на ++ - большое количество похожих но не точно
одинаковых обьектов.
cool.gif


--------------------

- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Nov 5 2004, 15:03
Сообщение #10


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Уже давно пишу на С++ для МК.
Плевать на снижение на 0.5% производительности и увеличение на 1.5% объёма кода.
Проекты разные: от 0.5К до 1.5М.
Пишу на С++ не из религиозных соображений, а просто потому, что УДОБНО мыслить категориями объектов, а не алгоритмов.
Пытался даже пропагандировать среди коллег, но недолго, т. к. быстро осознал тщетность этих попыток. Со временем они и сами перешли на С++, когда увидели преимущества (но не раньше) даже те, кто был ярым сторонником ассемблера и АлгоритмБилдера (последний похоронили как страшный сон).
Мой совет начинающим - не слушайте ничьих советов, пробуйте ВСЁ (пока ещё не выработалась интуиция) и только на основании собственного опыта делайте выводы.
По крайней мере ответственность за принятые решения будет только Ваша.
Go to the top of the page
 
+Quote Post
lamerok
сообщение Nov 10 2004, 09:42
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



KingGeorg
Попробывал маленький проектик, аля мигание...Вобщем то работает-). Тока кода получилось многовато.
Ок. Понятно. Т.е я так понимаю, что резонно применять С++ только в здоровых приложениях, в которых есть нормальный запас по памяти.
Для мелких проектов С++ избыточен.
Go to the top of the page
 
+Quote Post
froakch
сообщение Nov 15 2004, 09:50
Сообщение #12





Группа: Новичок
Сообщений: 5
Регистрация: 4-11-04
Пользователь №: 1 037



Цитата
У меня есть классы:
clocking -- инкапсулирует систему тактирования

DAC12 -- инкапсулирует цифро-аналоговый преобразователь

flash -- инкапсулирует работу с флеш-памятью

abstract_port -- инкапсулирует работу с портами ввода-вывода
|
+-- read_only_port -- реализация порта только для ввода
|......|
|......+-- read_interrupt_port -- то же с обработкой прерываний
|
+---write_only_port -- реализация порта только для вывода

SVS -- инкапсулирует работу с супервайзером питания

timerA -- инкапсулирует таймер А

timerB -- инкапсулирует таймер В

WDT -- инкапсулирует сторожевой таймер


KingGeorg, могу я получить flash, timerA, timerB и WDT. Если да, то заранее благодарю (froakch@mail.ru).
Go to the top of the page
 
+Quote Post
Slavik
сообщение Nov 29 2004, 10:11
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 30-09-04
Пользователь №: 746



C++ удобно применять где мегабайты текста.
А для встраиваемых приложений, где к примеру килобайт до пятисот памяти или процессор мегагерц до ста, смысла никакого. Для таких вещей оптимально C/Asm.

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

На мой субъективный взгляд использовать С++ темболее для микроконтроллеров неразумно.
Go to the top of the page
 
+Quote Post
COMA
сообщение Nov 30 2004, 06:10
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 851
Регистрация: 28-08-04
Пользователь №: 559



Цитата(Slavik @ Nov 29 2004, 13:11)
На мой субъективный взгляд использовать С++ темболее для микроконтроллеров неразумно.
*


Почему бы и нет? Если Мы от использования Си++ только выигрываем?
Из плюсов - 3 кита ООП. smile.gif
из минусов:
вижу только "разбухание" исходников, и то что надо немножко "повернуть" голову smile.gif
Но наша цель не компактность исходников а скомпилированного кода. smile.gif

P.S.
Код при компиляциии не увеличивается, если не использовать динамическое объявлении переменных.
Go to the top of the page
 
+Quote Post
Slavik
сообщение Nov 30 2004, 09:44
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 30-09-04
Пользователь №: 746



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

Но, придвидя, что разговор может скатится к теме типа "что лучьше, паскаль или си", умолкаю.

Сам я ярый приверженец Asm, С, С++. twak.gif :D

А наша цель - рабочее устройство, отвечающее заданными требованиям.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 15th June 2025 - 15:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016