Atmega32 - Jak na velké menu (200 položek string+bit)?

Začínám dělat prográmek v CodeVision, kde potřebuju poměrně velké menu, cca 200 položek (string+bit), ale nevím jak to naprogramovat, aby mi nepřetékal zásobník (stack 512B), nikde jsem nenašel nějaký příklad, abych viděl jak se to obvykle řeší… Oddělit to jako pole s menu (polozka_menu.jmeno) a tu dát do flash paměti a to bitové pole nechat zvlášť? Teprve s programováním v C a mikročipů začínám a tenhle problém se zásobníkem mně dost zaskočit, hlavně nikde nic, že bych byl jedinej začátečník s takovým problémem?

:arrow_right: administrator: přejmenováno z “Prosím HELP - Jak na menu v Atmega32”

:arrow_right: administrator: příspěvek byl upraven
Identický soubor byl vymazán.
projekt2.c (4.2 KB)

Je to možné, já jsem ještě začátečníka který se pustí do menu s 200 položkami neviděl.
Co to bude? Řízení raketoplánu?

Bude to řízení domu, bude tam pro začátek cca 100 položek ON-OFF, až tohle rozchodím, budu tam postupně přidávat rúzná měření teploty, automatizaci, časovače… atd. Do elektroniky dělám, jen jsem ještě nedělal s mcc a v programování jsem dělal jen kdysi TurboPascal, ale byl to prográmek asi o 10 tis. řádcích. Takže principy jsou mi tak nějak jasné, teď potřebuji rozchodit menu… :slight_smile:

To jednoznačně, tady není o čem přemejšlet. Texty do flash.
Bitové pole(200b) bych asi poskládal do bytového pole (25B) a napsal si funkci, které když dáš jako parametr číslo bitu, tak ho v bytovém poli najde a přečte/zapíše.
Index v poli textů by odpovídal indexu v bitovém poli (indexu předávanému funkci).
Požadovaný řetězec si pak jen skopíruješ do dočasné proměnné v ram a zobrazíš.
Vzhledem k tomu, že to chceš rozšiřovat, asi si v budoucnu nevystačíš jen s položkami on/off, takže bych to rovnou pakoval do struktury.

Fajn a nevíš prosim Tě o nějakém příkladu na netu, kam by se cpalo pole řetězců či struct do flash? Já se o to už nějak chvilku pokoušel a zatím mi to furt něco nebralo, no budu bádat dát. Začal jsem s tím cca před 2 týdny a občas si připadnu jak blbec…

Pozor, ve flash můžeš mít pouze konstantní věci. To řetězce obvykle splňují. Prostě si ho jen vytáhneš a zobrazíš. U té struktury to ovšem nelze. Tam potřebuješ zapisovat, ta musí být v ram. Pro jednoduchost ji můžeš mít globální. Příklad s řetězci ve flash tu určitě najdeš, to tu bylo. Taky je příklad přímo v manuálu GCC. Příklad na strukturu a přístup do ní bych kdyžtak smotnul.

a konstantní tím způsobem, že musí být přímo definované const nebo jen tím, že se do nich v programu nesnažím zapisovat?
jinak, dík, zkusím to předělat takhle a kdyby něco, tak se ozvu :slight_smile:

“avr-libc-user-manual.pdf”, kapitola 5 Data in Program Space. Makro PROGMEM.
Ten manuál otevři, bez něj to do kupy nedáš. Jsou tam i funkce pro čtení (nelze to klasicky) a pro kopii textu do ram.

a ještě jedna asi hloupá otázka, jde nadefinovat pole stringů tedy pole polí jinak než přes struct?

Všechno tam je, i to pole textů. Opět to má takovou zvláštnost, ale je tam i ukázka kódu.

OK, ještě jednou dík.

Co se týká struktury a uložení bitů, vypotil jsem následující kus kódu.
Funkce pro čtení bitů už by neměl být problém stejně tak jako ochrana proti zásahu mimo rozsah bitového pole.
Pokud by sis chtěl i strukturu předávat jako parametr, není problém :wink:
Je to vytvořené ve VS2008, ale mělo by to chodit i v AVR Studiu.

[code]typedef struct // definice struktury
{
unsigned char bitPole[25]; // celkem 200 bit
unsigned char dalsiPromena;
}jmneoStruktury_t;

jmneoStruktury_t promA; // definice globalni promenne typu “jmneoStruktury_t”

void wrBit(unsigned char index, unsigned char bitVal)
{
// zapis bitu do bitoveho pole ve strukture, index = index bitu (od nuly),
// bitVal = zapisovana hodnota (0=0, nenulove cislo = 1)
unsigned char indB = index & 7; // ulozi dolni 3 bity indexu, = index bitu v bytu
if(bitVal) promA.bitPole[index >> 3] |= (unsigned char)(1<<indB);
else promA.bitPole[index >> 3] &= (unsigned char)(~(1<<indB));
}[/code]

Jenom pár poznámek - všecno co je v uvozovkách je automaticky ve flash: byte string]={“ahoj”};
v Codevision můžeš dát cokoliv do paměti taky identifikátorem flash - např.:
char flash stringy [200][10]; - deklarace pole 200 stringů o 10ti znacích
Jinak Codevision zná i typ proměnné bit - má ale určitá omezení- může jich být max 112 (používá se pro ně 14 prac. reistrů - jsou bitově adresovatelné). Musí být deklarované jako globální a nemůžou být členy struktur či unionů ani z nich sestavit pole.

