Neden PROGMEM ile dizi yerine işaretçiler kullanamıyorum?


11

Şu anda bir projede SRAM tükenmez böylece dize depolama için RAM yerine flash kullanmak için bazı kütüphaneleri değiştiriyorum.

Kütüphanedeki bazı dizeler şu şekilde bildirilir:

const char *testStringA = "ABC";

Bu normalde bu yapılan görmek farklı:

const char testStringB[] = "DEF";

Ancak, bence bu ikisinin beyan beyanında const ve başlatıldığında denk olduğunu düşünüyorum. Her ikisi de kodda iyi çalışıyor.

Bunları flaşa taşımaya çalıştım:

const prog_char *testStringC PROGMEM = "GHI";

Sonra bunun işe yaramadığını gördüm. Basıldığında gobbledegook üretiyordu.

Bununla birlikte, daha olağan modeli takip ederek:

const prog_char testStringD[] PROGMEM = "JKL";

iyi çalışıyor.

Demontajda görebiliyorum:

00000068 <testStringC>:
  68:   04 01                                               ..

0000006a <_ZL11testStringD>:
  6a:   4a 4b 4c 00                                         JKL.

Böylece işaretçiyi temizler ve PROGMEM, dizenin / dizinin başlatılmamasına neden olur.

Bu neden?

Örnek kod:

#include <avr/pgmspace.h>

const int BUFFER_LEN = 20;

const char *testStringA = "ABC";
const char testStringB[] = "DEF";
const prog_char *testStringC PROGMEM = "GHI";
const prog_char testStringD[] PROGMEM = "JKL";

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

void loop()
{
    char buffer[BUFFER_LEN];

    Serial.println(testStringA);
    Serial.println(testStringB);

    strncpy_P(buffer, testStringC, BUFFER_LEN);
    Serial.println(buffer);

    strncpy_P(buffer, testStringD, BUFFER_LEN);
    Serial.println(buffer);

    delay(1000);

}

Yanıtlar:


6

Bu soru, Yığın Taşması soru C'nin cevabına akıllıca cevaplandı : karakter işaretçisi ve dizi arasındaki farklar .

Temel olarak, PROGMEM olarak belirttiğiniz şey,

const prog_char testStringD[] PROGMEM = "JKL";

hem dizi hem de işaret ettiği bellektir, yani dizinin elemanları, her ikisinin de akım kapsamı yığınındadır. Halbuki ile:

const prog_char* testStringC PROGMEM = "GHI";

bellekte başka bir yerde kalabilen ancak bir PROGMEM dizesi olarak bildirilmeyen sabit bir dizeye bir PROGMEM işaretçisi bildirirsiniz.

Bunu test etmeme rağmen , beyan etmeye çalışmalısın:

const prog_char* testStringC PROGMEM = F("GHI");

sivri ipin PROGMEM alanı içinde tahsis edilmesi. Ben sanırım o Arduino en kullanarak çalışıyor olması gerekir F()makro aslında dizi bildiriminde aynı sonucu olması Demirbaş bir sürü kod ekler.

Yorumlarda belirtildiği gibi, küresel bağlamda değilse, PSTR()makro yerine F()makro kullanılabilir.

Daha basit: işaretçi değil, dizi bildirimini kullanın!

Cf diğer cevap olduğunu , __flasheleme üçüncü çözüm ;-)


Tamamen "daha basit daha iyidir" - dizi s çok daha net katılıyorum. Bir şey hemen belli olmadığında her zaman ilgileniyorum.
Cybergibbons

F (), temelde aynı olan FlashStringHelper öğesini döndürür, ancak PSTR () kullanmak iyi çalışır (consts'ı bir işlevin içine getirdiğiniz sürece).
Cybergibbons

Aslında, ilk önce PSTR()makroyu F()önerdim ama göndermeden önce değiştirdim , çünkü cons'larınız Q'nuzda küresel olanlardır, bu yüzden her iki bağlamda da çalışacak olana bağlı kalmayı tercih ettim.
zmo

3

Bu hat ne:

const prog_char *testStringC PROGMEM = "GHI";

dizedeki karakterleri SRAM'a kopyalamak için prolog kodu yazmak ve ardından flash'ta depolanan işaretçiyi bu SRAM konumuna başlatır . İşaretçiyi normal yollarla yüklemeniz ve daha sonra işaretçiyi normalde olduğu gibi kaldırmanız gerekir.

const char *str = pgm_read_word(&testStringC);
Serial.println(str);

Bu hat:

const prog_char testStringD[] PROGMEM = "JKL";

Flash'taki karakter dizisini yaratarak karakterlere beklendiği gibi erişmenizi sağlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.