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

C++ на микроконтроллерах - это просто! Дискуссия-холливар;)

Всем привет!

Я тут на праздниках немного поковырять что-то новое решил...

Этим новым стало применене С++ в микроконтроллерном программировании.

 

Началось всё с прочтения статьи шамана(уж извините) под ником Neiver. http://easyelectronics.ru/rabota-s-portami...erov-na-si.html

С помощью не детских заклинаний, кажется, ему удаётся творить настоящие чудеса, о которых простым смертным Сишникам даже мечтать в голову не приходит )

 

Идеей шаблонной магии я здорово проникся и принялся за изучение главного пособия чёрных магов метапрограммирования - книги Современное проектирование на C++, за авторством Андрея Александреску. http://rutracker.org/forum/viewtopic.php?t=1434859

 

На данном этапе мне доступны лишь заклинания первого уровня, пользуясь которыми я реализовал довольно портабельный драйвер семисегментного индикатора с выводом значения на дисплей вызовом вида Display.DysplayStr("1234"); С поддержкой разных алфавитов символов, разными методами(полярность) засветки сегментов и отвязкой от реализации портов ввода/вывода, которая реализована благодаря библиотеке IO от Neiver. Ознакомиться с исходником можно тут http://pastebin.com/YMM96qz5

 

Вся эта красота и удобство скомпилилось в ~180байт кода и для дисплея с 2мя цифрами требуется 3 байта оперативки )

Драйвер поддерживает от 1 до 6 цифр.

 

Используется драйвер очень просто:

#include <avr/io.h>
#include "iopins.h"
#include "pinlist.h"
#include "7seg.h"

using namespace IO;

//тут пины к которым подключен 7сегментник. 
//любое сочетание доступных пинов(не обязательно по порядку как тут)
typedef PinList<Pc0, Pc1, Pb0, Pb1, Pb2, Pb3, Pb4, Pb5, Pb6, Pb7 > MyPins;
//объевляем дисплей с 2мя цифрами, с методом засветки 0 на сегмент, 1 на цифру и алфавитом из цифр.
SevenSeg<MyPins, 2, LOW, HIGH, DIGITSONLY> disp;
int main(void)
{    
    disp.DysplayStr("18");
    while(1)
    {
//по идее это вызывается в прерывании таймера
        disp.Sync();    
    }
}

 

Как думаете, это действительно так круто как кажется?

Нам всем надо радоваться, что технологии зашли так далеко, что теперь даже 8ми битную АВРку я могу программировать используя очень высокоуровневые конструкции или всё это от лукавого?

 

Потому что я тут еще и библиотеку, реализующую механизм делегатов подтянул www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible

и она даже работает!

Уже хотя-бы на той-же XMEGA можно создавать почти "книжные" архитектуры и паттерны с учетом всех заветов Стива Макконнелла, наставляющего нас посредством своей легендарной книги Совершенный Код(http://cafe-aristokrat.nethouse.ru/static/doc/0000/0000/0102/102807.m0nldixuku.pdf)

 

Не знаю как кто, а я в восторге! Потому что в принципе до сего дня я считал, что С++ это неуместная роскошь, доступная и оправданная как минимум на STM F4 :)

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


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

Этим новым стало применене С++ в микроконтроллерном программировании.

...

Как думаете, это действительно так круто как кажется?

Так ведь МК бывают разные. Одно дело - высокопроизводительный ARM с кучей ОЗУ и ПЗУ, и совсем другое - PIC или AVR. Для восьмибитных МК, ИМХО, обычного Си хватает с головой. Хотя, если вам нравится ... Почему бы и нет ? Вы довольны ? И заказчик доволен ? Тогда зачем вам чьи-то мнения ?

 

P.S. Вспоминаю, как я лет 10 назад открыл для себя Си. Первые же проекты показали, что на нем можно за день сделать то, что на ассемблере делается за неделю или даже две. Вот это было открытие :)

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


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

Не знаю как кто, а я в восторге!

А ведь есть ещё и ось на плюсах. Это уже будет восторг в квадрате:)

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


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

ну а чем это лучше

struct pin {
   int* port;
   int num;
   ...
};