A ještě nakonec : já bych to dělal jinak protože v tvém případě je nějaké zakládání bitového pole nesmysl - protože když to pak budeš posílat - nejspíš přes UART po 485 - stejně to budeš muset převádět na byte.
Já bych ten tvůj bit zakomponoval do MSB (bit 7 bytu) určeného bytu o kterém víš, že nepřesáhne hodnotu 127 ( třeba ASCII znaky). Samozřejmě až v nějakém bufferu, kam si ten string před odesláním vytáhneš z flash.

Ak uz z pamatovych dovodov chces pouzit jednotlivé bity, co takto vyuzit standartne bitove polia? A nielen pre premenne s dlzkou jedneho bitu.

napriklad pre kodovanie casu mozes pouzit zapis
(priklad je z knihy Vaclav Kadlec: Ucime se programovat v jazyce C, jedna z najlepsich kniziek o C, ktore sa mi dostali do ruky. Skoda ze nespravili dotlac)

typedef struct {
   unsigned sec : 5;   // ulozene v bitoch 0 -4
   unsigned min : 6;   // ulozene v bitoch 5 -10
   unsigned hod : 5;   // ulozene v bitoch 11 -15
} CAS;


CAS time;

time.sec = 20;
time.min = 13;
time.hod = 7;

je jasne, ze kludne mozes zapisat


#define ZAP 1
#define VYP 0

typedef struct {
  unsigned rele1 : 1;
  unsigned rele2 : 1;
  unsigned rele3 : 1;
  unsigned rele4 : 1;
  unsigned rele5 : 1;
  unsigned rele6 : 1;
} RELE;

RELE moje_rele;


// a neskor v kode

 moje_rele.rele1 = ZAP;

// ...

 moje_rele.rele1 = VYP;

vobec sa nemusis starat, ci bude pole bitovych zhlukov v jednom alebo v dvoch bajtoch.

obdobne mozes napisat


typedef struct {
  unsigned rele1 : 1;
  unsigned rele2 : 1;
  unsigned rele3 : 1;
  unsigned rele4 : 1;
  unsigned rele5 : 6;
  unsigned cislo6 : 7;
} RELE;

volatile RELE moje_rele;

// ...

moje_rele.cislo6 = 35;

// ...

prekladac to prelozi nasledovne (AVR-GCC)

147:      			moje_rele.rele6 = 35;
+000012BB:   918005ED    LDS       R24,0x05ED     Load direct from data space
+000012BD:   7083        ANDI      R24,0x03       Logical AND with immediate
+000012BE:   688C        ORI       R24,0x8C       Logical OR with immediate
+000012BF:   938005ED    STS       0x05ED,R24     Store direct to data space
+000012C1:   918005EE    LDS       R24,0x05EE     Load direct from data space
+000012C3:   7F8E        ANDI      R24,0xFE       Logical AND with immediate
+000012C4:   938005EE    STS       0x05EE,R24     Store direct to data space

tento sposob programovania je funkcny, len sa moc nepouziva, lebo pamate je vela a casu malo. Z disasembleru je jasne, ze tento sposob je casovo narocnejsi. A to i pri praci s jednym bitom. No nedalo mi ho tu neuviest. Povazujem ho za literarne cistejsi, ako rozne hrozne programatorove maskovania bitov v bajte, pri ktorych interpretacii sa i autor sam vie lahko zamotat. :slight_smile:

No nádhera :slight_smile: Jen je mi divný, že tahle věc(bitové pole) mi zatím neuvízla v budce :open_mouth:.

Teď jsem si všim, že píše v CV.
DAEV: všechny poznámky ohledně “avr-libc-user-manual.pdf” zvesela ignoruj.

“Já bych ten tvůj bit zakomponoval do MSB (bit 7 bytu) určeného bytu o kterém víš, že nepřesáhne hodnotu 127 ( třeba ASCII znaky).”

Doufám, že takovouhle prasárnu nikdo, kdo si to přečte, nikdy nepoužije…

to piityy: suhlasim s Tebou, aj ked s pouzitim bitoveho pola to uz tak moc ako prasarna vyzerat nebude :slight_smile:


#define MAX_VELKOST_POLA 20
#define ZAP 1
#define VYP 0

typedef struct {
  unsigned znak : 7;
  unsigned rele : 1;
} MIX;

MIX pole_mix[MAX_VELKOST_POLA];

//...
 
  pole_mix[2].znak = 'A';
  pole_mix[2].rele = ZAP;

//...

Na builderu píšou, že velikost bit. pole jsou násobky INTu. Dodržuje to GCC, nebo má pro avr výjimku pro omezení plýtvání pamětí? Takovej řetězec z intů by nebyl zrovna optimální :smiley:

Vies k comu vsetkemu ma nutis v tuto pozdnu pracovnu hodinu? :slight_smile: :slight_smile: :slight_smile:

AVR-GCC ako vzdy nesklamalo :slight_smile:

Ak by to aj bol 16b int, nic nebrani dat do bitovej struktury dva znaky a dva bity. A je po plytvaní, akurát ten prístup… Ale zas kľudne do troch bajtov štyri znaky (0-63) vložíš a “malá” kompresia je na svete :slight_smile:
bitove_pole.PNG

Vždyť i Tobě to určitě něco dá :smiley:
Jsou to parádní věcičky, co se s tím dá dělat. Třeba pointer na long přetypovat na bitové pole se 4 8bit prvky a přistupovat k jednotlivým bytům přímo bez logických operací, nebo si rozebrat float na jednotlivý části… :slight_smile: Ať žije C, takový úchylárny jen tak nějaký jazyk nedovolí :slight_smile:

Som rad, ze ta namaha stala za to a som Ta mohol v tuto hodinu potesit. :slight_smile:
C-cko je mocny nastroj.