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

Chlapci, když už jste mně označili za “prasáka” , můžete sdělit i důvod?
Je prasárnou i to když se MSB používá jako znaménkový bit?

Martin: souhlasíš s pitym, ale pak napíšeš přesně to co jsem měl na mysli- jen trochu jinak. :question: :question: :question: :question:

Znaménko je integrální součástí čísla a je to pro uživatele transparentní. Když už jsme u znamének, tak nejvyšší bit není znaménko, čísla jsou uložena ve dvojkovém doplňku. Že má pro všechna záporná čísla hodnotu 1 a pro nezáporná nulu je pouze vedlejší efekt.
Jenže když si do řekněme charu do nejvyššího bitu (který může být mimochodem využit pro české znaky) dáš nějakou informaci, která s významem proměnné nemá nic společného, tak to je pro mě nepřijatelné. Co se asi stane, když si do toho uvažovaného řetězce zapíše nový? Jeho data uložená do nejvyššího bitu jsou v tahu.
Martinův způsob pomocí bitového pole je z tohoto pohledu bezpečný, protože tomuto jevu brání. Nicméně neřekl bych, že to doporučil k použití.
Že s tím nebudou schopny pracovat stringové funkce je věc další.
Pokud jsi měl na mysli to, co martin, tak se hluboce omlouvám, ale to jsi tam nenapsal a stejně to má zásadní nevýhody pro další práci s daty.

Jiné řešení než samostatné bitové pole(třeba že jako prvek vyšší struktury) je velmi nepřehledné. Máš-li na mysli ještě jiný způsob, který bude čitelný i někomu jinému než pouze jeho tvůrci (a to ještě jen pár dní), rád se nechám poučit.

Ako som uz uviedol vyssie, rozdiel je v tom “trochu jinak” :slight_smile:

V ziadnom pripade by som si ta nedovolil oznacit tak ako si napisal, len suhlasim s piityym, ze ten zapis ktory si naznacil sa moze spravit velmi, ale naozaj velmi prasacky a to je este celkom slusny vyraz :slight_smile:.

A citim sa byt dost kompetentny to dobre posudit, kedze cas od casu nejaku podobnu zhovadilost vyprodukujem aj sam v domneni, ze ved je to len docasne a narychlo a bla bla bla…

Odkonzultovat taky zdrojak s niekym inym alebo ho pochopit cca po pol roku je vela prace naviac s pochopenim, co tym chcel autor povedat a ta prasarna je prave ten zabity cas pripraveny na neskor.

Ale par prikladov:

zapisat

TCCR1A = 18; // velmi velka "prasarna"
TCCR1A = 0x12; // iba o trochu mensia ale stale dost velka, aby som s otazkou kladenou k takemuto kodu nestracal cas
// trochu mensia "prasarna" preto,  lebo hexa kodu znali vidia za cislom nastavene bity. Este rychlo hladat nejake pdf aby som zistil, ktory ze je ktory

alebo

TCCR1A = (1<<COM1B0) | (1<<WGM11); // toto je uz celkom pekne citatelne a prehladnejsie, ak robim s casovacom casto, nemusim ani hladiet do pdf

da sa to vsak zapisat aj takto

// na zaciatku, alebo v nejakom hlavickovom subore zapisem
//(teraz neskumam, ci som to obsahovo zapisal spravne, ide mi o formalnu stranku veci :-) )

#define TOGGLE_COM1B0_PWM_FC_9bit ( (1<<COM1B0)|(1<<WGM11))

// a niekde v kode
TCCR1A = TOGGLE_COM1B0_PWM_FC_9bit;

no a k tomu Tvojmu navrhu (v ktorom som Ta vlastne podrzal, len som uviedol (aspon pre mna) neprasacky zapis) da sa to takto

uint8_t pole_mix[28];
// ...
 pole_mix[20] = 65 + (pole_mix[20] & 128);
// ...

if  (teplota > 80)  pole_mix[20] = pole_mix[20] & 127;
if (teplota < 40)  pole_mix[20] = pole_mix[20] | 128;

alebo aj takto

