[WinAVR] LCD Jednoduché menu

Budu poprvé řešit realizaci jednoduchého menu s Atmegou16 a 16x2 LCD displejem. Nejedná se snad o nic “komplexního”. Defaultně má aplikace na LCD “informativní menu” o stavu…dvojicí tlačítek se pak zobrazují další menu, kde se dá jedna hodnota nastavit další dvojicí tlačítek.
Mám z toho trochu obavy, pač to smrdí strukturami, poly struktur, pointery na funkce atd. :smiley: čemuž jsem se doteď úspěšně vyhýbal.
Zajímalo by mě, jestli existuje nějaká jednoduchá knihovna (myslím, že se něco řešilo tady viewtopic.php?t=2947&postdays=0&postorder=asc&highlight=menu&start=0) nebo to mám raději nasoftit sám (holt všechno je jednou poprvé). Potom bych ocenil rady jak se takový typický problém řeší.

Ano - pointer (tabulka pointeru) na funkce to resi dobre. Knihovny neznam, pisu si sam…

Mohl bys to prosím prosím víc rozepsat? Jak postupovat?

Jen zjednodušně, představ si to jako několik obrazovek mezi kterými se přemisťuješ. V některých se něco něčím mění, některý jen něco ukazují.
Každou obrazovku udělej jako funkci ve který se v nekonečný smyčce řeší zobrazení, změny hodnot a ze který vypadneš pomocí break když budeš chtít skočit do jiný obrazovky. Při opuštění funkce naplníš globální proměnou (ukazatel na funkci) novou hodnotou, podle toho do jaký obrazovky se pokračuje.

V mainu budeš mít něco takovýho:

void (*menu_Screen)(void)=PrvniObrazovka;

while(1)
{
menu_Screen();
}

tady máš takové jednoduché menu pro počet položek, který si zvolíš
každá položka má svou hodnotu a můžeš zadat minimum maximum při zadávání hodnoty

budeš potřebovat čtyři tlačítka - ENT,ESC, +,-

funguje to tak:
tlačítkem ent vstoupíš do menu - zobrazí se ti první položka s hodnotou
tlačítky +a- listuješ v položkách
tlačítkem esc vystoupíš z menu
tlačítkem ent umožníš změnu hodnoty(indikace na displeji)

když zvolíš změnu:
tlačítky +a- nastavuješ hodnotu
tlačítkem esc vystoupíš z nastavování zpět do menu bez uložení hodnoty
tlačítkem ent vystoupíš z nastavování zpět do menu s uložením hodnoty

musíš si ale dosadit svoje funkce pro obsluhu LCD
text položek a pozice na displeji samozřejmě taky dle tvých potřeb

[code]/nadefinuj si vstupy pro tlacitka tl_ent, tl_esc, tl_pus a tl_minus/

#define POCET_POLOZEK 5
typedef struct
{
int value;
int min=0;
int max=100;
}hodnotaStr;

hodnotaStr hodnota[POCET_POLOZEK];
char LcdBuffer[33];

void Main()
{
while(1)
{
if(!tl_ent) Menu();
/*
nejaky dalsi kod



*/
}
}

void Menu()
{
signed char i;
i=0;
MenuText(i);
while(!tl_ent);
while(1)
{
if(!tl_ent)
{
ZmenaHodnoty(i);
}
if(!tl_plus)
{
if(++i==POCET_POLOZEK)i=0;
MenuText(i);
while(!tl_plus);
}
if(!tl_minus)
{
if(–i<0)i=POCET_POLOZEK-1;
MenuText(i);
while(!tl_minus);
}
if(!tl_esc)break;
}
}

void MenuText(char index)
{

switch(index)
{
case 0: sprintf(LcdBuffer,“hodnota 1 %u”,hodnota[index].value);break;
case 1: sprintf(LcdBuffer,“hodnota 2 %u”,hodnota[index].value);break;
case 2: sprintf(LcdBuffer,“hodnota 3 %u”,hodnota[index].value);break;
case 3: sprintf(LcdBuffer,“hodnota 4 %u”,hodnota[index].value);break;
case 4: sprintf(LcdBuffer,“hodnota 5 %u”,hodnota[index].value);break;
}
//tady nastav lcd na 1.radek, 1.znak
Zobraz(LcdBuffer);
}

