gpt4 book ai didi

c++ - Arduino progmem 读回乱码数据

转载 作者:行者123 更新时间:2023-11-28 05:29:23 25 4
gpt4 key购买 nike

我正在开发一个小型 HTTP 服务器。我正在构建一个路由器,因为可能有很多路由,所以我想将它们放入闪存中,这样我就不必使用宝贵的 SRAM。然而,要么我没有正确理解某些事情,要么发生了一些奇怪的事情,因为我似乎无法从闪存中读回我存储的数据。

我有一个包含函数指针和字符指针的结构。我想将这些结构的数组存储到闪存中并读回它们。但是,通过一个小的调试打印,我可以看到我无法正确读回 char 指针。它将乱码打印到串口。

这是一个小例子。

#include <avr/pgmspace.h>

typedef struct {
void (*func)();
const char *URI;
} Route;

void test1() {
Serial.println("Executed testfunc1");
}

void test2() {
Serial.println("Executed testfunc2");
}

const char route1URI[] PROGMEM = "/route1";
const Route route1 PROGMEM = {
test1,
route1URI
};

const char route2URI[] PROGMEM = "/route2";
const Route route2 PROGMEM = {
test2,
route2URI
};

const Route routingTable[] PROGMEM = {
route1,
route2
};

void (*getRoute(char *URI))() {
Route *r = (Route *)pgm_read_word(routingTable + 0);
char *f = (char *)pgm_read_word(r->URI);

Serial.println(f);

return r->func;
}
void setup() {
Serial.begin(9600);
while (!Serial) { }

Serial.println("started setup");
void (*fn)() = getRoute("sometest");
// will cause errors if called
//fn();
Serial.println("ended setup");
}

void loop() {
// put your main code here, to run repeatedly:

}

最佳答案

PROGMEM 不是那么容易使用。它可以稍微简化一下:

#include <avr/pgmspace.h>

struct Route {
void (*func)();
const char *URI;
};

void test1() {
Serial.println(F("Executed testfunc1")); // if you are using progmem, why not for string literals?
}

void test2() {
Serial.println(F("Executed testfunc2"));
}

const char route1URI[] PROGMEM = "/route1";
const char route2URI[] PROGMEM = "/route2";

const Route routingTable[] PROGMEM = {
{test1,route1URI},
{test2,route2URI}
};

void (*getRoute(char *URI))() {
Route r;
memcpy_P((void*)&r, routingTable, sizeof(r)); // read flash memory into the r space. (can be done by constructor too)

Serial.println((__FlashStringHelper*)r.URI); // it'll use progmem based print
// for comparing use: strcmp_P( URI, r.URI)

return r.func; // r.func is already pointer to the function
}

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

Serial.println("started setup");
void (*fn)() = getRoute("sometest");
// will cause errors if called
//fn();
Serial.print((uint16_t)test1, HEX); Serial.print(' ');
Serial.print((uint16_t)test2, HEX); Serial.print(' ');
Serial.println((uint16_t)fn, HEX);

Serial.println("ended setup");
}

void loop() {
// put your main code here, to run repeatedly:

}

我想 route1route2 可能会导致所有问题,因为它们被用于复制到 routingTable 中。如果像我一样初始化 routingTable 的元素,它会工作得更好。而且 getRoute 也经常坏掉。

无论如何,如果你有 flash 字符串,你也可以使用 String str {(__FlashStringHelper*)r.URI}; 然后使用比较运算符:str == URI:

#include <avr/pgmspace.h>

// get size of array[]
template<typename T, int size> int GetArrLength(T(&)[size]){return size;}

struct Route {
void (*func)();
const char *URI;
};

void test1() {
Serial.println(F("Executed testfunc1")); // if you are using progmem, why not for string literals?
}

void test2() {
Serial.println(F("Executed testfunc2"));
}
void test3() {
Serial.println(F("Executed testfunc3"));
}

const char route1URI[] PROGMEM = "/route1";
const char route2URI[] PROGMEM = "/route2";
const char route3URI[] PROGMEM = "/route3";

const Route routingTable[] PROGMEM = {
{test1,route1URI},
{test2,route2URI},
{test3,route3URI}
};

void (*getRoute(char *URI))() {
for (int8_t i = 0; i < GetArrLength(routingTable); ++i) {
Route r;
memcpy_P((void*)&r, routingTable+i, sizeof(r)); // read flash memory into the r space. (can be done by constructor too)

String uri {(__FlashStringHelper*)r.URI};
if (uri == URI) {
return r.func; // r.func is already pointer to the function
}
}

return nullptr;
}

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

Serial.println("started setup");
void (*fn)() = getRoute("/route3");
// will cause errors if called
//fn();
Serial.print((uint16_t)test1, HEX); Serial.print(' ');
Serial.print((uint16_t)test2, HEX); Serial.print(' ');
Serial.print((uint16_t)test3, HEX); Serial.print(' ');
Serial.println((uint16_t)fn, HEX);

Serial.println("ended setup");
}

关于c++ - Arduino progmem 读回乱码数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39865734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com