#define MAX_POLE_MIX 28
#define RELE_ZAP 1
#define RELE_VYP 0

#define INDEX_KURENIE_OBYVACKA 20

#define TEPLOTA_MAX 80
#define TEPLOTA_MIN 40

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

MIX pole_mix[MAX_POLE_MIX];

//...
 
  pole_mix[INDEX_KURENIE_OBYVACKA].znak = 'A';
// ...

if (teplota > TEPLOTA_MAX)  pole_mix[INDEX_KURENIE_OBYVACKA].rele = ZAP';
if (teplota < TEPLOTA_MIN)  pole_mix[INDEX_KURENIE_OBYVACKA].rele = VYP;

Kod by mal byt pisany tak, aby bol co najzrozumitelnejsi a dalo sa v nom lahko orientovat. Ak sa na stabnu kulturu mysli od zaciatku, v priebehu pisania alebo pri modifikacii je daleko menej chyb ako v opacnom pripade.

Z mojej strany je to vyzva hlavne k zaciatocnikom, ktorych vytvory i tu uverejnovane su niekededy neuveritelne :slight_smile:

P.S. No a po precitani posledneho Piityyho prispevku nemozem nic viac ako s nim suhlasit :slight_smile:

Ale jo - vaše (hlavně Martinovy) argumenty beru i když nevím jak jste vyvodili, jaký chci použít zápis (Martin) - Pity to považuje celé za nesmysl.
Uznávám že to byl jen takový okamžitý nápad nedomyšlený do konce.

Koneckonců stejně tu vedeme spíš akademickou debatu o něčem co asi v reálu stejně nikdo nepoužije.Ale taky dobře - zas se dovím něco nového.

DAEW se už ani nehlásí - a my jsme se nechali strhnout jeho návrhem motat dohromady stringy z flash s nějakým bitovým polem, místo toho abysme mu poradili jak to udělat jinak - mimochodem - chce ovládat 200! zařízení ? - to vypadá na nějakou menší fabriku, nebo panelák ne dům jak píše.

Nesuhlasim, uz sme take nieco boli nuteny v ere x51 s malickou pamatou RAM pouzit. Ak je dost Flash a malo RAM, kazda rada ako ziskat bit je dobra :slight_smile:

osobne to povazujem za nezmysel. Ale na to pri pride, az ked to bude mat naprogramovane a bude sa chciet dostat z polozky c 57 na polozku c 123 :slight_smile: :slight_smile: :slight_smile:

Pri prvom (mozno druhom) takom pokuse sa vrhne do programovania PC a spravi si nejake prehladne rozhranie cez PC vratane viacerych sad parametrov pekne prehladne rozmiestnenych na monitore pocitaca. Ale predpokladam, ze o tom bude niektory z buducich dotazov. Vsetkym prajem pekny den :slight_smile:

Zdravím všechny diskutující, pěkně jste to rozjeli :slight_smile: Trošku jsem se v tom pohrabal. Udělal jsem to dle Piityyho, těch zabraných 25b mi přijde jako celkem efektní způsob. Názvy položkám dávat nemusím, jelikož jsou pevně přiřazeny k položce menu. Ten AVR-libc-man… - taky jsem z něj nastudoval i něco co se mi hodí v CV, takže dobrý. Už jsem to v CV tak nějak rozchodil, ale je to velmi hrubá verze, musím to samozřejmě upravit, aby to nebyla prasárna a vyznal jsem se v tom i za chvíli. Ani jsem ještě nezkoumal, zda mi to v tom menu bude dobře chodit, to pak bude jen otázka jen někde ubrat či přidat 1, to zatím neřeším. Teď čekám až mi přijde EvB KIT a budu to moc odzkoušet, jestli to vůbec bude nějak chodit. Docela se těším.
projekt2.c (7.7 KB)
projekt2.c (7.7 KB)

