Arduino, кажется, падает, когда uint32_t> 45 - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть приведенная ниже программа, работающая на клоне Uno.

uint32_t counter = 0;

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

void loop() {
    char *result = malloc(32);
    sprintf(result, "%024u", counter);

    Serial.print("{\"n\": ");
    Serial.print(result);
    Serial.println(" }");

    delay(100);
    counter++;
}

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

{"n": 000000000000000000000000 }
{"n": 000000000000000000000001 }
{"n": 000000000000000000000002 }
{"n": 000000000000000000000003 }
....

Однако, каждый раз, когда counter > 45, программа прекращает печать через UART, вот как выглядит вывод в этой точке:

{"n": 000000000000000000000044 }
{"n": 000000000000000000000045 }
{"n":  }

Любое понимание того, что может быть причиной этой проблемы, очень ценится.

Ответы [ 3 ]

0 голосов
/ 27 февраля 2019

malloc () разрешено, но не очень полезно для Arduino с очень ограниченным объемом ОЗУ.

Arduino не имеет операционной системы, которая может создавать помехи, если недостаточно памяти для выделения.(И что же он должен делать, чтобы Arduino работал вечно?)

Если у вас есть Java-фон, также избегайте ключевого слова new, которое вызывает те же проблемы.

Если вам нужна память, получите ее как можно раньше (лучше всего во время компиляции) и сохраните ее.

Конечно, ответ free(result) также верен.

0 голосов
/ 27 февраля 2019

Почему вы не используете String(), как показано ниже:

uint32_t counter = 0;

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

void loop() {

    Serial.print("{\"n\": ");
    Serial.print(String(counter));
    Serial.println(" }");

    delay(100);
    counter++;
}
0 голосов
/ 27 февраля 2019

Каждый раз, когда вызывается loop, выделяется 32 байта памяти.У Arduino Uno не так много памяти, поэтому он быстро иссякает.Вам нужно освободить память, когда вы закончите использовать.Вот аналогия.

RAM это кусок строки.Эта строка имеет фиксированную длину.Вы можете отрезать кусок этой строки и использовать его для чего угодно.Это распределение.Если вы продолжите вырезать 32 байта из вашей строки, у вас в конечном итоге закончится.Вам нужно приклеить кусок строки обратно на основную строку, когда вы закончите ее использовать.Это освобождение.

Это была довольно дурацкая аналогия, но я надеюсь, что вы поняли идею!Чтобы решить непосредственную проблему, вы можете просто добавить free(result) в конец функции, чтобы освобождать каждый раз, когда вы выделяете.Чтобы действительно решить проблему должным образом, вы должны разместить ее в стеке, а не в куче.Когда вы выделяете в стеке, память автоматически освобождается в конце области.Чтобы выделить 32 байта в стеке, вы просто должны сделать следующее:

char result[32];

Память в result действительна только в пределах ее объема (функция loop).Приведенный выше фрагмент в основном эквивалентен следующему:

char result_0;
char result_1;
char result_2;
// ...
char result_29;
char result_30;
char result_31;

Распределение стека происходит намного быстрее, чем выделение кучи (malloc и free), поскольку компилятор точно знает, сколько памяти вы используете.Это имеет свои недостатки, хотя.Чтобы выделить память в стеке, компилятору необходимо знать, сколько памяти вы используете!Вы не можете сделать это:

int size = get_a_number_from_somewhere();
char result[size];

, потому что компилятор не знает, сколько памяти выделить.Однако это:

int size = get_a_number_from_somewhere();
char *result = malloc(size);
// ...
free(result);

полностью в порядке.

В общем случае вы должны выделять в стеке, когда необходимый объем памяти является константой времени компиляции (например, 32) и кучейвыделить иначе.Каждый раз, когда вы пишете malloc, тщательно продумывайте, куда должен идти соответствующий free.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...