void pin_set(struct pin* pin, bool val){
...
}
...
// дисплей один, поэтому все статическое
static struct pin dist_pins[]={
   { .port=..., .pin=... }, // a
   ...    // f
}

void disp_print(char* str){
...
}

void disp_update(){
...
}

?

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

Использования каких-то особенностей C++, принципиально не реализуемых на C (перегрузки операторов, наследования и т.п.), в приведенном коде не наблюдается. Кстати, Александреску подался в D ;)

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


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

Шаблоны, переносимость, повторное использование мне не нужны. А ООП, инкапсуляция, структурное программирование - назрела необходимость.

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


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

ну а чем это лучше

struct pin {
   int* port;
   int num;
   ...
};

void pin_set(struct pin* pin, bool val){
...
}
...
// дисплей один, поэтому все статическое
static struct pin dist_pins[]={
   { .port=..., .pin=... }, // a
   ...    // f
}

void disp_print(char* str){
...
}

void disp_update(){
...
}

В статье http://electronix.ru/redirect.php?http://e...erov-na-si.html рассмотрены основные проблемы передачи по указателю.

 

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


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

Да да, когда-то я тоже говорил что си наше все и плюсов нам не надо)

Кстати посмотрю как нибудь исходники scmRTOS... Интересно же)

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


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

Поверю в эффективность предложенного, когда увижу управление, например, таймером STM32 с помощью шаблонов. Предполагаю, что не увижу никогда.

А так - нет. Баловство для развлечения. Для обучения неплохо, въехать в C++. А портом дрыгать я и так умею виртуозно.

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


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

В статье http://electronix.ru/redirect.php?http://e...erov-na-si.html рассмотрены основные проблемы передачи по указателю.

Статья интересная. В принципе, практически все то же самое можно было сделать руками и на С. Например, как-то так:

#include <stdbool.h>

enum {
    PORT_A=0,
    PORT_B=1
};

static void portA_set(int pin_num, bool val){
   ...
}

static void portA_dir(int pin_num, bool val){
  ...
}

static void portB_set(int pin_num, bool val){

}

static void portB_dir(int pin_num, bool val){

}

struct port_handler {
    void (*set)(int, bool);
    void (*dir)(int, bool);
};

static struct port_handler handlers[]={
    {   .set=portA_set, .dir= portA_dir },
    {   .set=portB_set, .dir= portB_dir }
};

void port_set(int port_num, int pin_num, bool val){
    struct port_handler* p=&handlers[port_num];

    p->set(pin_num, val);
}

void port_dir(int port_num, int pin_num, bool val){
    struct port_handler* p=&handlers[port_num];

    p->dir(pin_num, val);
}

#define EN_ 9

int main(){
    port_set(PORT_A, EN_, true);
    ...
}

В случае C++ компилятор сам развернет portX_set, portX_dir по шаблону.

Но статья интересная.

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


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

А портом дрыгать я и так умею виртуозно.

 

Как раз в STM32 портом дрыгать намного красивей получается на C++ с использованием шаблонов. Настройка аппаратных таймеров - там монстроидальный шаблонный класс получится, ну его. А вот программные таймеры в виде экземпляров соответствующего класса - это красота.

 

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


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

Настройка аппаратных таймеров - там монстроидальный шаблонный класс получится, ну его.

Из этого следует: C++ с шаблонами не подходит для инициализации аппаратуры чуть посложнее порта ввода-вывода? Так может, ну его... не C++, а шаблон? :rolleyes: Шаблоны хороши для чего-то унифицированного, GUI всякие, кнопки...

Насчет красоты - меня восхищают собственные макрофункции для инициализации и работы с портами. И таймеры я настраиваю столькими (или чуть больше) командами, сколько регистров есть в управляющей аппаратной структуре. Что правильнее - пять команд засылки в регистры или монстроидальный шаблонный класс?

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


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

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

 

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


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

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

Это вы не посчитали строчки в исходнике шаблонного класса. :biggrin:

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


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

Это вы не посчитали строчки в исходнике шаблонного класса. :biggrin:
А вы строчки исходников своих макросов посчитали? :biggrin: Ну больше гибкости дают шаблоны, больше.

 

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


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

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

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

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

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

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

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

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

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

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