Projekt časovače: Dny v týdnu, reálný čas,LCD a textové menu

me to menu funguje nejak pofiderne kdyz zmacknu OK a vybere se case 0 a zmacknu UP tak mi to hodi polozku Menu1 pokud v case 0 zmacknu Down tak mi to ukaze polozku Menu 2 :slight_smile: ja jsem upl stary kod nema tam byt ten Define co je nahore uplne knicemu :slight_smile: . No to menu pro me bude orisek a asi tohle nebude uplne vhodne pro moje ucely ze ? asi se podivam po necem po internetu. Vypsal si mi to tu pekne akorat ja to jeste neumim dat dohromady aby to fungovalo :frowning: zatim nektery veci dam uz dohromady sam nektere upravy a vyuziju od jinud a nektere nepoberu vubec :smiley:

Dneska jsem rozjel hodiny zatim jen zkusebne s internim 8MHz krystalem takze presnost nic moc po 1Hodine se predbehnou o 24Sekund. Spinani funguje krasne tak jak sem si predstavoval. Akorat mam ted problem jak udelat spinani na jednotlive dny ?
Premyslel jsem ze bych k nastavovani casu dal i nastaveni Dnu v tydnu, fungovat by to melo tak ze po 24H by se vypsal na LCD pod Cas jeste Den a jednotlive dny bych zakomponoval i k Casum ale jeste nevim jak napriklad ze by se u kazdeho dnu pricital cas nejak takto:
pondeli 0H
utery 24H
streda 48H
ctvrtek 72H
patek 96H
sobota 120H
nedele 144H

Nebo by jste mi poradili nejaky jiny Zpusob co by byl jednodussi ?

Ja sa ospravedlnujem, ze nemam cas prehrabavat sa v zdrojaku a nieco testovat, ale ako som pisal, velmi bezpecny sposob je nasledovny. Hlavne treba oddelit cinnost zobrazenia polozky menu od cinnosti pohybu v menu. Dopredu sa ospravedlnujem za rozsiahlost vykladu, ale nie som pedagog a tak to strucnejsie a mozno aj pochopitelnejsie napisat neviem :slight_smile:

Priklad pohybu vo viacrozmernom menu:

Aby som neuvadzal nejake teoreticke priklady, skusim si vymysliet nieco s konkretnymi hodnotami poloziek.

Nech mam hlavne menu s piatimi polozkami
Nech ma kazda polozka prisudene submenu so styrmi polozkami.
Nech ma kazda polozka submenu prisudene subsubmenu s troma polozkami.

celkovo mam

jedno menu s piatimi polozkami
pat submenu so styrmi polozkami
dvadsat subsubmenu s troma polozkami.

Takze spolu je 26 menu usporiadanych v troch vrstvach. Spolu je tam 85 poloziek.

Pre kazde menu sa bude uchovavat informacia o maximalnom pocte poloziek (index_max). V tomto pripade by sa mohlo zdat, ze naco, ked az 20 subsubmenu z prikladu ma rovnaky pocet poloziek, ale tu niet na com setrit, skutocny zivot prinasa pestrost.
Potom nam uz stacia tri premenne (indexy). Tri z nich informuju na ktorej polozke v menu, submenu a subsubmenu sa aktualne system menu nachadza. Hodnota 0 znamena, ze v danej urovni nie som, ale nachadzam sa o uroven vyssie.

Treba spravit rutinu, ktora testuje stav tlacitok. Tlacitka su pre jednoduchost styry sipka hore, sipka dole, enter a escape. Escape moze byt napriklad sucasne stlacenie oboch sipok.

Aby pohyb v menu vplyvom vyhodnotenia klaves neblblo, vrele odporucam nasledovny trik. Treba vyhodnotit nabeznu hranu stlacenia klavesy a nie jej drzanie. Ta mrcha procesor za 50ms moze aj 10x vyhodnotit stlacenie sipky hore a tak sa predsa s menu neda pracovat. Preto za stlacenie tlacitka povazujte iba nabeznu hranu bez ohladu na to ako dlho je tlacitko stlacene. Za urcitych okolnosti je vhodne vyhodnotit hranu dobeznu (pustenie tlacitka pri kombinacii stlacenia klaves) ale tym si teraz nebudeme komplikovat zivot. Skratka ak chce niekto chodit v menu, musi sipku stlacit a potom ju pustit predtym, ako chce prejst na dalsiu polozku. Trochu inak sa vyhodnocuju klavesy pri nastavovani hodnoty. To preto, aby clovek nezblbol, ked chce zmenit hodnotu napr z 20 na hodnotu 30000. O tom sa vsak teraz nebavime.

