Операции со структурой IPAddress

rico
Offline
Зарегистрирован: 26.08.2014

Добрый день!

Начал разбираться с библиотекой Ethernet и, в частности, со структурой IPAddress.

Возник ряд вопросов, на которые пока не смог найти ответа:

1. В одном из примеров предложен следующий способ задания значения:

#define REMOTE_IP 192,168,10,41
IPAddress RAddr(REMOTE_IP);

но мне нужно задавать значения динамически, в процессе исполнения. Как это правильно сделать? Корректно ли обращение вида:

RAddr[0]=192;
RAddr[1]=168;
RAddr[2]=100;
RAddr[3]=1;

2. Нашел метод fromString(), который позволяет передать значение из строки. А как передать значение из четырехбайтового значения, unsigned long, например?

P.S. С языком только разбираюсь, раньше только с Delphi сталкивался.

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015
#define uswap_32(x) \
        ((((x) & 0xff000000) >> 24) | \
         (((x) & 0x00ff0000) >>  8) | \
         (((x) & 0x0000ff00) <<  8) | \
         (((x) & 0x000000ff) << 24))
         
IPAddress ip;

void setup()
{
    Serial.begin( 9600 );
}

void loop()
{
    ip[0]=192;
    ip[1]=168;
    ip[2]=100;
    ip[3]=1;

    Serial.println( ip );
    
    uint32_t utmp32 = ip;
    
    utmp32 = uswap_32( utmp32 );
    
    ip = utmp32;
    
    Serial.println( ip );
}

 

rico
Offline
Зарегистрирован: 26.08.2014

Спасибо! Не все конструкци понял, но буду разбираться.

rico
Offline
Зарегистрирован: 26.08.2014

Подскажите еще, пожалуйста, как правильно собрать строку для вывода в Serial.

Есть некая исходная строка:

String S;

И есть значение, возращаемое функцией:

RTC time;
time.gettime("Y-m-d H:i:s");

описанной как

char* gettime(char*);

Хочется вывести сначала отметку времени, а потом саму строку. Как правильно собрать все это в одном объекте String? Вызов

Serial.println(String(time.gettime("Y-m-d H:i:s")) + S);

выдает пустую строку, хотя в S есть текст. И отдельный вывод gettime тоже нормально выводится.

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Попробуйте сначала что попроще, а потом подставляйте своё (может быть gettime возвращает ноль):

char s1[3] = "12";

String s = "123";

void setup()
{
    Serial.begin( 9600 );
    
    Serial.print( String( s1 ) + " " + s + "\r\n" );
}

void loop()
{
}

 

rico
Offline
Зарегистрирован: 26.08.2014

Спасибо. Я уже понял, в чем дело было. После подключения очередной библиотеки в Uno банально перестало хватать памяти для объектов. VS  об этом явно не предупреждает, а вот ArduinoIDE при попытке скомпилировать - сразу сказало, что памяти может не хватить.

Похоже, что в моем случае преобразование типов String(time.gettime(...)) неумолимо приближает невозможность ее выделения под объект типа String. Может, какой-то более экономный способ есть, кучу всего вывести в Serial без больших затрат памяти?

А кроме Кернигана и Ритчи - что порекомендуете почитать?

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Не помню, чтобы они про C++ писали, но, вообще говоря, для мк обычные книги подойдут только отчасти. Желательно не использовать выделение памяти под объекты вообще, а все классы объявить статическими, т.к. никаких ресурсов мк для C++ не хватит. Никаких операторов new и много чего ещё, иначе нужно покупать сразу Mega 2560, но и она не панацея, забить можно очень легко.

Программирование на C++ для встраиваемых систем имеет определённые ограничения и в двух словах их не объяснить. Не могу посоветовать книжки, но могу посоветовать тупо делать эксперименты. Есть одно простое правило - писать на C++ в стиле C, только обёртывать код не в функции, а в статические классы с методами.

Есть ещё одно правило - все постоянные строки должны располагаться во флеш. ОЗУ на них тратить не имеет смысла. Я пока не понял как это устроено в Arduino, у меня есть свой собственный способ, но он не совместим с классами Arduino.

rico
Offline
Зарегистрирован: 26.08.2014

uni пишет:
только обёртывать код не в функции, а в статические классы с методами.
Поясните, пожалуйста, в чем здесь  особенность?

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Разница в использовании ОЗУ. Если описать класс и создать его экземпляр, то расходуется ОЗУ под каждый экземпляр и ОЗУ быстро заканчивается. Его не так много в мк, чтобы создавать экземпляры классов. Вместо этого классы используют как удобные обёртки для набора функций.

Если класс описать так:

class CMCU 
{
public:
    static void Initialize();
    static void PortsInit();
};

void CMCU::Initialize()
{
}

void CMCU::PortsInit()
{
}

То вызов метода класса делается таким образом:

CMCU::Initialize();

При таком способе использования классов ОЗУ не используется. Все методы и поля класса делаются статическими и такой класс как бы и сам является одним единственным экземпляром. Можно описать мк и периферию только используюя статические классы (и шаблоны). При таком способе результирующий код будет мало чем отличаться от аналогичного кода на C, но удобство его использования будет больше.