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

Конвертирование прошивки из Ардуино в С++ под AVR


Goliard

Рекомендуемые сообщения

Доброго времени суток. Требуется помощь в переделывание прошивки для работы сервопривода. Я сам так и не разобрался, теперь прошу помощи. Готов оплатить труд, Вообщем имеется код прошивки под Ардуино на атмеге 328 и нужно изменить прошивку на "чистый" С++.

UselessMachine.pde

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

7 часов назад, Viktor26 сказал:

Почему

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

@Goliard , библиотеку серво ещё нужно.

Я не раздаю удочки. Я продаю рыбу.

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

  • 3 года спустя...

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Здравствуйте всем!

В программировании на С новичок. Переделываю программу из Ардуино в АВР Студию 4. Попался вот такой кусок кода:

..............................................

void _orientCoordinates(uint16_t &x1, uint16_t &y1) {   

    switch (_orientation) {
    case 0:  // ok
        break;
    case 1: // ok
        y1 = _maxY - y1 - 1;
        _swap(x1, y1);
        break;
    case 2: // ok
        x1 = _maxX - x1 - 1;
        y1 = _maxY - y1 - 1;
        break;
    case 3: // ok
        x1 = _maxX - x1 - 1;
        _swap(x1, y1);
        break;
    }
}

..............................................

void _swap(uint16_t &a, uint16_t &b)
 { uint16_t w = a;
    a = b;
    b = w; }

Посмотрев в инете, понял, что &a и  &b - это "ссылки" на языке С++.  Компилятор С ругается на такое. Как я понял, "ссылка" - это псевдоним переменной и все операции в итоге совершаются с ними. Можно ли тогда сделать код без "ссылок" и оставить одни переменные? Наведите на нужную мысль:unknw:

void _swap(uint16_t a, uint16_t b) // сделать так???
 { uint16_t w = a;
    a = b;
    b = w; }