P.S. Jinak 200 zařízení ovládat nechci, cca do 100ky, ale menu aby bylo tak do 200 položek - různé čtení teplot, další nastavování apod. Jinak spolupráci s PC s nějakým vizuálním programem v Delphi to chci časem rozchodit taky, pokud to zvládnu :slight_smile: Mám udělaný k tomu čipu 2 moduly IN/OUT po 96 výstupech/vstupech z 4021 a 4094, po baráku je rozvod světel sice v 230V, ale do každě velké krabice je přiveden 8žilový kabel a tam přidám relé na ovládání světel a časem i dalšího přes tento výtvor…

Nepřemejšlels o sbalení inicializace mcu v mainu do samostatný funkce? Přijde mi to přehlednější, obzvlášť, když ji máš dlouhou na 2x A4 :slight_smile:
U switche v mainu:
než pro kontrolu tlačítek psát čísla jako 1,2,4,8… je přejlednější tam dát:
1<<PC0, 1<<PC1, 1<<PC2 …
nebo použít makro (ovšem nevím, jesli ho má tvůj překladač) _BV(PC0)… Je to to samý jako výše. Jeho definice je totiž #define _BV(bit) (1<<(bit))
A nakonec kdyby sis tlačítka a PINC registr pojmenoval a chtěl to někdy změnit, nebudeš muset procházet celej kód, změníš to na jednom místě.

Za koncem funkce není středník nutný :slight_smile:
Toto

if(PoleStavu.bitPole[index >> 3] &= (unsigned char)(1<<indB)) pom=1; else pom=0; return pom; lze zjednodušeně zapsat jakoif(PoleStavu.bitPole[index >> 3] &= (unsigned char)(1<<indB)) return 1; else return 0;a proměnná “pom” je pak zbytečná.
Funkci stačí být “usigned char”.

Díky za připomínky to pojmenování pinů apod. určitě bude, jak píšu, takhle jsem to jen surově odladil i poznámky tam musím vylepšit. to značení 1,2,4,8 u switche je dobrej nápad to použiju, to jsem v tom nějak neviděl a s tou funkcí a return bez pomocné pom jsem měl problém, furt mi to hlásilo nějakou chybu, asi jsem to měl blbě napsané, přepíšu to dle tebe. Ta inicializace jsem myslel, že musí být definována na tomto místě. Když už jsme u toho ta inicializace mcu a popř. i toho flash pole, nejde nějak napsat v CV do jiného souboru - něco na způsob knihovny?

Tu inicializa tam vpodstatě mít budeš. Jen vytvoříš funkci, do který to vložíš a zavoláš ji na tom místě, kde tu inicialiazci máš teď. Funkčnost bude stejná, jen se ti zpřehlední main :slight_smile:.

OK, vyzkouším to, jinak mi prej domů dnes přišel ten KIT, tak jestli zbyde o víkendu čas, zkusím to tam nacpat. Zatím tuhle starou verzi.

mnozina funkcii v C subore nie je kniznica. Uz som tu na to upozornoval. To pomenovanie sa moze zdat za urcitych okolnosti trefne, ale je skor zavadzajuce.

S kniznicami pracujes (AVRstudio) v

project->configuration options->libraries

kniznice maju priponu *.a a je to predkopilovany kus kodu, takze ziaden zdrojak.

Martin tě asi nepochopil - zmátls ho asi tou knihovnou, ale jinak samozřejmě tu inicializaci můžeš dát jinam - do headeru - třeba s názvem inicializace.h, který ale musíš pak volat : #include “inicializace.h”

pak by to vypadalo asi takto:

[code]
#include “inicializace.h”//obsahuje vše co bylo nad fcí main
void main(void)
{
init_cpu(); //funkce je v inicializace.h - samotná inicializace, jak psal piityy
char OnOff=0;
unsigned char CisMenu=0;
unsigned char CisPolozky=0;
char radek1[17]=(“”);
char radek2[17]=(“”);

lcd_init(16);
lcd_puts(“Test LCD”);
delay_ms(1000);
strcpy(radek1,“Menu”);
//WrBit(‘1’,‘1’);

while (1)
{   
    lcd_gotoxy(0,0);
    lcd_puts(radek1);
    lcd_gotoxy(0,1);
    lcd_puts(radek2);
    if(CisMenu){lcd_gotoxy(16,1);
                lcd_putchar(OnOff);}
   switch (PINC)
    {case 1:if (CisPolozky>0) CisPolozky--; else CisPolozky=MaxPocetPolozek; break;//PINC.0 klávesa Left 
     case 2:if (CisPolozky<MaxPocetPolozek) CisPolozky++; else CisPolozky=0; break;//PINC.1 klávesa Right
     case 4:if (CisMenu==0){CisMenu=CisPolozky+1; CisPolozky=0;} else //jsem v hlavn9m menu a po Enteru skacu do sumenu, ale v submneu ji6 neguji promennou ANONE
                         {if(IsBit(PozMenu)) WrBit(PozMenu,'0'); else WrBit(PozMenu,1); delay_ms(700);}; break; //jsem v submenu a Enterem m2n9m 0-1-0-1..
     case 8:if (CisMenu==0)CisPolozky=0; else //CisMenu=0 tak jsem v hlavnim menu a 0,0
                            {if (CisPolozky>0) CisPolozky=0; else //po escapu skoci do submenu do 0,0 a pak do menu 0,0
                                          {CisPolozky=0; CisMenu=0;}} break;//PINC.3 klávesa ESC     
     //default:
   };  
   
   switch (CisMenu) //vzber polozkz z menu-submenu3 do promene radek2
   {case 0: strcpyf(radek2,menu_table[CisPolozky]); PozMenu=0; break;
    case 1: strcpyf(radek2,submenu1_table[CisPolozky]); PozMenu=CisPolozky+1; break;
    case 2: strcpyf(radek2,submenu2_table[CisPolozky]); PozMenu=CisPolozky+21; break;
    case 3: strcpyf(radek2,submenu3_table[CisPolozky]); PozMenu=CisPolozky+41; break;
    case 4: strcpyf(radek2,submenu4_table[CisPolozky]); PozMenu=CisPolozky+61; break;
    case 5: strcpyf(radek2,submenu5_table[CisPolozky]); PozMenu=CisPolozky+81; break;
    case 6: strcpyf(radek2,submenu6_table[CisPolozky]); PozMenu=CisPolozky+101; break;
    case 7: strcpyf(radek2,submenu7_table[CisPolozky]); PozMenu=CisPolozky+121; break;
    case 8: strcpyf(radek2,submenu8_table[CisPolozky]); PozMenu=CisPolozky+141; break;
    case 9: strcpyf(radek2,submenu9_table[CisPolozky]); PozMenu=CisPolozky+161; break;
    case 10:strcpyf(radek2,submenu0_table[CisPolozky]); PozMenu=CisPolozky+181; break;   
   }
    strcat(radek2," ");
    if(IsBit(PozMenu))OnOff=1; else OnOff=0;
    delay_ms(200);
     


}

}
//definice funkci*******
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) PoleStavu.bitPole[index >> 3] |= (unsigned char)(1<<indB);
else PoleStavu.bitPole[index >> 3] &= (unsigned char)(~(1<<indB));
};
char IsBit(unsigned char index) //zjistovani stavu ve strukture "PoleStavu’
{ char pom;
unsigned char indB = index & 7; // ulozi dolni 3 bity indexu, = index bitu v bytu
if(PoleStavu.bitPole[index >> 3] &= (unsigned char)(1<<indB)) pom=1; else pom=0;
return pom;
}; [/code]
inicializace.h:[code]#include <mega32.h>
#include <delay.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <alcd.h>
typedef struct stav // definice struktury
{ unsigned char bitPole[25]; // celkem 200 bit
unsigned char dalsiPromena;
}stav;
stav PoleStavu; // definice globalni promenne typu “jmneoStruktury_t”