void ZmenaHodnoty(char index)
{
int tmp;
tmp=hodnota[index].value;
sprintf(LcdBuffer,“nastaveni”);
//tady nastav lcd na 2.radek, 1.znak
Zobraz(LcdBuffer);
while(!tl_ent);
while(1)
{
if(!tl_ent)
{
hodnota[index].value=tmp;
break;
}
if(!tl_plus)
{
if(tmp<hodnota[index].max)++tmp;
sprintf(LcdBuffer,"%u",tmp);
//tady nastav lcd na 1.radek, 12.znak
Zobraz(LcdBuffer);
while(!tl_plus);
}
if(!tl_minus)
{
if(tmp>hodnota[index].min)–tmp;
sprintf(LcdBuffer,"%u",tmp);
//tady nastav lcd na 1.radek, 12.znak
Zobraz(LcdBuffer);
while(!tl_minus);
}
if(!tl_esc)break;
}

}[/code]

lou, Raidus díky moc…lou ten tvůj kód je pro mě pochopitelnější než ty komplexní examply, co jsem vygoogloval, protože je to přesně to, co potřebuju. Nějak si už poradím.
Ještě jednou díky.

Jsem si asi dělal to samé. Spínání 3 výstupů. Je to teda na PIC, ale na ukázku to asi stačí :slight_smile:
Vypadá to asi takto, v závorkách je vždycky vybranej výstup
OUT [1] 2 3
___on off off

[code]#include <htc.h>
#include “lcd.h”
#include <stdio.h>
#define _XTAL_FREQ 8000000

int poc=0;
int a = 0, b = 0, c = 0;
int ok;
char text[16];
int ok_1, ok_2, ok_3;
int stary_stav, aktualni_stav;
int stary_stav_b, aktualni_stav_b;
int stary_stav_c, aktualni_stav_c;

void main(void)
{
ANSEL = 0; // Disable adc
CM1CON0 = 0; //Turn off Comparator 1
CM2CON0 = 0; //Turn off Comparator 2
TRISB = 0; // PORTB all outputs
TRISC = 0;
TRISA = 0b00001111;

lcd_init();
lcd_clear();

while(1)
{
b = PORTA; 
aktualni_stav_b = a & 0b00000001; 
if(!(stary_stav_b == aktualni_stav_b))
{    
	stary_stav_b = aktualni_stav_b; 
 	if(aktualni_stav_b)
	{ 
		poc = poc - 1;  
    }
}
c = PORTA; 
aktualni_stav_c = a & 0b00000010; 
if(!(stary_stav_c == aktualni_stav_c))
{    
	stary_stav_c = aktualni_stav_c; 
 	if(aktualni_stav_c)
	{ 
		poc = poc + 1;  
    }
}


	if(poc == 0)
	{
		lcd_goto(0);
		lcd_puts("Out  [1]  2   3 ");	
	}

	if(poc == 1)
	{
		lcd_goto(0);
		lcd_puts("Out   1  [2]  3 ");	
	}	
	
	if(poc == 2)
	{
		lcd_goto(0);
		lcd_puts("Out   1   2  [3] ");	
	}
	if(poc == 3 || poc == -1)
	{
		poc = 0;
	}

a = PORTA;
aktualni_stav = a & 0b00000100;
if(!(stary_stav == aktualni_stav))
{
stary_stav = aktualni_stav;
if((aktualni_stav) && (poc == 0))
{
if(ok_1)
ok_1 = 0;
else
ok_1 = 1;
}
if((aktualni_stav) && (poc == 1))
{
if(ok_2)
ok_2 = 0;
else
ok_2 = 1;
}
if((aktualni_stav) && (poc == 2))
{
if(ok_3)
ok_3 = 0;
else
ok_3 = 1;
}
}
lcd_goto(64);
lcd_puts(“Stav”);

if(ok_1)
{
lcd_goto(69);
lcd_puts("On ");
}
else
{
lcd_goto(69);
lcd_puts(“Off”);
}
if(ok_2)
{
lcd_goto(73);
lcd_puts("On ");
}
else
{
lcd_goto(73);
lcd_puts(“Off”);
}
if(ok_3)
{
lcd_goto(77);
lcd_puts("On ");
}
else
{
lcd_goto(77);
lcd_puts(“Off”);
}
}}[/code]