Po restarte sa index pre menu nastavi na hodnotu 1 a indexy pre nizsie urovne sa nastavia na nulu. Hodnota premennej informujucej na ktorej urovni v menu som (uroven) sa nastavi na hodnotu 1.

zavola sa funkcia, ktora zobrazi text pre danu polozku. Zaroven nech som si isty, ze v ziadnom menu nebudem mat viac ako 99 poloziek.

Potom sa da zobrazovacia funkcia spravit cez case napriklad takto:

fn_zobraz_menu(void)
{
uint32_t hodnota_menu;
     hodnota_menu = index_menu * 10000 + index_submenu * 100 + index_subsubmenu;

   switch (hodnota_menu) {
      case (010000) : {
           fn_zobraz_prvu_polozku_z_prveho_menu();
           break;
      }
      case (020000) : {
           fn_zobraz_druhu_polozku_z_prveho_menu();
           break;
      }
// ...
      case (020100) : {
           fn_zobraz_prvu_polozku_z_druheho_menu_z_1p1m();
           break;
      }
// ...
      case (030302) : {
           fn_zobraz_druhu_polozku_z_tretieho_menu_z_3p2m_z_1p1m();
           break;
      }
// ...
      default : {
         fn_zobraz_chybu_zbrazenia()
         break;
      }
   }

}

Funkcia pre spracovanie tlacitok.

Stlacenim sipky (vyhodnocuje sa iba nabezna hrana) hore sa odpocita 1 z indexu menu. Ak je index rovny 0, potom sa do premennej nastavi maximalna hodnota z daneho menu.

Stlacenim sipky dole (vyhodnocuje sa iba nabezna hrana) sa pripocita 1 k indexu menu. Ak je hodnota vyssia ako maximalna hodnota, do premennej sa nastavi hodnota 1.

Ak som na niektorej z pozicii a stlaci sa Enter (stale sa vyhodnocuje iba nabezna hrana), premenna uroven sa zvaci o jedna a index pre uroven menu 2 sa nastavi na hodnotu 1. Stlacanim sipiek menim premennu zodpovedajucu polozke na druhej urovni, lebo hodnota v ktorej urovni som sa rovna hodnote 2.

Ak som stlacil Enter na tretej polozke v menu, funkcia fn_zobraz_menu(void) postupne pri stlacani sipky dole zobrazuje obsah poloziek v menu

030100, 030200, 030300, 030400, 030100, 030200, …

Ak na niektorej z poloziek stlacim Enter, premenna uroven sa nastavi na hodnotu 3 a index pre uroven menu 3 sa nastavi na hodnotu 1.

Ak som stlacil Enter na druhej polozke v menu, funkcia fn_zobraz_menu(void) postupne pri stlacani sipky dole zobrazuje obsah poloziek v menu

030201, 030202, 030203, 030201, 030202, 030203, …

Po stlaceni tlacitka Escape sa premenna informujuca o polozke v danej urovni nastavi na nulu a premenna index sa zmeni o 1. Samozrejme, ak u ma hodnotu 1 dalej ju neznizujem. Taku polozku v menu nemam. Alebo ju mat mozem a moze to byt uvodna obrazovka s privitanim a gratulaciami spojenymi s pouzivanim tohto skveleho vyrobku potom ale treba do switch a case doplnit

      case (000000) : {
           fn_zobraz_uvodne_privitanie();
           break;
      }

Doteraz som hovoril o niecom tak nepraktickom ako je nejake chodenie v “skoro” nekonecnom menu. To je v praxi malokedy ziaduce. Casto je treba nastavovat alebo nulovat rozne hodnoty, zobrazovat ich v roznych ciselnych sustavach, rozsahoch, pripadne textovych interpretaciach (napriklad ANO/NIE/NECHCE SA MI).