void WrBit(unsigned char index, unsigned char bitVal);
char IsBit(unsigned char index);
//menu ma 20 polozek v 21 je ‘\0’
flash char *menu_table]={“menu1”,“menu2”,“menu3”,“menu4”,“menu5”,“menu6”,“menu7”,“menu8”,“menu9”};
flash char *submenu1_table[21]={“submenuA0”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu2_table[21]={“submenuB1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu3_table[21]={“submenuC1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu4_table[21]={“submenuD1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu5_table[21]={“submenuE1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu6_table[21]={“submenuF1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu7_table[21]={“submenuG1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu8_table[21]={“submenuH1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu9_table[21]={“submenuG1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};
flash char *submenu0_table[21]={“submenuH1”,“submenuA2”,“submenuA3”,“submenuA4”,“submenuA5”,“submenuA6”,“submenuA7”,“submenuA8”,“submenuA9”};

unsigned char PozMenu=0; //submenu1 a polozka1 je 1 atd.
const char MaxPocetPolozek=30;

void init_cpu ()
{
char OnOff=0;
unsigned char CisMenu=0;
unsigned char CisPolozky=0;
char radek1[17]=(“”);
char radek2[17]=(“”);
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x1F;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// USART disabled
UCSRB=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Alphanumeric LCD initialization
// Connections specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTA Bit 0
// RD - PORTA Bit 1
// EN - PORTA Bit 2
// D4 - PORTA Bit 4
// D5 - PORTA Bit 5
// D6 - PORTA Bit 6
// D7 - PORTA Bit 7
// Characters/line: 16
lcd_init(16);
lcd_puts(“Test LCD”);
delay_ms(1000);
strcpy(radek1,“Menu”);
//WrBit(‘1’,‘1’);
}[/code]

Jinak ale v CV můžeš tvořit svoje knihovny - to se ti ale samozřejmě vyplatí, když to použijš víc než jen jednou - což není případ té inicializace - ta bude vždy jiná.

Piityy: tu zdánlivě nesmyslnou inicializaci se zbytečnými příkazy a dlouhými komentáři generuje sám ProjectWizzard v CV včetně těch zbytečných středníků na koci bloků
aaaaa.jpg

Ještě jsem našel chyby, na které tě ale musel upozornit překladač:

lcd_init(16); lcd_puts("Test LCD"); delay_ms(1000); strcpy(radek1,"Menu");
místo fcí lcd_puts a strcpy musíš použít lcd_putsf a strcpyf protože jako parametr zadáváš řetězce z flash.

Díky za výpis jak napsat tu inicializaci.h, určitě to na to předělám a něco i povymažu z toho Wizardu. Ale to lcd_puts by mélo být správné, protože to menu z flash dávám přes to "tvoje " strcpyf do pomocné proměnné “radek2”.

Jde mi o to: lcd_puts(“Test LCD”); - to, že to Test LCD máš v uvozovkách znamená, že jako parametr zadáváš konstanty z flash, proto musíš použít fci pracující s flash -i když je fakt, že CV chybu nehodí.

Opravil jsem to na putsf, ale chodí to i s puts - v reálu, už to mám v Atmega32 nahrané

Tak jsem to trochu zkulturnil a hlavně už to funguje v reálu!! Není to teda ještě plně ošetřené. Takže můžu pokračovat dál, 2*96 I/O převodníků, nějaké kravinky jako pár teploměrů, nějaké chybové hlášení, pokud se zvenčí objeví v bitovém registru nějaká jednička, ne pouhé zapínání a vypínání bitového pole, ale zakomponovat časovačů nebo výběr závislosti na nějakém vstupu-vše přes menu! atd. atd. zkusit rozchodit komunikaci s PC, nejbližší mi je Delphi, tak se ho ještě taky naučit :slight_smile:
projekt2.c (8.17 KB)

ještě, když je tu řeč o šetření s byty - dalších asi 220 jich v RAM ušetříš, když vyhodíš pár * - vysvětlím na: flash char *submenu1_table[21]={"submenuA0","submenuA2","submenuA3","submenuA4","submenuA5","submenuA6","submenuA7","submenuA8","submenuA9"};
překladač ti tu vytvoří 21 ukazatelů (uložených v RAM)na stringy ve flash + ty stringy ve flash. Pro tvoje potřeby jsou ukazatele zbytečné - ve funkci strcpyfse automaticky zadáním jména stringu vytvoří ukazatel na něj a ve tvojem případě vytváříš ukazatel na ukazatel na string