void _orientCoordinates(uint16_t x1, uint16_t y1) {     // и тут убрать???

Изменено пользователем Nilas
Ссылка на комментарий
Поделиться на другие сайты

Замените на указатели.

PS: Ссылка - это тот же указатель. Просто доступ к ним синтаксически организуется как к переменной. Есть, конечно, ещё нюансы - не может быть пустой, и т.д... Но это Вам не нужно.

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

 

3 часа назад, Nilas сказал:

void _swap(uint16_t a, uint16_t b) // сделать так???

Вот так:

oid _swap(uint16_t *a, uint16_t *b)
 { uint16_t w = *a;
    *a = *b;
    *b = w; }

 

Изменено пользователем BARS_
Ссылка на комментарий
Поделиться на другие сайты

Переделал на указатели:

void _orientCoordinates(uint16_t *x1, uint16_t *y1) {

    switch (_orientation) {
    case 0:  // ok
        break;
    case 1: // ok
        *y1 = _maxY - *y1 - 1;
        _swap(x1, y1);    
        break;
    case 2: // ok
        *x1 = _maxX - *x1 - 1;
        *y1 = _maxY - *y1 - 1;
        break;
    case 3: // ok
        *x1 = _maxX - *x1 - 1;
        _swap(x1, y1);    
        break;
    }
}

void _swap(uint16_t *a, uint16_t *b)
 {
    uint16_t w = *a;
    *a = *b;
    *b = w;

}

Объявил в хидер-файле функции как:

   void _swap(uint16_t *a, uint16_t *b);
   void _orientCoordinates(uint16_t *x1, uint16_t *y1);

Но теперь компилятор выдает варнинги на тип переменных, хотя по моему разумению вроде как все одной масти (uint16_t):

void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    _orientCoordinates(x0, y0);
    _orientCoordinates(x1, y1);

    if (x1 < x0) {_swap(x0, x1);}
    if (y1 < y0) {_swap(y0, y1);}

:292:5: warning: passing argument 1 of '_orientCoordinates' makes pointer from integer without a cast [enabled by default]

.h:148:9: note: expected 'uint16_t *' but argument is of type 'uint16_t'

и т.д. на каждый аргумент.

Хотя на эту функцию не ругается:

...........................................

    case 1: // ok
        *y1 = _maxY - *y1 - 1;
        _swap(x1, y1);    
        break;

............................................

Или в вызове функции надо сразу ставить указатель:  _orientCoordinates(*x0, *y0); , но тогда, как я понимаю, в функцию будут посылаться указатели на переменную (и получится указатель указателя), и обрабатываться будут они, а не переменные?

Изменено пользователем Nilas
Ссылка на комментарий
Поделиться на другие сайты

Цитата

    _orientCoordinates(x0, y0);
    _orientCoordinates(x1, y1);

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

18 минут назад, Nilas сказал:

Хотя на эту функцию не ругается:

 _swap(x1, y1); 

Потому, что x1 и y1 - указатели. И т.к. функция их же (указатели) и принимает, то ошибок нет.

PS: Погуглите и почитайте про указатели. Это элементарное, что есть в этом языке. Так сказать, азы ...

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

Переделал на

void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    _orientCoordinates(*x0,* y0);
    _orientCoordinates(*x1, *y1);

    if (x1 < x0) {_swap(*x0,* x1);}
    if (y1 < y0) {_swap(*y0, *y1);}

Теперь ругается на каждый аргумент:

.c:292:24: error: invalid type argument of unary '*' (have 'uint16_t')

Совсем уже запутался. Понимаю что указатель это адрес переменной, но вот в использовании в функциях:huh:... 
 

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

4 minutes ago, Nilas said:

указатель это адрес переменной

Указатель это переменная. Чтобы получить адрес, нужно использовать &

_orientCoordinates(&x0, &y0);

 

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

Получается, что при вызове функции берем адрес переменной   _swap(&x0, &x1)

В самой функции адрес "перекочевывает" в указатель переменной   void _swap(uint16_t *a, uint16_t *b)

И в самой функции оперирует с переменными через адресацию. 

Сейчас все нормально скомпилировалось! и в коде, и в голове :D

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

Неужели проще тыкать и писать на форум кучу слов, вместо того, чтобы сделать 1 запрос в поисковике и почитать ? :rake:
Тема указателей разжёвана до некуда ...

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

Здравствуйте всем!
В продолжение темы:  третий день бьюсь с чтением из памяти даных. Уже и раскомментировал его, и вроде должен работать, но выдает не то, что надо. Уже всякого начитался в интернете, но в симуляции АВР Студии берутся не те данные, которые должны идти дальше в программе.
Вот так сейчас:

Скрытый текст

 

---------------------------------------шрифты---------------------------------------------------
#define fontdatatype   const uint8_t
#include <avr/pgmspace.h>
fontdatatype Terminal6x8[] PROGMEM = {
    0x06, 0x08, 0x20, 0x60,
    0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char  пробел
………………………………………………………………………………….
    0x06, 0x00, 0x24, 0x7E, 0x24, 0x7E, 0x24,  // Code for char #


Вызов из main:
………………………………………………………………….
setFont(Terminal6x8);        // Terminal6x8 – это и есть первый адрес шрифта

drawChar(10, 180, 'D',COLOR_RED );
// setFont(&Terminal6x8[0]);                //ПРОБОВАЛ ТАК, хотя это одно и то же

................................................................

В хидере:


/* Font defines */
#define FONT_HEADER_SIZE 4 // 1: pixel width of 1 font character, 2: pixel height,
 
#define readFontByte(x)    pgm_read_byte(&cfont.font[x])           // берет байт Х по адресу cfont.font

extern const uint8_t Terminal6x8[];
extern const uint8_t Terminal11x16[];

struct _currentFont
{
 const uint8_t* font;
    uint8_t width;
    uint8_t height;
    uint8_t offset;
    uint8_t numchars;
    uint8_t nbrows;
}cfont;
……………………………………………………………………………..
    /// Draw single character (pixel coordinates) 
    uint16_t drawChar(uint16_t x, uint16_t y, uint16_t ch, uint16_t color);

    /// Set current font    
    /// @param  font Font name
    void setFont(const uint8_t * font);


в  .С  файле
………………………………………………………………………….
void setFont(const uint8_t* font) {
БЫЛО:

    cfont.font = font;                    //адрес таблицы символов (указатель на таблицу)    
    cfont.width = font[0];                    //байт ширины символа
    cfont.height = font[1];                //байт высоты символа
    cfont.offset = font[2];                //байт смещения кода символа 
    cfont.numchars = font[3];                //байт кол-ва символов в таблице шрифтов
*********************************************
СДЕЛАЛ ТАК, т.к. данные берем из памяти программ:
    cfont.font = font;
    cfont.width = (pgm_read_byte(font[0]));                    //    БЕРЕТ 
cfont.height = (pgm_read_byte(font[1]));                      //   ДАННЫЕ
    cfont.offset = (pgm_read_byte(font[2]));                   //    НЕ ИЗ  
    cfont.numchars = (pgm_read_byte(font[3]));            //  ТАБЛИЦЫ

    cfont.nbrows = cfont.height / 8;            //кол-во целых байтов в высоту
    if (cfont.height % 8) cfont.nbrows++;      // если высота делится с остатком, то +1 байт в высоту

}
uint16_t drawChar(uint16_t x, uint16_t y, uint16_t ch, uint16_t color) {

    uint8_t charData, charWidth;
    uint8_t h, i, j;
    uint16_t charOffset;

    charOffset = (cfont.width * cfont.nbrows) + 1;      // кол-во байт на каждый символ
    charOffset = (charOffset * (ch - cfont.offset)) + FONT_HEADER_SIZE;  // кол-во байт для смещения
    charWidth = pgm_read_byte(cfont.font[charOffset]);              // первый байт – ширина символа
    charOffset++;          // на первый байт данных символа

    for (i = 0; i <= charWidth; i++) {      // каждый столбец шрифта (+1 пустой для интервала
        h = 0;                  // отслеживание высоты символа
        for (j = 0; j < cfont.nbrows; j++) {      // каждый байт столбца
            if (i == charWidth) charData = (uint8_t)0x0;     // вставить пустой столбец
            else                charData = pgm_read_byte(cfont.font[charOffset]);
            charOffset++;

            // обработка каждой строки шрифта
            for (uint8_t k = 0; k < 8; k++) {
                if (h >= cfont.height) break;          // выход, если высота больше высоты шрифта
                if (bitRead(charData, k)) drawPixel(x + i, y + (j * 8) + k, color);
                else                      drawPixel(x + i, y + (j * 8) + k, _bgColor);
                h++;
            };
        };
    };
    return charWidth;
}

void drawText(uint16_t x, uint16_t y, char *s, uint16_t color) {

    uint16_t currx = x;

    // Print every character in string
    for (uint8_t k = 0; k < strlen(s); k++) {
        currx += drawChar(currx, y, s[k], color) + 1;
    }
}
…………………………………………………………………………………………….

 


Компилируется без ошибок.
Не могу понять, где не так делаю.
 

Изменено пользователем Nilas
Ссылка на комментарий
Поделиться на другие сайты

8 часов назад, Nilas сказал:

должен работать

setFont принимает const uint8_t* , а Вы ему подсовываете fontdatatype PROGMEM. Откуда уверенность, что всё должно работать ?
Дальше программу даже не смотрел. Хватило этого :)

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

1 час назад, Nilas сказал:

PROGMEM указывает на flash память.

А компилятор сам должен догадаться, что Вы в setFont захотите передать указатель на область flash ?

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

Понял почему были не те данные.  В  setFont(Terminal6x8);  Terminal6x8 является указателем на массив (содержит его адрес), но если обращаться к отдельному его элементу, то надо указывать его адрес : cfont.height = (pgm_read_byte(&(font[1]))); Сейчас идут нужные данные из flash памяти.

Буду дальше ковырять код:blink:

10 часов назад, Alex сказал:

А компилятор сам должен догадаться

Видимо сам догадывается, раз всё компилиться и работает:)

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...