Z tohto dovodu je potrebme kazdu polozku menu doplnit o nasledovne informacie, co sa ma stat, ak sa na polozke stlaci klavesa Enter

  • polozka je needitovatelne cislo, ak sa stlaci enter, nic nerob

  • polozka je editovatelne cislo hocikym

  • polozka je editovatelna, iba ak je niekde zadane aktivacne heslo (napr. laicke, uzivatelske, servisne a vyrobne menu. Tieto styri urovne sa v praxi osvedcili najviac.)

  • polozka je “vstupom” do submenu (to co som vyssie popisoval)

  • polozka je pri danom nastavenom hesle neviditelna a automaticky sa preskakuje na nasledujucu polozku (ak niekto nezadal heslo s pristupovymi pravami pre prezeranie danej polozky)

  • ak polozka predstavuje zobrazenie nejakeho cisla, tak v akom formate.
    Osvecuju sa nasledovne: 16b integer bez znamienka, so znamienkom, 8b integer bez znamienka, zo znamienkom, 32b integer, char, binarne zobrazenie 8b/16b z 0 a 1, vhodne pre prezeranie napr nastavenia relatok, vyctovy typ, t.j. kazda hodnota cisla zodpoveda nejakemu textu z pola textov. Napr 0 = mrzne, 1 = je chladno, 2 = je sviezo, 3 = je prijemne, 4 = je horuco.

Ak sa zobrazuje polozka menu na LCD display, tak treba v ramci polozky zvlast zadefinovat pomocne texty ako je nazov polozky a napr. fyzikalna jednotka a zvlast treba definovat priestor na cislo (na kolko miest a na kolko miest za desatinnou bodkou).

  • velmi dolezita vec je, ci sa ma cislo zobrazit s desatinnou bodkou a kde ma byt tato v cisle umiestnena. Preco by som mal kvoli tomu, ze potrebujem zisti hodnotu prudu v mA mal aj interne pracovat s mA na tri desatiny. Interne predsa mozem mat prud spracovavany v uA. Staci mi potom na spracovanie 16b premenna a nemusim narabat s matematikou s plavajucou ciarkou. Je jednoduchsie iba spravne formatovat vystupne zobrazenie. K desatinnej ciarke samozrejme patri aj to, na kolko miest sa ma premenna zobrazit za desatinnou ciarkou. Ak je premenna moc vysoka aby sa zmestila do zobrazovacieho priestou, zobrazte tam znaky napr. HH.HH Ak je premenna moc nizka, zobrazte znaky LL.LL alebo tak nejako.

Co je velmi dolezite, VZDY si rozkuskujte sw na samostatne funkcie vykonavajuce jednu logicku a lahko skontrolovatelnu cinnost. Napriklad behanie v ramci menu. To predsa nema vobec nic spolocne so sposobom prezentacie udajov. Tak si to tou castou nekaze. Tento pristup ocenite pri pouzivani menu pre LED alebo pre LCD display. Prezentacia je principialne odlisna, behanie po menu, submenu a subsub… menu rovnaka.

Pekne je doprogramovat ficuru, ze ak sa dlhsie nic nestlaci menu prejde do nejakeho stavu a za kazdy nastaveny cas (napr za tri sekundy) sa presunie na inu polozku. Tak je mozne prezentovat najdolezitejsie udaje v automaticky sa striedajucich sekvenciach. Nie je to ziadna veda. Staci rutine pre pohyb v menu iba “podstrcit” fantomove stlacenie tlacitok.

Zase som sa rozpisal, tak sorry. Niektory tu maju pravdu, ze ked zacnem, neviem kedy skoncit. :slight_smile:

Ak to aspon jednemu na nieco uzitocne bude, tak fajn. Prajem pekny vecer. :slight_smile:

Diky za vycerpavajici odpoved :smiley: tak pokud jsem to dobre pochopil tak jednotlive casti menu by meli mit cisla jak jsou na obrazku: taktokurvanahraj.okamzite.eu/upl … 987304.png

ovladani tlacitek jsem uplne nepobral ale mozna snad by to mohlo fungovat tak ze hodnota_menu bude promenna z ktere ze po stlaceni OK vydeli 100, po stlaceni ESC vynasobi 100, po stlaceni UP pripocte 1, pri stlaceni Down odecte 1, akorat nevim jak zabezpecit aby to nepocitalo do minusu jestli to je vubec mozne nebo na 0 ktera neni obsazena. Potom si teda neumim uplne predstavit ze vyberu v menu polozku 3 a vybere se Submenu 3 asi to nebude uplne fugovat s ESC kdyz tu hodnotu vynasobim bude to pravdepodobne neco jineho :frowning:

ja se o to dat to nejak zkusebne dohromady pokousel ale hazelo to asi 3 chybky ktere jsem nedohakaz opravit jsou videt v programu.

ji k ovladani tlacitek pouzivam spesl programek kterej testuje tlacitka pokud si dobre pamatuju po 8ms po stisknuti se opravdu nacte tlacitko jen jednou po drzeni pomalu nacita :slight_smile: jeste je mam HW osetreny tak stemi by problem byt nebyl

Edit: ted mi doslo ze ty tlacitka UP a DOWN fungovat nebudou protoze to pricita jen jednotky a ne stovky nebo desetitice takze jeste to bude chtit dopsat k sipkam po zmacknuti ESC nebo Enter zmenu radu.

[code]#include <avr/io.h>
#include “lcd.h” // LCD HEADER FILE
#include “tlacitka.h”
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#define F_CPU 8000000UL

char hodnota_menu = 0;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx tlacitka.h xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
ISR (TIMER0_OVF_vect); //casovac

{ //CHYBA …/lcd-menu.c:15:1: error: expected identifier or ‘(’ before ‘{’ token
KEY_Obsluha(); //volani funkce
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx konec tlacitka.h xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
void spinace (void)
{
uint8_t kod_tl;
kod_tl=KEY_Inkey();

if (kod_tl==_KEY_ENTER){
hodnota_menu = hodnota_menu / 100; // po stlaceni ENTER vydel promennou 100
}
if (kod_tl==_KEY_ESC){
hodnota_menu = hodnota_menu * 100; // po stlaceni ESC vynasob promennou 100
}

if (kod_tl==_KEY_UP){ // po stlaceni UP pricti k promenne 1
hodnota_menu++;
}
if (kod_tl==_KEY_DOWN){ //po stlaceni DOWN odecti z promenne 1
hodnota_menu–;
}
}

int main(void){

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx tlacitka.h xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//

DDRD = 0b1111000;  // PD0, PD1, PD2 jako vstupní pin ostatní jako výstupní
PORTD |= (1 << PD0)|(1 << PD1)|(1 << PD2); // zapnutí pull-up rezistoru na PD0, PD1, PD2

//tlacitka.h
TCCR0 |= (1 << CS02); // předělička /256 (8us)
TIMSK |= (1 << TOIE0); // přerušení při přetečení TCNT0
sei(); // povol globální přerušení
//konec tlacitka.h

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx konec tlacitka.h xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//

fn_zobraz_menu(void) { // 3 CHYBY …/lcd-menu.c:61:1: warning: implicit declaration of function ‘fn_zobraz_menu’
//…/lcd-menu.c:61:16: error: expected expression before ‘void’
//…/lcd-menu.c:61:22: error: expected ‘;’ before ‘{’ token
uint32_t hodnota_menu;
hodnota_menu = index_menu * 10000 + index_submenu * 100 + index_subsubmenu;

switch (hodnota_menu) {
case (010000) : {
lcd_puts(Svetlo 1);
break;
}
case (020000) : {
lcd_puts(Svetlo 2);
break;

  } 
   case (030000) : { 
       lcd_puts(Svetlo 3); 
       break; 

  }
   case (040000) : { 
       lcd_puts(Svetlo 4); 
       break; 

  }
   case (050000) : { 
       lcd_puts(Cas svetlo 1); 
       break; 

  }
   case (060000) : { 
       lcd_puts(Cas svetlo 2); 
       break; 

  }
   case (070000) : { 
       lcd_puts(Cas svetlo 3); 
       break; 

  }
   case (110000) : {           //nejde 8 musi byt 8mickova soustava
       lcd_puts(Cas svetlo 4); 
       break; 

  } case (120000) : {         //nejde 9 musi byt 8mickova soustava
       lcd_puts(Cas svetlo 5); 
       break; 

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Submenu 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
}
case (010100) : {
lcd_puts(Zapnout/Vypnout1);
break;

  }
   case (020100) : { 
       lcd_puts(Zapnout/Vypnout2); 
       break; 

  }
   case (030100) : { 
       lcd_puts(Zapnout/Vypnout3); 
       break; 

  }
   case (040100) : { 
       lcd_puts(Zapnout/Vypnout4); 
       break; 

  }
   case (050100) : { 
       lcd_puts(Pondeli); 
       break; 

  }
   case (050200) : { 
       lcd_puts(Utery); 
       break; 

  }
   case (050300) : { 
       lcd_puts(streda); 
       break; 

  }
   case (050400) : { 
       lcd_puts(ctvrtek); 
       break; 

  }
   case (050500) : { 
       lcd_puts(Patek); 
       break; 

  }
   case (050600) : { 
       lcd_puts(Sobota); 
       break; 

  }
   case (050700) : { 
       lcd_puts(Nedele); 
       break; 

  }
  default : { 
     fn_zobraz_chuby_zbrazenia() 
     break; 
  } 

}

}
}[/code]

:arrow_right: administrator: přiloženy externí soubory

No presne takto sa to robit nema. To nasobenie sa robi vylucne v rutine, ktora sa stara o prezentaciu danej obrazovky fn_zobraz() a tato nijako nesmie ovplyvnit premenne s ktorymi pracuje funckia fn_menu(). Skusim to po pamati napisat. Nebude to uplne, ale snad to bude jasne. Ak nie, treba sa ozvat
Nech ma hlavne menu tri polozky, kazda polozka ma submenu po styroch polozkach. Ale principialne kazde menu a submenu moze mat lubovolny pocet poloziek


#define SIPKA_HORE 1
#define SIPKA_DOLE 2
#define ENTER 3
#define ESCAPE 4

#define POCET_UROVNI 2

#define MAX_MENU 3

#define MAX_SUBMENU1 4
#define MAX_SUBMENU2 4
#define MAX_SUBMENU3 4


static uint8_t klavesa, uroven_menu, menu[2];

fn_init(void)
{
   menu[0] = 0;
   menu[1] = 0;
   uroven_menu = 0;
}


fn_menu(void)
{
// toto je priklad ako sa moze vyhodnocovat klavesnica. 
// Netvrdim, ze je idealny.
// Funkcia fn_klavesnica() vyhocuje stav tlacitok.
// Ak to bola sipka hore, tak vrati hodotu 1, pre sipku dole vrati hodnou 2
// pre Enter vrati hodotu 3 a pre Escape vrati hodnotu 4
// Funkcia si po odoslani lubovolnej hodnoty svoj stav vynuluje a bude 
// vracat hodnotu 0 az kym sa neobjavi nejaka nabezna hrana
// Za povsimnutie stoji, ze napr. pre navrat kodu pre ESCAPE vobec 
// nemusi byt fyziky pritomne tlacitko ESCAPE, ale ako ESCAPE moze byt 
// funkciou fn_klavesnica() vyhodnotene napriklad kombinacia stlaceni 
// sipky hore a sipky dole. 
// Ako je kod klavesy vygenerovany funkciu fn_menu ABSOLUTNE nezaujima. 
// Ju zaujima iba navodeny stav a na zaklade neho reaguje.


   klavesa = fn_vrat_hodnotu_klavesy();
   switch  klavesa {
      case SIPKA_HORE : {
          if (uroven_menu == 0) {
             if (menu[0] == 0) menu[0] = MAX_MENU;
             menu[0]--;
          }
          else if (uroven_menu == 1) {
             if (menu[1] == 0) {
                if (menu[0] == 0) menu[1] = MAX_SUBMENU1;
                if (menu[0] == 1) menu[1] = MAX_SUBMENU2;
                if (menu[0] == 2) menu[1] = MAX_SUBMENU3;
             }
             menu[1]--;

          }
          break;  
      }
      case SIPKA_DOLE : {
          if (uroven_menu == 0) {
             menu[0]++;
             if (menu[0] == MAX_MENU) menu[0] = 0;
          }
          else if (uroven_menu == 1) {
             menu[1]++;
             if (menu[0] == 0) {
                if (menu[1] == MAX_SUBMENU1) menu[1] = 0;
             }
             if (menu[0] == 1) {
                if (menu[1] == MAX_SUBMENU2) menu[1] = 0;
             }
             if (menu[0] == 2) {
                if (menu[1] == MAX_SUBMENU3) menu[1] = 0;
             }
          }
          break;  
      }
      case ENTER : {
          uroven_menu++;
          if (uroven_menu == POCET_UROVNI) uroven_menu--;
          menu[uroven_menu] = 0;
          break;  
      }
      case ESCAPE : {
          if (uroven_menu > 0) uroven_menu--;
          menu[uroven_menu + 1] = 0;
          break;  
      }
   }
}

tato funkcia by mala zabezpecit zmenu premennej menu[0] v rozsahu od 0 do 2 a zmenu premennej menu[1] v rozsahu 0 az 3.
ESC prednastavi polozku v submenu na prvu. Stlacanim sipiek menu prechadza z poslednej polozky na prvu a spat.
Pri zobrazeni treba brat v uvahu premenne menu[0] a menu[1] a tak isto aj premennu uroven_menu.

Nieco v zmysle

fn_zobraz(void)
{
uint16_t zobrazenie;

   zobrazenie = uroven_menu * 10000 + menu[0] * 100 + menu[1];

  // v praxi sa vyskytnu dekadicke hodnoty pre hlavne menu:
  // 000000, 000100, 000200,000300, 
  // pre submenu 1 
  // 010100, 010101, 010102, 010103
  // pre submenu 2 
  // 010200, 010201, 010202, 010203
  // a pre submenu 3
  // 010300, 010301, 010302, 010303

   switch (zobrazenie) {
      case 0 : {
          // ...
          break;
      }
      case 100 : {
          // ...
          break;
      }
      case 200 : {
          // ...
          break;
      }
      case 300 : {
          // ...
          break;
      }
// ....
      case 10303 : {
          // ...
          break;
      }
   }
}

Uvedeny kod berte ako nacrt riesenia, nie ako hotove riesenie.

Diky skusim si stim v pondeli poohrat a pak napisu jak to dopadlo zatim jsem dal dohromady casovac dny v tydnu a spusteni v urcyty cas a den :slight_smile: takze uz jen menu a nejak to do nej nahazet :slight_smile:

Tak jsem zkousel to menu podle tebe dat nejak dohromady ale nedari se mi :frowning: porad to hazi nejake chyby kdyz umistim main tak nektere zmizej ale objevej se dalsi :frowning: ocislovani jednotlivych polozek mam snad dobre podle toho tveho noveho navodu viz obrazek. s max itemama jsem si jeste nehral pokousel jsem se to at jen neka zkusebne dohromady :frowning:

taktokurvanahraj.okamzite.eu/upl … 326411.png

kod vypada cca takto:

[code] include <avr/io.h>
#include “lcd.h” // LCD HEADER FILE
#include “tlacitka.h”
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#define F_CPU 8000000UL

#define POCET_UROVNI 2

#define MAX_MENU 3

#define MAX_SUBMENU1 4
#define MAX_SUBMENU2 4
#define MAX_SUBMENU3 4

static uint8_t klavesa, uroven_menu, menu[2];

fn_init(void)
{
menu[0] = 0;
menu[1] = 0;
uroven_menu = 0;
}

fn_menu(void)
{
klavesa = fn_vrat_hodnotu_klavesy();
switch klavesa {
case _KEY_UP : {
if (uroven_menu == 0) {
if (menu[0] == 0) menu[0] = MAX_MENU;
menu[0]–;
}
else if (uroven_menu == 1) {
if (menu[1] == 0) {
if (menu[0] == 0) menu[1] = MAX_SUBMENU1;
if (menu[0] == 1) menu[1] = MAX_SUBMENU2;
if (menu[0] == 2) menu[1] = MAX_SUBMENU3;
}
menu[1]–;

      } 
      break;  
  } 
  case _KEY_DOWN : { 
      if (uroven_menu == 0) { 
         menu[0]++; 
         if (menu[0] == MAX_MENU) menu[0] = 0; 
      } 
      else if (uroven_menu == 1) { 
         menu[1]++; 
         if (menu[0] == 0) { 
            if (menu[1] == MAX_SUBMENU1) menu[1] = 0; 
         } 
         if (menu[0] == 1) { 
            if (menu[1] == MAX_SUBMENU2) menu[1] = 0; 
         } 
         if (menu[0] == 2) { 
            if (menu[1] == MAX_SUBMENU3) menu[1] = 0; 
         } 
      } 
      break;  
  } 
  case _KEY_ENTER : { 
      uroven_menu++; 
      if (uroven_menu == POCET_UROVNI) uroven_menu--; 
      menu[uroven_menu] = 0; 
      break;  
  } 
  case _KEY_ESC : { 
      if (uroven_menu > 0) uroven_menu--; 
      menu[uroven_menu + 1] = 0; 
      break;  
  } 

}
}

fn_zobraz(void){
uint16_t zobrazenie;

zobrazenie = uroven_menu * 10000 + menu[0] * 100 + menu[1];

switch (zobrazenie) {
case (000100) : {
lcd_puts(“Svetlo 1”);
break;
}
case (000200) : {
lcd_puts(“Svetlo 2”);
break;

  } 
   case (000300) : { 
       lcd_puts("Svetlo 3"); 
       break; 

  }
   case (000400) : { 
       lcd_puts("Svetlo 4"); 
       break; 

  }
   case (000500) : { 
       lcd_puts("Cas svetlo 1"); 
       break; 

  }
   case (000600) : { 
       lcd_puts("Cas svetlo 2"); 
       break; 

  }
   case (000700) : { 
       lcd_puts("Cas svetlo 3"); 
       break; 

  }
   case (001100) : { 
       lcd_puts("Cas svetlo 4"); 
       break; 

  } case (001200) : { 
       lcd_puts("Cas svetlo 5"); 
       break; 

  }                      //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
   case (010100) : {  //xxxxxxxxxxxxxxxxxxxxxxxxxxxx submenu 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
       lcd_puts("Zapnout/Vypnout1");   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//
       break; 

  }
   case (010101) : { 
       lcd_puts("Zapnout/Vypnout2"); 
       break; 

  }
   case (010102) : { 
       lcd_puts("Zapnout/Vypnout3"); 
       break; 

  }
   case (010103) : { 
       lcd_puts("Zapnout/Vypnout4"); 
       break; 

  }
   case (010500) : { 
       lcd_puts("Pondeli"); 
       break; 

  }
   case (010501) : { 
       lcd_puts("Utery"); 
       break; 

  }
   case (010502) : { 
       lcd_puts("streda"); 
       break; 

  }
   case (010503) : { 
       lcd_puts("ctvrtek"); 
       break; 

  }
   case (010504) : { 
       lcd_puts("Patek"); 
       break; 

  }
   case (010505) : { 
       lcd_puts("Sobota"); 
       break; 

  }
   case (010506) : { 
       lcd_puts("Nedele"); 
       break; 

  }
  default : { 
     fn_zobraz_chuby_zbrazenia();
     break; 
  } 

}

}
[/code]

Jeste mam jeden problem nastavovani dnu i spinani mi funguje bezchybne akorat pri posunuti o jeden den vzdy ve 00:00:00 mi to misto + jednoho dnu hodi za tu jednu vterinu 4 Dny premejslel jsem hodit tam nejake spozdeni akorat nevim aby to nespozdovalo hodiny Delay sem vyloucil hned ten mi je jasnej :smiley: to je jasna brzda akorat stema ostatnima spozdenima nemam zkusenosti.

Kod vypada cca takto je to jedine jednoduche co me napadlo :

[code]if((hod == 0) && (min == 0) && (sek == 0))
den++;

if(den>6)
den = 0;[/code]

:arrow_right: administrator: přiloženy externí soubory

Velmi v rychlosti, lebo pri vsetkej dobrej voli nemam casopriestor riesit Tvoju ulohu komplexne.

Ak porovnavas cas, kolko krat prejdes cez tu istu splnenu podmienku?
Ako pises, tak posun 4 krat za sekundu sa mi zda byt zalostne malo. Nieco nebude s kodom v state Danskom v poriadku. Pri normalne (ani nie optimalne) napisanom kode, by si mal vbehnut do funkcie tak 10 az 100 krat. Mozno aj vbehnes 704 krat a Tebe sa to javi ako posun o styri dni. To by bol ten lepsi pripad.


uint8_t bol_novy_den = FALSE

// ... niekde v kode

if (((hod == 0) && (min == 0) && (sek == 0)) && (bol_novy_den == FALSE)) {
   bol_novy_den = TRUE;
   den++;

   if(den>6)
   den = 0;
}
// uyplne zbytocne sa vela krat vykona. No a co :-)
If (hod == 1) bol_novy_den = FALSE;

Skratka vzdy testuj, ze dana funkcionalita (nie funkcia) prebehla kedy mala a poznac si to. Nech nebezi niekolko krat v tej istej podmienke zbytocne. To je takzvane testovanie nabeznej hrany udalosti.