Ошибка чтения из PROGMEM

Я пытался запустить код с этого https://circuits4you. .com/2018/03/10/esp8266-jquery-and-ajax-веб-сервер/

Я вставляю это сюда.

/*
 * ESP8266 NodeMCU jQuery CDN Demo
 * 
 * https://circuits4you.com
 */
#include <ESP8266WiFi.h>
#include <WiFiClient.h>

//Библиотека веб-сервера ESP для размещения веб-страницы
#include <ESP8266WebServer.h>

//------------------------------------------------ ---------------
// Содержимое нашей веб-страницы в формате HTML в памяти программы
const char MAIN_page[] PROGMEM = R"=====(
  <!DOCTYPE html>
  <html>
  <head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script>
  $(document).ready(function(){
      $("p").click(function(){
          $(this).hide();
      });
  });
  </script>
  </head>
  <body>
  
  <p>If you click on me, I will disappear.</p>
  <p>Click me away!</p>
  <p>Click me too!</p>
  <br><hr>
  <a href="https://circuits4you.com">circuits4you.com</a>
  </body>
  </html>
)=====";
//------------------------------------------------ ---------------

// Встроенный светодиод подключен к GPIO2
#define LED 2  

//SSID и пароль вашего WiFi роутера
const char* ssid = "circuits4you.com";
const char* password = "yourWiFipassword";

// Объявить глобальную объектную переменную из класса ESP8266WebServer.
ESP8266WebServer server(80); //Сервер на порту 80

//=============================================== ===============
// Эта процедура выполняется, когда вы открываете его IP в браузере
//=============================================== ===============
void handleRoot() {
 Serial.println("You called root page");
 String s = MAIN_page; //Чтение HTML-содержимого
 server.send(200, "text/html", s); //Отправить веб-страницу
}
//=============================================== ==============
// НАСТРАИВАТЬ
//=============================================== ==============
void setup(void){
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);     //Подключитесь к вашему Wi-Fi роутеру
  Serial.println("");

  // Бортовой светодиодный порт Выход направления
  pinMode(LED,OUTPUT); 

  //Включение светодиода выключено
  digitalWrite(LED,HIGH);
  
  WiFi.mode(WIFI_STA); //Режимная станция WiFi (подключение только к Wi-Fi роутеру
  
  WiFi.begin(ssid, password);

  // Ждем соединения
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //Если подключение успешное, показать IP-адрес в последовательном мониторе
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP-адрес, присвоенный вашему ESP
 
  server.on("/", handleRoot);      // Какую процедуру обрабатывать в корневом каталоге. Это страница дисплея

  server.begin();                  //Запускаем сервер
  Serial.println("HTTP server started");
}
//=============================================== ==============
// ПЕТЛЯ
//=============================================== ==============
void loop(void){
  server.handleClient();          //Обработка запросов клиентов
}

Когда я развертываю это на моем nodemcu esp-12e, я получаю сообщение об ошибке ниже

Я использовал декодер исключений

Exception 3: LoadStoreError: Processor internal physical address or data error during load or store
PC: 0x4000bf64
EXCVADDR: 0x4023d581

Декодер говорит, что эта строка вызывает ошибку

void handleRoot() {
 Serial.println("You called root page");
 String s = MAIN_page; //<<<<<<<<<<<<<<<<<<<<< Ошибка в этой строке
 server.send(200, "text/html", s); 
}

Похоже, он не может прочитать переменную в PROGMEM..

Я заменил эту строку этим кодом и преобразовал ее в строку, и ошибка исчезла.

String MAIN_page = R"=====(
  <!DOCTYPE html>
  <html>
  <head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script>
  $(document).ready(function(){
      $("p").click(function(){
          $(this).hide();
      });
  });
  </script>
  </head>
  <body>
  
  <p>If you click on me, I will disappear.</p>
  <p>Click me away!</p>
  <p>Click me too!</p>
  <br><hr>
  <a href="https://circuits4you.com">circuits4you.com</a>
  </body>
  </html>
)=====";

Есть ли что-то неправильное в коде, который я использую для чтения переменной из флэш-памяти PROGMEM?

, 👍0

Обсуждение

server.send_P(200, "текст/html", MAIN_page);, @Juraj

[В ESP32 все, что объявлено как const, попадет в сегмент родата, который затем перейдет во флэш-память и будет считан непосредственно из него.](https://esp32.com/viewtopic.php?f=13&t=4780) . Не знаю про ESP8266., @Gerben

https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html PS почему тег UNO?, @Gerben


2 ответа


Лучший ответ:

0

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

Если вы хотите использовать PROGMEM, вам нужно использовать const char *, а не String.

,

String s = (const __FlashStringHelper*) MAIN_page; будет работать и использует ОЗУ только временно. может быть полезно заменить некоторые части строки. Но весь подход ОП к этому неверен., @Juraj

Да, я просто следил за всем по этой ссылке. Я просто не уверен, как они могут заставить это работать в конце концов., @Mark Estrada


-1

Смысл использования PROGMEM заключается в сохранении оперативной памяти для других целей. Если у вас есть огромная строка, которая переполнит вашу оперативную память, PROGMEM необходим. Однако, если строка не слишком велика и программа работает нормально, просто используйте String вместо PROGMEM.

,