SDS-C: popis jazyka: Porovnání verzí

 
(Nejsou zobrazeny 2 mezilehlé verze od stejného uživatele.)
Řádek 2: Řádek 2:
 
  Některá zařízení používají FULL-C, pro který máme návody jinde na této WiKi.
 
  Některá zařízení používají FULL-C, pro který máme návody jinde na této WiKi.
  
Jazyk SDS-C má vyhrazené proměnné a příkazy. Přes tyto proměnné a příkazy ovládá váš SDS-C program zařízení SDS.
+
== SDS-C ==
  
 +
SDS-C je programovací jazyk. V lidsky čitelném textu zapisujete to, co chcete aby se stalo.
  
== Funkce ==
+
Sami musíte vědět, co vlastně chcete, no a pak už je to jen o tom, nějak to zapsat do stroje.
  
'''Seznam systémových funkcí (které poskytuje zařízení SDS-C) naleznete [[SDS-C: sdsc sysf|zde]].'''
+
SDS-C je odvozeno od [[FULL-C: intro|FULL-C]], který je odvozen od [http://cs.wikipedia.org/wiki/Jazyk_C jazyka C].
  
Samozřejmě že si můžete definovat své vlastní uživatelské funkce (pokud jejich název nebude kolidovat s vyhrazenými slovy).
+
SDS-C je tedy zjednodušenou variantou FULL-C.
  
  
== #define ==
+
==== Jak to celé funguje? ====
  
Můžete si zpřehlednit program a především centralizovat řadu funkcí, a to pomocí deklarace '''#define'''.
+
Napíšete program. Ten se "přeloží" (compile), z vašeho pohledu to je kontrola správnosti zápisu. Následně se tento přeložený program nahraje (upload) do zařízení. Toto vše se provede v jediné aplikaci pro Windows, kterou si zdarma stáhnete z této WiKi.
  
Zejména pokud máte často se opakující odkaz v celém programu (např. často ovládáte např. třetí relé z mnoha míst v programu), pak je výborné si program zpřehlednit, a zejména, pokud se pak rozhodnete ve zmíněném příkladu přejít z třetího na první relé, mít možnost tuto změnu provést jediným zásahem na jediném místě.
+
Ihned po (úspěšném) nahrání se program automaticky spustí a je neustále dokola prováděn.  
  
 +
Každou 1 msec je proveden jeden celý příkaz (např. celé volání funkce, celý složitý zápis do proměnné, vyhodnocení if, a tak dále) - takže celková rychlost je vysoká - nepleťte si to s např. postupným vykonáváním instrukcí procesoru atd., tady se bavíme o nejvyšsí úrovni. Omezení na 1msec krok lze programově vypnout, viz návod.
 +
 +
Aby jste mohli v SDS-C psát svůj program, musíte znát všechny příkazy, a (systémové) proměnné. Detaily naleznete na tomto webu.
 +
 +
Ideální pro začátek je vzít již hotový funkční program, a ten si začít postupně upravovat. Každou úpravu co provedete si hned vyzkoušíte, a hned vám bude zřejmé, co který příkaz atd. dělá.
 +
 +
 +
== První program - jak na to ==
 +
 +
Potřebujete speciální kombinovaný editor/simulátor/uploader, ke stažení je z těchto [[Firmware|stránek]].
 +
 +
[[Soubor:Sds_english_sdsc_intro.jpg]]
 +
 +
V tomto programu zapíšete zdrojový kód svého SDS-C programu, můžete (ale nemusíte) jej ověřit odkrokováním v simulátoru, a nahrajete jej odsud přímo do výrobku SDS, kde se program zapíše do paměti a začne se ihned neustále dokola vykonávat.
 +
 +
V záložce "Source code" je textový editor - do něj budete zapisovat program. Až budete se zápisem hotovi, zmáčknete tlačítko "Compile". Otevře se okno s hlášením, zda-li je program v pořádku nebo zda-li je v něm chyba.
 +
 +
Pokud je program v pořádku, máte dvě možnosti (navzájem se nevylučují).
 +
 +
Můžete si program spustit v simulátoru "Debugger", ručně v něm krokovat nebo si vložit breakpointy (doubleclick nad místem kam se má breakpoint vložit). Rychlost automatického krokování lze nastavit posuvníkem na horní liště. Součástí simulátoru je i další okno, ve kterém máte možnost ovládat hardware, a sledovat výstupy vašeho programu.
 +
 +
Druhá funkce je nahrání programo do zařízení, karta "UPLOAD TO DEVICE". Jakmile jste se svým programem spokojeni, tak odsud jej nahrajete do hardware - v kartě jsou dvě tlačítka, první ověří komunikaci a velikost volné paměti, druhé pak provede samotné nahrání.
 +
 +
 +
==== Jak se píše SDS-C program ====
 +
 +
Každý SDS-C program musí mít funkci '''main'''.
 +
 +
To co je uvnitř této funkce, je provedeno po spuštění programu.
 +
 +
Všechny další vámi definované funkce se volají teprve odsud.
 +
 +
Minimální program vypadá takto:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
#define RELE sys[231]
+
main
 +
{
 +
 
 +
  // tady je program zapsaný ve funkci main
 +
 
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Takto teď kdekoliv v programu, kam napíšete '''RELE''' (pozn. kromě ohraničených textů a komentářů), bude automaticky vloženo '''sys[231]''' (nebo cokoli jiného co si pak sami definujete).
 
  
Příklad:
+
Aby to něco udělalo, dáme tam volání jedné systémové funkce, '''echo''', což provede výpis textu na konzoli (viz webové rozhraní).
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
RELE = 1; //zapne rele
+
main
 +
{
 +
 
 +
  echo('Ahoj z main!');
 +
 
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Všechny názvy musí být kompletně velkými písmeny.
+
Když se provedou všechny příkazy, které jsou v '''main''' zapsány, stane se to, že je '''main''' automaticky spuštěno zase znovu - takže v důsledku je to nekonečná smyčka (dokud není program zastaven uživatelem, například).
  
Pozor - lze použít jen jednu úroveň (tzn. nelze vnořit define do define).
+
Pokud je potřeba provést nějakou činnost, ale jen jednou po resetu programu, použije se vyhrazená funkce '''init'''. Příklad se pak rozroste následovně:
  
 +
<syntaxhighlight lang="c">
 +
init
 +
{
 +
  echo('Ahoj z init!');
 +
}
  
== Vyhrazené proměnné SDS-C ==
+
main
 +
{
 +
  echo('Ahoj z main!');
 +
}
 +
</syntaxhighlight>
  
Vyhrazené proměnné v SDS-C jsou tzv. ''systémové proměnné''. Jejich obsah odpovídá aktuálnímu fyzickému stavu systému, tj. HW zařízení.
+
Samozřejmě, pokud '''init''' nepotřebujeme, nemusíme ho tam zapisovat.
Stejně tak lze pomocí specifických systémových proměnných zasahovat i do konfigurace, měnit textové údaje ve webovém rozhraní atd.
 
  
'''Kompletní seznam naleznete [[SDS-C: sdsc_sysp|zde]].'''
+
Pokročíme dále. Program má možnost pracovat se všemi vstupy a výstupy, které dané zařízení poskytuje. Následující program zapne první relé:
  
 +
<syntaxhighlight lang="c">
 +
main
 +
{
 +
  sys[231] = 1;
 +
}
 +
</syntaxhighlight>
  
== Uživatelské proměnné ==
+
Kde se vzalo to [[SDS-C: sdsc_sysp| sys[]]] ? To jsou pevně definované, tzv. systémové proměnné. Tyto proměnné jsou přímou vazbou na hardware.
  
Programátor si může v SDS-C definovat své vlastní proměnné.
+
Pomocí tzv. proměnných lze uchovávat hodnoty v paměti. Proměnná má nějaký název, ten si vymyslíte vy. Definuje se pomocí klíčového slova '''var'''. V příkladu si definujeme proměnnou ''pr'', a zapíšeme do ní hodnotu 1.
  
Použije se pro tento účel klíčové slovo ''var''. Toto je jediný možný definiční typ pro proměnnou, akceptovaný v SDS-C.
+
<syntaxhighlight lang="c">
 +
var pr;
 +
 
 +
main
 +
{
 +
  pr = 1;
 +
}
 +
</syntaxhighlight>
 +
 
 +
S proměnnou lze různě pracovat, a lze ji předat i jako parametr do funkce. Další příklad to ukazuje:
  
Příklad:
 
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
var pocet;
+
var pr;
 +
 
 +
main
 +
{
 +
  pr = 1;
 +
 
 +
  pr = pr + 10;
 +
 
 +
  echo('Hodnota promenne je ',pr);
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Definuje proměnnou ''pocet'', typ 32-bitů signed (to znamená: 1 bit pro znaménko a 31 bitů pro číslo).
+
Co se stane: nejprve definujeme ''pr'', od místa kde je ''pr'' definována pomocí '''var''' s tím můžeme pracovat. Pak do ''pr'' vložíme pevnou hodnotu (v příkaldu je to číslo 1). Pak k hodnotě která je v tu chvíli v ''pr'', přičteme číslo 10 (tj.: ''pr = pr + 10;'').
  
V této verzi je možné používat pouze 32-bit/signed. Proto se do programu nepíše typ proměnné, ale jen ''var'' a zvolený název.
+
Nakonec se zavolá funkce '''echo''' (výpis textu na konzoli) a vypíše se text: ''Hodnota promenne je 11''.
 +
 
 +
 
 +
Další příklad ukazuje, jak se do proměnné dá zapsat hodnota z hardware (tj. '''sys[]'''). Konkrétně se (podle tabulky) jedná o teplotní údaj z prvního externího teplotního čidla. Tento údaj je ale potřeba upravit (protože je posunut o dvě nuly), a nakonec je vypsán na konzoli.
  
Co a jak když chcete pracovat s desetinnými čísly? Snadná pomoc:
 
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
var a,b,x, celaCast, desetinnaCast, preciznost;
+
var pr;
+
 
a = 5;
+
main
b = 2;
+
{
 +
  pr = sys[310]; // prevezmeme teplotu z cidla 1 v tomto okamziku
  
// ted chci x = a/b, tj x=5/2, tj. x=2.5
+
  pr = pr / 100;  // vydelime 100, takze posuneme desetinnou tecku o dve mista doleva
// ale mam jen celociselne deleni...
 
  
preciznost = 10; // nebo 100, 1000, ... jak moc je potreba
+
  echo('Teplota je ',pr,' stupnu Celsia.');
 +
}
 +
</syntaxhighlight>
  
x = (a * preciznost) / b;  // posuneme tedy desetinnou carku nasobenim
 
  
// x je ted 25, takze
+
== Další vlastní funkce ==
  
celaCast = x / preciznost;
+
Nemusíte se snažit vše vecpat do '''main'''. Často opakované kusy programu lze dát "bokem" do jiné funkce, a pak stačí jen tuto funkci "zavolat" a program v této funkci se na místě zavolání provede.
desetinnaCast = x % preciznost;
 
  
// vysledek -> celaCast = 2, desetinnaCast = 5 
+
Příklad zápisu vlastní funkce (samozřejmě můžete mít svých funkcí více):
 +
<syntaxhighlight lang="c">
 +
moje
 +
{
 +
  echo('Pozdrav z moji funkce.');
 +
}
  
echo('vysledek = ',celaCast,'.',desetinnaCast);  //-> vypise: vysledek = 2.5
+
main
 +
{
 +
  echo('Pozdrav z main.');
 +
 
 +
  moje();  // takto se zavola moje funkce
 +
 
 +
   moje();  // ... muzu volat kolikrat chci, a to i odkudkoliv
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
== Texty ==
+
== Chytřejší SDS-C program ==
 +
 
 +
Důležitou součástí programu je schopnost rozhodovat na základě různých stavů a vstupů. Veškeré rozhodování se provádí zápisem konstrukce '''if''' (česky: pokud).
 +
 
 +
Kostra zápisu:
 +
<syntaxhighlight lang="c"> if (PODMÍNKA) {UDĚLEJ KDYŽ ANO} else {UDĚLEJ KDYŽ NE}; </syntaxhighlight>
 +
Nebo druhá možnost (zkrácená):
 +
<syntaxhighlight lang="c"> if (PODMÍNKA) {UDĚLEJ KDYŽ ANO}; </syntaxhighlight>
 +
 
 +
Důležité je znát, co se má psát na místo '''PODMÍNKA''' a co lze zapsat na místa '''UDĚLEJ KDYŽ ANO/NE'''.
  
Jazyk SDS-C umožňuje pracovat pouze s pevně definovanými, konstantními (tj. dále neměnnými) texty.  
+
Podmínkou je samozřejmě všechno, podle čeho se chceme rozhodovat. Pokud budeme např. měřit teplotu, tak budeme např. chtít něco provést, když teplota bude větší než stanovený limit. Tento test se právě zapíše na místo označené jako '''PODMÍNKA'''.
  
Jazyk SDS-C má tedy z hlediska práce s texty řadu omezení, vůči jazyku FULL-C.
+
Zbylé dvě místa, označená jako "UDĚLEJ KDYŽ ANO/NE", jsou zápisem činnosti, která se provede po vyhodnocení podmínky.  
  
Všechny texty (jako konstanty) si definuje programátor. Definice lze provést kdekoliv.
+
Příkladný program:
  
Např.
 
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
smtp_send('joe@foo.bar', 'subject', 'Další definovaný text, hodnota i=', i, ' a další text...');
+
ano
 +
{
 +
  echo('Funkce ano.');
 +
}
 +
 
 +
ne
 +
{
 +
  echo('Funkce ne.');
 +
}
 +
 
 +
main
 +
{
 +
  if (sys[310] > 1050) ano() else ne();
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Texty lze předat pouze jako parametry funkcí a do některých systémových proměnných, a dále už nikam jinam.
+
Co zde můžete vidět: definici dvou funkcí a ještě základní funkce ''main'', dále jeden '''if'''. Tento '''if''' testuje aktuální hodnotu z hardware, která je uložena v '''sys[310]''' (což je teplota z prvního čidla), a pokud je tato teplota větší než 10.5°C, tak se zavolá funkce '''ano''', v opačném případě se zavolá funkce '''ne'''.
  
 +
Všimněte si, že volání funkce v '''if''' je specifické, a to přidáním '''()''' na konec názvu volané funkce.
  
== Vyhrazené klíčové slova ==
+
V rámci testu lze spojit více podmínek dohromady. Například (vymyšleno pro zajímavost):
 +
<syntaxhighlight lang="c">
 +
if (pr >= 102 && ((i % 2 == 0) || (sys[310] <= 0))) neco();
 +
</syntaxhighlight>
  
V jazyku SDS-C je řada vyhrazených slov, které mají pevně přiřazenou funkci. Jejich znalost je pro
+
Konkrétní obsah testu si připravíte vy dle svých potřeb.
programovaní v SDS-C naprosto '''nezbytná'''.
 
  
 +
''LZE POUŽÍT OD 14.5.2011:''
  
* '''return'''
+
Lze si i zpřehlednit zápis:
 +
<syntaxhighlight lang="c">
 +
main
 +
{
 +
  if (nejaky_test)  { a = a + 1; b = b + 1; }; //pokud nejaky_test je ANO, pak se provede VSE co je zapsáno v { a }
 +
}
 +
</syntaxhighlight>
  
Umožňuje předčasný návrat ze zavolané funkce.
+
Lze použít i '''else''':
Příklad:
 
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
if (i % j == 0) return;
+
ano
 +
{
 +
  a = a + 1; b = b + 1;
 +
}
 +
 
 +
main
 +
{
 +
  if (nejaky_test) { a = a + 1; echo(' ano !'); } else { a = a - 1; echo (' ne ! '); };
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Pokud zavoláte '''return''' přímo v ''main'', pak je ''main'' předčasně ukončen a vzápětí znovu spuštěn od svého začátku.
+
Vyzkoušejte si to.
  
 +
Pozor! Pokud za IF použijete podblok, tj. '''{''' '''}''' , pak musíte do podbloku umístit jak kód před '''else''', tak i za '''else'''.
  
* '''label'''
 
  
Definuje bod v programu (návěstí), kam je možné odkudkoliv odjinud skočit. V současné verzi SDS-C není vyžadován (byl to původně vyžadováno v prvních starých verzích).
+
== Jak dělat smyčky ==
  
Využívá se např. pro vytváření smyček.
+
V jazyce C se smyčky dají zapsat řadou způsobů. Nejznámější je funkce '''for''', kterou ale v této verzi SDS-C '''nemáme''' (ta je až ve FULL-C).
  
Definice cílového bodu (tj. kam lze skočit):
+
Proto je potřeba si poradit - a je to snadné.
  
lze použít dvě varianty:
+
Následující příklad ukazuje, jak udělat jednoduchou smyčku v SDS-C:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
  -název-:
+
main
</syntaxhighlight>
+
{
<syntaxhighlight lang="c">
+
  var i;
label -název-:
+
 
 +
  i = 0; //nastavíme výchozí hodnotu
 +
 
 +
label smycka:
 +
 
 +
  echo('hodnota i je ', i);
 +
 
 +
  i++; //zvýšit i o 1
 +
 
 +
  //test: vše hotovo?
 +
  if (i < 10) goto smycka;
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Všimněte si, že si můžete zvýšit přehlednost programu tím, že před samotný název návěstí dáte slovo '''label'''. Pak lze v editoru snadněji najít pohledem místa, kam se bude skákat (pozn. jiný význam to prakticky nemá).
+
Tento program postupně na konzoli vypíše čísla 0, 1, 2, 3, 4, 5, 6, 7, 8 a nakonec 9 .
  
Skok se provede takto:
+
Poznámka: tuto smyčku by jste v původím jazyce C zapsali následovně:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
goto -název-;
+
// příklad pro jazyk FULL-C (pozor ne pro SDS-C !)
 +
// ve výsledku odpovídá předchozímu ukázkovému programu
 +
 +
int i;
 +
for (i = 0; i < 10; i++) { printf("hodnota i je %d", i); };
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Pozor! Definice bodu návěstí lze provést pouze '''nad''' všemi skoky (goto) na konkrétní návěst.
 
Pokud bude tedy skok (goto) nad místem definice cíle (label), bude to bráno jako chyba.
 
  
 +
'''Příklad: nekonečná smyčka'''
  
* '''if'''
+
Nekonečná smyčka je velmi užitečná. Ze dvou důvodů: trvalé zablokování činnosti programu (užitečné při zkoušení a podobně), a dále jako hlavní smyčka programu.
  
Pomocí ''if'' se provádí větvení programu dle aktuálního stavu.
+
Příklad nekonečné "zásekové" smyčky:
Provede se test zadané podmínky, a na základě výsledku (pravda/nepravda) se provede příslušná zadaná akce.
+
<syntaxhighlight lang="c">
Lze provést pouze jediné volání funkce nebo jediný skok (label), přičemž pro pravdivý výsledek lze definovat takovouto akci a stejně tak i pro nepravdivý výsledek.
+
main
 +
{
 +
  //...
  
'''POZOR''' Vždy jsou vykonány kompletně '''všechny''' testované vstupy v podmínce '''if''' - ať pak nejste překvapeni !
+
label smycka:
 +
  //hned skocim zpatky na label smycka, takze to zde zustane natrvalo
 +
  goto smycka;
  
Příklad:
+
  //sem uz se program nikdy nedostane !
<syntaxhighlight lang="c">
+
}
if (sys[24] < 23) posliSMS();
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
Samozřejmě použití klíčového slova '''label''' není nutné (může být použito pro zpřehlednění textu), takže následující příklad je správně:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
if (i % 10 == 0) goto neni10 else jinaFunkce();   //pokud i je nasobek 10, pak se skoci na label neni10, jinak se vola jinaFunkce
+
main
 +
{
 +
  //...
 +
 
 +
smycka:
 +
   //hned skocim zpatky na label smycka, takze to zde zustane natrvalo
 +
  goto smycka;
 +
 
 +
  //sem uz se program nikdy nedostane !
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
Příklad hlavní smyčky programu:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
if (q & 2 && z != u) neco() else necoJineho();
+
main
 +
{
 +
  //...
 +
 
 +
label smycka:
 +
 
 +
  //nejaky kus programu, kde je potreba neco neustale testovat
 +
 +
  if (sys[151 == 0) udelej_neco();
 +
 
 +
  //atd...
 +
 
 +
  goto smycka;
 +
 
 +
  //sem uz se program nikdy nedostane !
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
'''Příklad: čekací smyčka'''
 +
 +
Někdy je potřeba čekat nějakou pevně stanovenou dobu, než se provede nějaká akce, atd. Např. při postupném zapínání relátek (které mohou připojovat velké zátěže, a nelze je sepnout najednout, příkladů z praxe je celá řada).
 +
 +
Následující příklad sepne RELE1, pak počká 2 sekundy a pak sepne RELE2:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
if (teplota < 10 && chci_alarm != 0) hlas_alarm() else return; //priklad vyuziti return
+
main
 +
{
 +
 +
  sys[231] = 1;  //zapni RELE 1
 +
 
 +
  sys[64] = 2; //nastav odpočítávač na 2 sekundy (od tohoto okamžiku, kdy do sys[64] zapíšeme hodnotu 2)
 +
label cekam:
 +
  if (sys[64] != 0) goto cekam; //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"
 +
 
 +
  sys[232] = 1; //zapni RELE 2
 +
 
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Takže viz poslední příklad - i když bude platit, že teplota < 10, vždy bude otestován i chci_alarm != 0, a až pak na základě všech výsledků se rozhodne, který příkaz se provede.  
+
Samozřejmě, nemusíte hned používat smyčku a sekundový odpočítávač sys[64], můžete totiž použít funkci '''wait'''. Ale umožní vám funkce '''wait''' vložit svůj další kus programu do čekací smyčky a tento kus programu provádět, zatímco čekáte? Ne.
 +
 
 +
Často je potřeba při čekání provádět další činnost. Vezměme si opět předchozí příklad, ale doplňme ho o potřebu měřit teplotu (z teplotního čidla) a pokud teplota klesne pod 30°C, tak zavolat nějakou funkci. Jde o příklad, takže to bude stačit.
  
Jak pomocí '''if''' pracovat s bloky kódu, když nechcete volat funkce:
 
  
 +
Následující příklad sepne RELE1, pak počká 2 sekundy a pak sepne RELE2, ale současně během čekání hlídá teplotu:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
if (i != 0)
+
main
 
{
 
{
 
   
 
   
  echo(' i neni nula ');
+
  sys[231] = 1;  //zapni RELE 1
  // atd...
+
 
+
  sys[64] = 2; //nastav odpočítávač na 2 sekundy
} else
+
label cekam:
 +
 
 +
  //klesla teplota z cidla 1. pod 30.00°C ? Pokud ano, zavolej "nejaka_funkce"
 +
  if (sys[310] < 3000) nejaka_funkce();
 +
 
 +
  //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"
 +
  if (sys[64] != 0) goto cekam;  
 +
 
 +
  sys[232] = 1; //zapni RELE 2
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
Můžete si program i zpřehlednit, za použití '''#define''' :
 +
<syntaxhighlight lang="c">
 +
#define RELE1 sys[231]
 +
#define RELE2 sys[232]
 +
#define TEPLOTA1 sys[310]
 +
#define ODPOCET_SEKUND sys[64]
 
   
 
   
 +
main
 
{
 
{
 
   
 
   
  echo(' i je nula ');
+
  RELE1 = 1; //zapni RELE 1
+
 
 +
  ODPOCET_SEKUND = 2; //nastav odpočítávač na 2 sekundy
 +
label cekam:
 +
 
 +
  //klesla teplota z cidla 1. pod 30.00°C ? Pokud ano, zavolej "nejaka_funkce"
 +
  if (TEPLOTA1 < 3000) nejaka_funkce();
 +
 
 +
  //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"
 +
  if (ODPOCET_SEKUND != 0) goto cekam;  
 +
 
 +
  RELE1 = 1; //zapni RELE 2
 +
 
 
}
 
}
 
// dalsi kod...
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
* '''var'''
+
== První užitečný SDS-C program ==
  
Pomocí ''var'' se definují uživatelské proměnné.
+
Ukažme si na následujícím příkladu první užitečnější program.  
  
 +
Tento program měří teplotu z prvního teplotního čidla, a při překročení teploty odešle email s poplachovou zprávou. Email je poslán jen jednou, pouze v okamžiku, kdy dojde k překročení stanovené teploty. Jakmile se teplota vrátí pod poplachový limit, je program znovu připraven poslat další email, při novém překročení limitu.
  
== Funkce v SDS-C ==
+
Co budeme potřebovat, aby se takový program dal sestavit:
 +
* promennou s urcenym limitem
 +
* promennou s hodnotou hystere (hysterezi je nezbytne pouzit v obecne kazde uloze s merenim teploty, zkuste to bez a uvidite proc)
 +
* hlavní programovou smyčku, ve které se bude neustále porovnávat změřené teplota s určeným limitem
 +
* funkci pro odesílání emailu
 +
* proměnnou, ve které bude uložena informace o tom, že byl email odeslán - to proto, aby byl odeslán vždy jen jeden email při překročení limitu (pokud by se toto vynechalo, byly by emaily odesílány nepřetržitě po celou dobu, kdy je teplota překročena, a to jistě nikdo nechce)
  
Funkce jsou ohraničené části programu, které mají svůj specifický název, zadaný programátorem.
+
<syntaxhighlight lang="c">
 +
var limit, hystereze;
 +
var email_odeslan;
  
Všechny tyto funkce nevracejí hodnotu, lze je pouze zavolat.
+
teplota_ok
Po svém provedení pokračuje běh programu v místě, odkud byla funkce zavolána.
+
{
 +
  //volano po celou dobu, kdy je teplota pod limitem (do uvahy je brana i hystereze)
  
Využití funkcí - nejčastěji pro opakované kusy programu, aby se nemuselo plýtvat s volným místem pro zápis programu.
+
  //povolime odeslani emailu pri pristim prekroceni limitu
 +
  email_odeslan = 0;
  
Příklad definice funkce ''test'' a jejího zavolání z jiné funkce ''funkceX'':
+
  //sem se daji doplnit dalsi funkce, napr. ovladani rele (zapnout topeni = zvysovat teplotu)
<syntaxhighlight lang="c">
+
}
test
+
 
 +
hlasim_prekroceno
 
{
 
{
   i += 10; //nejaky obsah funkce...
+
   //volano po celou dobu, kdy je teplota nad limitem
 +
 
 +
  //pokud jsem uz odeslal email, nebudu ho posilat znovu
 +
  if (email_odeslan == 0)
 +
  {
 +
 
 +
    //jeste jsem email neodeslal, takze...
 +
    smtp_send('joe@foo.bar','Teplotni poplach', 'Teplota prvního čidla překročila limit!');
 +
 
 +
    //a zapamatuji si odeslani
 +
    email_odeslan = 1;
 +
 
 +
  }
 +
 
 +
  //sem se daji doplnit dalsi funkce, napr. ovladani rele (vypnout topeni = snizovat teplotu)
 +
  sys[RELE] = 1;
 
}
 
}
  
funkceX
+
main
{
+
{
 +
 
 +
  //nastavime limit teploty (st.C)
 +
  limit = 25; 
 +
 
 +
  //nastavime hodnotu hystereze pro urceni navratu (st.C)
 +
  hystereze = 2;
 +
 
 +
  //vychozi stav
 +
  email_odeslan = 0;
 +
 
 +
  //pockame 10 sekund, az nabehne cely system
 +
  wait(10000); 
 +
 
 +
 
 +
  //------------------------------------------------------------ 
 +
 
 +
  //hlavni smycka, ve ktere se vykonava proces
 +
label smycka_rizeni: 
 +
 +
 
 +
  //teplota je brana z cidla
 +
  teplota = (sys[310] / 100);  //musime delit 100 aby to byly cele stupne Celsia 
  
    //zavolame test()
+
  //podle aktualni teploty se rozhodnu 
    test();
+
  if (teplota < limit - hystereze) teplota_ok(); 
 +
  if (teplota > limit) hlasim_prekroceno();
  
    //...
+
  //a porad dokola 
 +
  goto smycka_rizeni; 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Všimněte si rozdílu definice funkce v SDS-C, ve srovnání s FULL-C. Pro SDS-C funkce nevrací hodnoty a nepřebírá parametry.
+
Toto už je pěkný program na hraní, dá se kompletně odzkoušet v debuggeru. Můžete se pak pokusit sami doplnit další funkce, např. již naznačené ovládání relé (např. ovládající nějaké topení, které by ovlivňovalo teplotní čidlo), atd.
 +
 
 +
Dalším rozšířením programu může být dálkové ovládání. Využije se funkce zařízení SDS, které umožňuje měnit hodnoty některých proměnných "na dálku" - přes webové rozhraní nebo pomocí vhodně složených URI, poslaných z jiného zařízení nebo nadřazeného řídícího systému. Více informací [[SDSC-C: sharing|naleznete zde]]. V tomto příkladu by se jednalo o potřebu dálkově měnit proměnné ''limit'' a případně ''hystereze''. Pak stačí doplnit do programové smyčky tento kus programu:
 +
<syntaxhighlight lang="c">
 +
//...
 +
 
 +
// hlavni smycka, ve ktere se vykonava proces
 +
label smycka_rizeni:
 +
 
 +
// prevezmeme hodnoty z dalkoveho nastavovani
 +
limit = sys[140];
 +
hystereze = sys[141];
 +
 
 +
// ...
 +
</syntaxhighlight>
 +
 
 +
Pak můžete u běžícího programu, bez nutnosti do jeho kódu zasahovat při potřebě změnit např. zmíněný teplotní limit, provést tuto změnu za provozu, např. přes webové rozhraní (opět viz návod [[SDS-C: sharing|zde]]) - s výhou si můžete do zařízení nahrát svou vlastní webovou stránku, a přes tu pak měnit konkrétní ''sys[]'' hodnoty. V té samé stránce může být i dynamické zobrazování aktuálních hodnot, takže cílový uživatel si bude moct komfortně ovládat zařízení, bez nutnosti se starat o vnitřní funkci.
 +
 
 +
 
 +
== Pole ram[] ==
 +
 
 +
Od verze SDS-C č. '''03''', můžete kromě pole '''sys[]''' využít i pole '''ram[]'''.
 +
 
 +
Jak už název napovídá, je možné do pole '''ram[]''' uložit libovolné údaje, a přistupovat k nim přes index.
 +
 
 +
Pole '''ram[]''' je už automaticky deklarováno, takže jej můžete přímo použít.
 +
 
 +
Příklad:
 +
<syntaxhighlight lang="c">
 +
var q;
 +
 
 +
q = 12;
 +
 
 +
ram[q] = 23;
 +
 
 +
echo('ram[',q,'] = ',ram[q]);
 +
</syntaxhighlight>
 +
 
 +
V příkladu jsme do pole ram, na pozici určenou obsahem proměnné '''q''', zapsali hodnotu 23. Následuje zavolání funkce '''echo''', která pro tento konkrétní příklad má následující výstup:
 +
ram[12] = 23
 +
 
 +
Pole ram[] se nastaví po resetu zařízení SDS (např. po zapnutí) na samé nuly.
 +
 
 +
 
 +
== Pole text[] ==
 +
 
 +
Všechny výrobky SDS, které mají verzi SDS-C č. 06 (a nebo vyšší), mají k dispozici pole '''text[]'''.
 +
 
 +
Díky tomu můžete snadněji pracovat s texty. Např. při příjmu textu ze sériové linky (např. z RS485 elektroměru nebo např. měniče), kde tento text chcete následně odeslat na svůj webový server k uložení do databáze. Nebo naopak, pokud potřebujete sestavit nějaký textový příkaz, který následně přes sériovou linku odešlete ven. Zde lze pole '''text[]''' s výhodou využít i např. pro výpočet CRC celého tohoto pole, nebo jeho části... viz pokročilé příklady.
 +
 
 +
Pole '''text[]''' je už automaticky deklarováno, takže jej můžete přímo použít.
 +
 
 +
Příklad:
 +
<syntaxhighlight lang="c">
 +
text[0] = 'A';
 +
text[1] = 'h';
 +
text[2] = 'o';
 +
text[3] = 'j';
 +
text[4] = 0x00; // nulová hodnota určuje konec psaného textu
 +
 
 +
echo(text[0]);
 +
</syntaxhighlight>
 +
 
 +
Příklad naplní prvních 5 pozic v poli '''text[]'''. Následné zavolání funkce '''echo()''' vypiše obsah pole '''text[]''' na konzoli, a to od pozice [0]. Takže zde vidíte, že můžete při předávání pole '''text[]''' jako parametr do nějaké funkce, určit, od které pozice bude mít daná funkce obsah pole '''text[]''' k dispozici.
 +
 
 +
Každý text v jazyce C je vždy ukončen znakem 0x00 (nulová hodnota). Všechny funkce při přebírání obsahu pole '''text[]''' ví, kde skončit, a to v okamžiku kdy narazí na tuto nulu. Tento znak (nula) není funkcí dále zpracován (např. vypsán na konzoli atd.), je použit jen jako indikátor konce.
 +
 
 +
Jednotlivé položky lze naplnit znaky ('A'), nebo konstatami (čísly - např. 15, 0x35, 0b01101101) nebo hodnotou z proměnné - v tomto posledním případě však dojde k převodu dolních osmi bitů na ASCII znak.
 +
 
 +
Příklad:
 +
<syntaxhighlight lang="c">
 +
var promenna;
 +
 
 +
promenna = 68;
 +
 
 +
text[0] = 'A';
 +
text[1] = 66;
 +
text[2] = 0x42;
 +
text[3] = promenna;
 +
text[4] = 0x00;
 +
 
 +
echo(text[0]);
 +
</syntaxhighlight>
 +
 
 +
Obsah pole '''text[]''' pro tento příklad bude: index [0] = 'A', index [1] = 'B', index [2] = 'C', index [3] = 'D'.
 +
Lze zapsat jen jeden znak najednou. Pro zápis celého řetězce viz funkce '''sprintf''' popsaná dále.
 +
 
 +
Každá položka pole '''text[]''' má datový rozměr 1 Byte. To znamená, že do ní lze uložit pouze číslo od 0 do 255. To je zásadní rozdíl vůči poli '''sys[]''' nebo '''ram[]''' které mají položky o rozměru 4 Bajty (viz základní popis). Pole '''text[]''' je totiž určeno k uchovávání ASCII znaků, nikoliv velkých číselných hodnot.
 +
 
 +
Příklady:
 +
<syntaxhighlight lang="c">
 +
text[0] = 'a';
 +
 
 +
// příklad numerické operace s položkou pole text[]
 +
text[0] = text[0] + 1;
 +
// pozice text[0] teď obsahuje znak 'b' (což je 'a' + 1)
 +
</syntaxhighlight>
 +
 
 +
Dále:
 +
<syntaxhighlight lang="c">
 +
var x;
 +
x = 123456;
 +
text[0] = x;
 +
// protože ale položky text[] mají jen 8 bitů (jen pro hodnoty 0 až 255),
 +
// je obsahem text[0] hodnota 64, i když v proměnné "x" je 123456.
 +
</syntaxhighlight>
 +
Všimněte si, že nedošlo k převodu číslo 123456 na text a jeho uložení do pole, ale naopak se vzala hodnota v '''x''' a uložila se do jediné položky, a to zde do indexu [0].
 +
 
 +
Pokud chcete převádět text na číselnou hodnotu, musíte použít funkci '''atoi()'''. V ostatních případech je k dispozici funkce '''sprintf()'''.
 +
 
 +
Využití v '''if''':
 +
<syntaxhighlight lang="c">
 +
if (text[123] == 'a') { goto neco_1; };  // bere pouze hodnotu na pozici [123], nikoliv celý text
 +
if (text[10] != x) { goto neco_2; }; // opět pouze hodnota na indexu [10], porovná s číslem v proměnné x
 +
if (text[54] < text[22]) { goto neco_3; }; // porovnává číselnou hodnotu na indexu [54] s číselnou hodnotou na indexu [22]
 +
//atd.
 +
</syntaxhighlight>
 +
 
 +
Znovu opakuji - využítí '''text[]''' v proměnných a pro '''if''' vždy bere jedinou položku určenou indexem pole.
 +
 
 +
Naopak využití '''text[]''' jako parametru funkce, bere všechny indexy počínaje uvedeným indexem, a to až do nálezu obsahu 0 nebo konce pole '''text[]'''. Pokud však je vašim záměrem předat funkci hodnotu jen konkrétního indexu pole, musíte to provést přes předání do uživatelské proměnné, viz následující příklad:
 +
 
 +
<syntaxhighlight lang="c">
 +
var x;
 +
 
 +
text[12] = 123;  // všimněte si, že zapisujeme na index [12] číselnou hodnotu 123, nikoliv však text '123' - nejsou tam ty '
 +
x = text[12]; // vezmi číselnou hodnotu jen z pozice [12]
 +
echo(x);  // vypíše hodnotu proměnné x: 123
 +
</syntaxhighlight>
 +
Dále:
 +
<syntaxhighlight lang="c">
 +
text[0] = 'a'; text[1] = 'b'; text[2] = 'c'; text[3] = 0;
 +
echo(text[0]);
 +
// vypíše: abc
 +
</syntaxhighlight>
 +
 
 +
Ruční naplnění (části) pole '''text[]''' textem - pouze funkcí '''sprintf''' (nebo pak ručné index po indexu...):
 +
<syntaxhighlight lang="c">
 +
sprintf(text[0], 'XXX');
 +
 
 +
sprintf(text[10], 'Ahoj.'); // vyplní [10]='A', [11]='h', [12]='o', [13]='j', [14]='.', [15]=0
 +
 
 +
echo(text[10]);
 +
// vypíše: Ahoj. (protože text[15] je 0).
 +
 
 +
echo(text[0]);
 +
// vypíše: XXX (protože text[3] je 0).
 +
</syntaxhighlight>
 +
 
 +
Detaily k '''sprintf''' jsou uvedeny na jiné [[SDS-C: sdsc_sysf|stránce]]. Omezení použití '''sprintf''' je pouze pro zápis do pole '''text[]'''. Všechny následující parametry jsou pak brány stejně jako pro funkci '''echo()'''. Funkce '''sprintf()''' vloží za poslední znak hodnotu nula.
 +
<syntaxhighlight lang="c">
 +
sprintf(text[123], 'Teplota je ', sys[310],' stupňů.');
 +
 
 +
echo(text[123]); // vypíše: Teplota je 1234 stupňů.
 +
</syntaxhighlight>
 +
 
 +
Hodnota v sys[98] určuje, kde je poslední zapsaný znak (0x00) při posledním provedení funkce '''sprintf'''. Toho lze využít pro navázání více následných volání funkce '''sprintf''' pro zápis textů přesně za sebou, bez ohledu na různou délku těchto textů.
 +
 
 +
A naposledy ještě jednou zopakuji, rozmezí hodnot uložitelných do každé položky (indexu) pole '''text[]''' je 0 až 255 včetně.
 +
 
 +
Pole text[] se nastaví po resetu zařízení SDS (např. po zapnutí) na samé nuly.
 +
 
 +
Další poznámka - ukončovací znak je 0 (tzn. 0x00 nebo také 0b00000000), nepleťte si to se znakem (char) '0' což má dekadickou hodnotu 48.
  
Takže pro SDS-C je definice: ''test { . . . };'' kdežto pro FULL-C je odpovídající definice: ''void test(void) { . . . };''
 
  
Funkce lze volat odkudkoliv, včetně klíčového slova ''if'' (pouze jako reakci na vyhodnocení podmínky, nikoliv v podmínce samotné).
+
== Pole share[] ==
  
Některé funkce jsou definovány jako vyhrazené, a některé jsou definovány jako interní pro daný výrobek SDS - viz seznam. Nesmíte použít názvy těchto funkcí pro své vlastní (uživatelské). Celkový počet funkcí je omezen.
+
Všechny výrobky SDS, které mají verzi SDS-C č. 08 (a nebo vyšší), mají k dispozici pole '''share[]'''.
  
 +
Princip použití pole share[] je identický s použitím pro pole text[].
  
== Vyhrazené funkce v SDS-C ==
+
Pole share[] ale navíc:
 +
* je přístupné stejně jako Sdílené Proměnné z webového rozhraní SDS (tzn. vhodné pro např. dálkovou konfiguraci SDS-C programu)
 +
* nelze jej využít ve zcela všech SDS-C funkcích (v porovnání s polem text[]) - nicméně se zde bavíme jen o několika funkcích z mnoha, kde to nejde
  
Jsou definovány tři základní vyhrazené funkce, které lze použít jedině k definovánému účelu.
 
  
Funkce '''main''' obsahuje hlavní program. Pokud si nevytvoříte vlastní smyčku, je po provedení všech instrukcí v ''main'' tato opět spuštěna od začátku (toto se dějě stále dokola po celou dobu kdy je zařízení zapnuto). Z této funkce lze volat jakékoliv podfunkce.
+
== Omezení ==
'''Je povinnost mít funkci ''main'' v programu definovanou.'''
 
  
Funkce '''init''' je zavolána jen při resetu zařízení. Není povinnost mít funkci ''init'' v programu definovanou.
+
Jazyk SDS-C má několik omezení, oproti plnému C99. Pokud chcete programovat bez těchto omezení, vyberte si SDS které pracuje s jazykem FULL-C.
Pozn. funkci ''init'' je možné znovu zavolat odkudkoliv.
 
  
Příkaz '''return''' je speciální funkce/příkaz - jedná se pouze o návrat (viz zásobník, tj. předčasné ukončení funkce ve které je ''return'' zavolán). ''return'' se nikde v programu nedefinuje, je to totiž vyhrazené slovo, které se jen používá.
 
  
 +
== Co teď ? ==
  
== Další poznámky ==
+
Vyzkoušejte si všechny předchozí příklady, uvidíte jak se skutečně chovají. Upravte je jak sami chcete, tím se to dále ještě naučite.
  
Návod pro SDS-C je rozdělen do více stránek na této WiKi.
+
Používejte vždy nejnovější firmware a EXE program. Obojí stáhnete vždy zdarma z našeho webu. Pokud použijete starší verzi, tak vám některé funkce nemusí fungovat, a zbytečně budete ztrácet čas hledáním chyby.
  
 +
Pokud vám SDS-C přijde příliš omezený, máte možnost přejít na [[FULL-C: intro|FULL-C]] jazyk, který omezení nemá - potřebujete ale pak použít výrobky SDS druhé řady, viz [[Seznam Všech SDS]].
  
 
__NOTOC__
 
__NOTOC__

Aktuální verze z 11. 4. 2021, 14:25

Tato stránka popisuje programovací jazyk SDS-C, který je dostupný na vybraných zařízeních SDS. 
Některá zařízení používají FULL-C, pro který máme návody jinde na této WiKi.

SDS-C

SDS-C je programovací jazyk. V lidsky čitelném textu zapisujete to, co chcete aby se stalo.

Sami musíte vědět, co vlastně chcete, no a pak už je to jen o tom, nějak to zapsat do stroje.

SDS-C je odvozeno od FULL-C, který je odvozen od jazyka C.

SDS-C je tedy zjednodušenou variantou FULL-C.


Jak to celé funguje?

Napíšete program. Ten se "přeloží" (compile), z vašeho pohledu to je kontrola správnosti zápisu. Následně se tento přeložený program nahraje (upload) do zařízení. Toto vše se provede v jediné aplikaci pro Windows, kterou si zdarma stáhnete z této WiKi.

Ihned po (úspěšném) nahrání se program automaticky spustí a je neustále dokola prováděn.

Každou 1 msec je proveden jeden celý příkaz (např. celé volání funkce, celý složitý zápis do proměnné, vyhodnocení if, a tak dále) - takže celková rychlost je vysoká - nepleťte si to s např. postupným vykonáváním instrukcí procesoru atd., tady se bavíme o nejvyšsí úrovni. Omezení na 1msec krok lze programově vypnout, viz návod.

Aby jste mohli v SDS-C psát svůj program, musíte znát všechny příkazy, a (systémové) proměnné. Detaily naleznete na tomto webu.

Ideální pro začátek je vzít již hotový funkční program, a ten si začít postupně upravovat. Každou úpravu co provedete si hned vyzkoušíte, a hned vám bude zřejmé, co který příkaz atd. dělá.


První program - jak na to

Potřebujete speciální kombinovaný editor/simulátor/uploader, ke stažení je z těchto stránek.

Sds english sdsc intro.jpg

V tomto programu zapíšete zdrojový kód svého SDS-C programu, můžete (ale nemusíte) jej ověřit odkrokováním v simulátoru, a nahrajete jej odsud přímo do výrobku SDS, kde se program zapíše do paměti a začne se ihned neustále dokola vykonávat.

V záložce "Source code" je textový editor - do něj budete zapisovat program. Až budete se zápisem hotovi, zmáčknete tlačítko "Compile". Otevře se okno s hlášením, zda-li je program v pořádku nebo zda-li je v něm chyba.

Pokud je program v pořádku, máte dvě možnosti (navzájem se nevylučují).

Můžete si program spustit v simulátoru "Debugger", ručně v něm krokovat nebo si vložit breakpointy (doubleclick nad místem kam se má breakpoint vložit). Rychlost automatického krokování lze nastavit posuvníkem na horní liště. Součástí simulátoru je i další okno, ve kterém máte možnost ovládat hardware, a sledovat výstupy vašeho programu.

Druhá funkce je nahrání programo do zařízení, karta "UPLOAD TO DEVICE". Jakmile jste se svým programem spokojeni, tak odsud jej nahrajete do hardware - v kartě jsou dvě tlačítka, první ověří komunikaci a velikost volné paměti, druhé pak provede samotné nahrání.


Jak se píše SDS-C program

Každý SDS-C program musí mít funkci main.

To co je uvnitř této funkce, je provedeno po spuštění programu.

Všechny další vámi definované funkce se volají teprve odsud.

Minimální program vypadá takto:

main
{

   // tady je program zapsaný ve funkci main

}


Aby to něco udělalo, dáme tam volání jedné systémové funkce, echo, což provede výpis textu na konzoli (viz webové rozhraní).

main
{

   echo('Ahoj z main!');

}

Když se provedou všechny příkazy, které jsou v main zapsány, stane se to, že je main automaticky spuštěno zase znovu - takže v důsledku je to nekonečná smyčka (dokud není program zastaven uživatelem, například).

Pokud je potřeba provést nějakou činnost, ale jen jednou po resetu programu, použije se vyhrazená funkce init. Příklad se pak rozroste následovně:

init
{
   echo('Ahoj z init!');
}

main
{
   echo('Ahoj z main!');
}

Samozřejmě, pokud init nepotřebujeme, nemusíme ho tam zapisovat.

Pokročíme dále. Program má možnost pracovat se všemi vstupy a výstupy, které dané zařízení poskytuje. Následující program zapne první relé:

main
{
  sys[231] = 1;
}

Kde se vzalo to sys[] ? To jsou pevně definované, tzv. systémové proměnné. Tyto proměnné jsou přímou vazbou na hardware.

Pomocí tzv. proměnných lze uchovávat hodnoty v paměti. Proměnná má nějaký název, ten si vymyslíte vy. Definuje se pomocí klíčového slova var. V příkladu si definujeme proměnnou pr, a zapíšeme do ní hodnotu 1.

var pr;

main
{
  pr = 1;
}

S proměnnou lze různě pracovat, a lze ji předat i jako parametr do funkce. Další příklad to ukazuje:

var pr;

main
{
  pr = 1;

  pr = pr + 10;

  echo('Hodnota promenne je ',pr);
}

Co se stane: nejprve definujeme pr, od místa kde je pr definována pomocí var s tím můžeme pracovat. Pak do pr vložíme pevnou hodnotu (v příkaldu je to číslo 1). Pak k hodnotě která je v tu chvíli v pr, přičteme číslo 10 (tj.: pr = pr + 10;).

Nakonec se zavolá funkce echo (výpis textu na konzoli) a vypíše se text: Hodnota promenne je 11.


Další příklad ukazuje, jak se do proměnné dá zapsat hodnota z hardware (tj. sys[]). Konkrétně se (podle tabulky) jedná o teplotní údaj z prvního externího teplotního čidla. Tento údaj je ale potřeba upravit (protože je posunut o dvě nuly), a nakonec je vypsán na konzoli.

var pr;

main
{
  pr = sys[310];  // prevezmeme teplotu z cidla 1 v tomto okamziku

  pr = pr / 100;  // vydelime 100, takze posuneme desetinnou tecku o dve mista doleva

  echo('Teplota je ',pr,' stupnu Celsia.');
}


Další vlastní funkce

Nemusíte se snažit vše vecpat do main. Často opakované kusy programu lze dát "bokem" do jiné funkce, a pak stačí jen tuto funkci "zavolat" a program v této funkci se na místě zavolání provede.

Příklad zápisu vlastní funkce (samozřejmě můžete mít svých funkcí více):

moje
{
  echo('Pozdrav z moji funkce.');
}

main
{
  echo('Pozdrav z main.');

  moje();  // takto se zavola moje funkce

  moje();  // ... muzu volat kolikrat chci, a to i odkudkoliv
}


Chytřejší SDS-C program

Důležitou součástí programu je schopnost rozhodovat na základě různých stavů a vstupů. Veškeré rozhodování se provádí zápisem konstrukce if (česky: pokud).

Kostra zápisu:

if (PODMÍNKA) {UDĚLEJ KDYŽ ANO} else {UDĚLEJ KDYŽ NE};

Nebo druhá možnost (zkrácená):

if (PODMÍNKA) {UDĚLEJ KDYŽ ANO};

Důležité je znát, co se má psát na místo PODMÍNKA a co lze zapsat na místa UDĚLEJ KDYŽ ANO/NE.

Podmínkou je samozřejmě všechno, podle čeho se chceme rozhodovat. Pokud budeme např. měřit teplotu, tak budeme např. chtít něco provést, když teplota bude větší než stanovený limit. Tento test se právě zapíše na místo označené jako PODMÍNKA.

Zbylé dvě místa, označená jako "UDĚLEJ KDYŽ ANO/NE", jsou zápisem činnosti, která se provede po vyhodnocení podmínky.

Příkladný program:

ano
{
   echo('Funkce ano.');
}

ne 
{
   echo('Funkce ne.');
}

main
{
  if (sys[310] > 1050) ano() else ne();
}

Co zde můžete vidět: definici dvou funkcí a ještě základní funkce main, dále jeden if. Tento if testuje aktuální hodnotu z hardware, která je uložena v sys[310] (což je teplota z prvního čidla), a pokud je tato teplota větší než 10.5°C, tak se zavolá funkce ano, v opačném případě se zavolá funkce ne.

Všimněte si, že volání funkce v if je specifické, a to přidáním () na konec názvu volané funkce.

V rámci testu lze spojit více podmínek dohromady. Například (vymyšleno pro zajímavost):

if (pr >= 102 && ((i % 2 == 0) || (sys[310] <= 0))) neco();

Konkrétní obsah testu si připravíte vy dle svých potřeb.

LZE POUŽÍT OD 14.5.2011:

Lze si i zpřehlednit zápis:

main
{
  if (nejaky_test)  { a = a + 1; b = b + 1; }; //pokud nejaky_test je ANO, pak se provede VSE co je zapsáno v { a }
}

Lze použít i else:

ano
{
  a = a + 1; b = b + 1;
}

main
{
  if (nejaky_test) { a = a + 1; echo(' ano !'); } else { a = a - 1; echo (' ne ! '); };
}

Vyzkoušejte si to.

Pozor! Pokud za IF použijete podblok, tj. { } , pak musíte do podbloku umístit jak kód před else, tak i za else.


Jak dělat smyčky

V jazyce C se smyčky dají zapsat řadou způsobů. Nejznámější je funkce for, kterou ale v této verzi SDS-C nemáme (ta je až ve FULL-C).

Proto je potřeba si poradit - a je to snadné.

Následující příklad ukazuje, jak udělat jednoduchou smyčku v SDS-C:

main
{
   var i;

   i = 0; //nastavíme výchozí hodnotu

label smycka:

   echo('hodnota i je ', i);

   i++;  //zvýšit i o 1

   //test: vše hotovo?
   if (i < 10) goto smycka;
}

Tento program postupně na konzoli vypíše čísla 0, 1, 2, 3, 4, 5, 6, 7, 8 a nakonec 9 .

Poznámka: tuto smyčku by jste v původím jazyce C zapsali následovně:

// příklad pro jazyk FULL-C (pozor ne pro SDS-C !)
// ve výsledku odpovídá předchozímu ukázkovému programu
 
int i;
for (i = 0; i < 10; i++) { printf("hodnota i je %d", i); };


Příklad: nekonečná smyčka

Nekonečná smyčka je velmi užitečná. Ze dvou důvodů: trvalé zablokování činnosti programu (užitečné při zkoušení a podobně), a dále jako hlavní smyčka programu.

Příklad nekonečné "zásekové" smyčky:

main
{
   //...

label smycka:
   //hned skocim zpatky na label smycka, takze to zde zustane natrvalo
   goto smycka;

   //sem uz se program nikdy nedostane !
}

Samozřejmě použití klíčového slova label není nutné (může být použito pro zpřehlednění textu), takže následující příklad je správně:

main
{
   //...

smycka:
   //hned skocim zpatky na label smycka, takze to zde zustane natrvalo
   goto smycka;

   //sem uz se program nikdy nedostane !
}

Příklad hlavní smyčky programu:

main
{
   //...

label smycka:

   //nejaky kus programu, kde je potreba neco neustale testovat
 
   if (sys[151 == 0) udelej_neco();

   //atd...

   goto smycka;

   //sem uz se program nikdy nedostane !
}

Příklad: čekací smyčka

Někdy je potřeba čekat nějakou pevně stanovenou dobu, než se provede nějaká akce, atd. Např. při postupném zapínání relátek (které mohou připojovat velké zátěže, a nelze je sepnout najednout, příkladů z praxe je celá řada).

Následující příklad sepne RELE1, pak počká 2 sekundy a pak sepne RELE2:

main
{
 
   sys[231] = 1;  //zapni RELE 1

   sys[64] = 2; //nastav odpočítávač na 2 sekundy (od tohoto okamžiku, kdy do sys[64] zapíšeme hodnotu 2)
label cekam:
   if (sys[64] != 0) goto cekam; //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"

   sys[232] = 1; //zapni RELE 2

}

Samozřejmě, nemusíte hned používat smyčku a sekundový odpočítávač sys[64], můžete totiž použít funkci wait. Ale umožní vám funkce wait vložit svůj další kus programu do čekací smyčky a tento kus programu provádět, zatímco čekáte? Ne.

Často je potřeba při čekání provádět další činnost. Vezměme si opět předchozí příklad, ale doplňme ho o potřebu měřit teplotu (z teplotního čidla) a pokud teplota klesne pod 30°C, tak zavolat nějakou funkci. Jde o příklad, takže to bude stačit.


Následující příklad sepne RELE1, pak počká 2 sekundy a pak sepne RELE2, ale současně během čekání hlídá teplotu:

main
{
 
   sys[231] = 1;  //zapni RELE 1

   sys[64] = 2; //nastav odpočítávač na 2 sekundy
label cekam:

   //klesla teplota z cidla 1. pod 30.00°C ? Pokud ano, zavolej "nejaka_funkce"
   if (sys[310] < 3000) nejaka_funkce();

   //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"
   if (sys[64] != 0) goto cekam; 

   sys[232] = 1; //zapni RELE 2

}

Můžete si program i zpřehlednit, za použití #define :

#define RELE1 sys[231]
#define RELE2 sys[232]
#define TEPLOTA1 sys[310]
#define ODPOCET_SEKUND sys[64]
 
main
{
 
   RELE1 = 1;  //zapni RELE 1

   ODPOCET_SEKUND = 2; //nastav odpočítávač na 2 sekundy
label cekam:

   //klesla teplota z cidla 1. pod 30.00°C ? Pokud ano, zavolej "nejaka_funkce"
   if (TEPLOTA1 < 3000) nejaka_funkce();

   //dokud je sys[64] nenulové (neuplynuly nastavené 2 sekundy), skoč na label "cekam"
   if (ODPOCET_SEKUND != 0) goto cekam; 

   RELE1 = 1; //zapni RELE 2

}


První užitečný SDS-C program

Ukažme si na následujícím příkladu první užitečnější program.

Tento program měří teplotu z prvního teplotního čidla, a při překročení teploty odešle email s poplachovou zprávou. Email je poslán jen jednou, pouze v okamžiku, kdy dojde k překročení stanovené teploty. Jakmile se teplota vrátí pod poplachový limit, je program znovu připraven poslat další email, při novém překročení limitu.

Co budeme potřebovat, aby se takový program dal sestavit:

  • promennou s urcenym limitem
  • promennou s hodnotou hystere (hysterezi je nezbytne pouzit v obecne kazde uloze s merenim teploty, zkuste to bez a uvidite proc)
  • hlavní programovou smyčku, ve které se bude neustále porovnávat změřené teplota s určeným limitem
  • funkci pro odesílání emailu
  • proměnnou, ve které bude uložena informace o tom, že byl email odeslán - to proto, aby byl odeslán vždy jen jeden email při překročení limitu (pokud by se toto vynechalo, byly by emaily odesílány nepřetržitě po celou dobu, kdy je teplota překročena, a to jistě nikdo nechce)
var limit, hystereze;
var email_odeslan;

teplota_ok
{
  //volano po celou dobu, kdy je teplota pod limitem (do uvahy je brana i hystereze)

  //povolime odeslani emailu pri pristim prekroceni limitu
  email_odeslan = 0;

  //sem se daji doplnit dalsi funkce, napr. ovladani rele (zapnout topeni = zvysovat teplotu)
}

hlasim_prekroceno
{
  //volano po celou dobu, kdy je teplota nad limitem

  //pokud jsem uz odeslal email, nebudu ho posilat znovu
  if (email_odeslan == 0)
  {

    //jeste jsem email neodeslal, takze...
    smtp_send('joe@foo.bar','Teplotni poplach', 'Teplota prvního čidla překročila limit!');

    //a zapamatuji si odeslani 
    email_odeslan = 1;

  }

  //sem se daji doplnit dalsi funkce, napr. ovladani rele (vypnout topeni = snizovat teplotu)
  sys[RELE] = 1;
}

main
{  

  //nastavime limit teploty (st.C) 
  limit = 25;  

  //nastavime hodnotu hystereze pro urceni navratu (st.C)
  hystereze = 2;

  //vychozi stav
  email_odeslan = 0;

  //pockame 10 sekund, az nabehne cely system
  wait(10000);  


  //------------------------------------------------------------  

  //hlavni smycka, ve ktere se vykonava proces
label smycka_rizeni:  
 

  //teplota je brana z cidla
  teplota = (sys[310] / 100);  //musime delit 100 aby to byly cele stupne Celsia  

  //podle aktualni teploty se rozhodnu  
   if (teplota < limit - hystereze) teplota_ok();   
   if (teplota > limit) hlasim_prekroceno();

  //a porad dokola  
  goto smycka_rizeni;  
}

Toto už je pěkný program na hraní, dá se kompletně odzkoušet v debuggeru. Můžete se pak pokusit sami doplnit další funkce, např. již naznačené ovládání relé (např. ovládající nějaké topení, které by ovlivňovalo teplotní čidlo), atd.

Dalším rozšířením programu může být dálkové ovládání. Využije se funkce zařízení SDS, které umožňuje měnit hodnoty některých proměnných "na dálku" - přes webové rozhraní nebo pomocí vhodně složených URI, poslaných z jiného zařízení nebo nadřazeného řídícího systému. Více informací naleznete zde. V tomto příkladu by se jednalo o potřebu dálkově měnit proměnné limit a případně hystereze. Pak stačí doplnit do programové smyčky tento kus programu:

//...

// hlavni smycka, ve ktere se vykonava proces
label smycka_rizeni: 

// prevezmeme hodnoty z dalkoveho nastavovani
limit = sys[140];
hystereze = sys[141];

// ...

Pak můžete u běžícího programu, bez nutnosti do jeho kódu zasahovat při potřebě změnit např. zmíněný teplotní limit, provést tuto změnu za provozu, např. přes webové rozhraní (opět viz návod zde) - s výhou si můžete do zařízení nahrát svou vlastní webovou stránku, a přes tu pak měnit konkrétní sys[] hodnoty. V té samé stránce může být i dynamické zobrazování aktuálních hodnot, takže cílový uživatel si bude moct komfortně ovládat zařízení, bez nutnosti se starat o vnitřní funkci.


Pole ram[]

Od verze SDS-C č. 03, můžete kromě pole sys[] využít i pole ram[].

Jak už název napovídá, je možné do pole ram[] uložit libovolné údaje, a přistupovat k nim přes index.

Pole ram[] je už automaticky deklarováno, takže jej můžete přímo použít.

Příklad:

var q;

q = 12;

ram[q] = 23;

echo('ram[',q,'] = ',ram[q]);

V příkladu jsme do pole ram, na pozici určenou obsahem proměnné q, zapsali hodnotu 23. Následuje zavolání funkce echo, která pro tento konkrétní příklad má následující výstup:

ram[12] = 23

Pole ram[] se nastaví po resetu zařízení SDS (např. po zapnutí) na samé nuly.


Pole text[]

Všechny výrobky SDS, které mají verzi SDS-C č. 06 (a nebo vyšší), mají k dispozici pole text[].

Díky tomu můžete snadněji pracovat s texty. Např. při příjmu textu ze sériové linky (např. z RS485 elektroměru nebo např. měniče), kde tento text chcete následně odeslat na svůj webový server k uložení do databáze. Nebo naopak, pokud potřebujete sestavit nějaký textový příkaz, který následně přes sériovou linku odešlete ven. Zde lze pole text[] s výhodou využít i např. pro výpočet CRC celého tohoto pole, nebo jeho části... viz pokročilé příklady.

Pole text[] je už automaticky deklarováno, takže jej můžete přímo použít.

Příklad:

text[0] = 'A';
text[1] = 'h';
text[2] = 'o';
text[3] = 'j';
text[4] = 0x00; // nulová hodnota určuje konec psaného textu

echo(text[0]);

Příklad naplní prvních 5 pozic v poli text[]. Následné zavolání funkce echo() vypiše obsah pole text[] na konzoli, a to od pozice [0]. Takže zde vidíte, že můžete při předávání pole text[] jako parametr do nějaké funkce, určit, od které pozice bude mít daná funkce obsah pole text[] k dispozici.

Každý text v jazyce C je vždy ukončen znakem 0x00 (nulová hodnota). Všechny funkce při přebírání obsahu pole text[] ví, kde skončit, a to v okamžiku kdy narazí na tuto nulu. Tento znak (nula) není funkcí dále zpracován (např. vypsán na konzoli atd.), je použit jen jako indikátor konce.

Jednotlivé položky lze naplnit znaky ('A'), nebo konstatami (čísly - např. 15, 0x35, 0b01101101) nebo hodnotou z proměnné - v tomto posledním případě však dojde k převodu dolních osmi bitů na ASCII znak.

Příklad:

var promenna;

promenna = 68;

text[0] = 'A';
text[1] = 66;
text[2] = 0x42;
text[3] = promenna;
text[4] = 0x00;

echo(text[0]);

Obsah pole text[] pro tento příklad bude: index [0] = 'A', index [1] = 'B', index [2] = 'C', index [3] = 'D'. Lze zapsat jen jeden znak najednou. Pro zápis celého řetězce viz funkce sprintf popsaná dále.

Každá položka pole text[] má datový rozměr 1 Byte. To znamená, že do ní lze uložit pouze číslo od 0 do 255. To je zásadní rozdíl vůči poli sys[] nebo ram[] které mají položky o rozměru 4 Bajty (viz základní popis). Pole text[] je totiž určeno k uchovávání ASCII znaků, nikoliv velkých číselných hodnot.

Příklady:

text[0] = 'a';

// příklad numerické operace s položkou pole text[]
text[0] = text[0] + 1;
// pozice text[0] teď obsahuje znak 'b' (což je 'a' + 1)

Dále:

var x;
x = 123456;
text[0] = x;
// protože ale položky text[] mají jen 8 bitů (jen pro hodnoty 0 až 255), 
// je obsahem text[0] hodnota 64, i když v proměnné "x" je 123456.

Všimněte si, že nedošlo k převodu číslo 123456 na text a jeho uložení do pole, ale naopak se vzala hodnota v x a uložila se do jediné položky, a to zde do indexu [0].

Pokud chcete převádět text na číselnou hodnotu, musíte použít funkci atoi(). V ostatních případech je k dispozici funkce sprintf().

Využití v if:

if (text[123] == 'a') { goto neco_1; };  // bere pouze hodnotu na pozici [123], nikoliv celý text
if (text[10] != x) { goto neco_2; }; // opět pouze hodnota na indexu [10], porovná s číslem v proměnné x
if (text[54] < text[22]) { goto neco_3; }; // porovnává číselnou hodnotu na indexu [54] s číselnou hodnotou na indexu [22]
//atd.

Znovu opakuji - využítí text[] v proměnných a pro if vždy bere jedinou položku určenou indexem pole.

Naopak využití text[] jako parametru funkce, bere všechny indexy počínaje uvedeným indexem, a to až do nálezu obsahu 0 nebo konce pole text[]. Pokud však je vašim záměrem předat funkci hodnotu jen konkrétního indexu pole, musíte to provést přes předání do uživatelské proměnné, viz následující příklad:

var x;

text[12] = 123;  // všimněte si, že zapisujeme na index [12] číselnou hodnotu 123, nikoliv však text '123' - nejsou tam ty '
x = text[12]; // vezmi číselnou hodnotu jen z pozice [12]
echo(x);  // vypíše hodnotu proměnné x: 123

Dále:

text[0] = 'a'; text[1] = 'b'; text[2] = 'c'; text[3] = 0;
echo(text[0]);
// vypíše: abc

Ruční naplnění (části) pole text[] textem - pouze funkcí sprintf (nebo pak ručné index po indexu...):

sprintf(text[0], 'XXX');

sprintf(text[10], 'Ahoj.'); // vyplní [10]='A', [11]='h', [12]='o', [13]='j', [14]='.', [15]=0

echo(text[10]);
// vypíše: Ahoj. (protože text[15] je 0).

echo(text[0]);
// vypíše: XXX (protože text[3] je 0).

Detaily k sprintf jsou uvedeny na jiné stránce. Omezení použití sprintf je pouze pro zápis do pole text[]. Všechny následující parametry jsou pak brány stejně jako pro funkci echo(). Funkce sprintf() vloží za poslední znak hodnotu nula.

sprintf(text[123], 'Teplota je ', sys[310],' stupňů.');

echo(text[123]); // vypíše: Teplota je 1234 stupňů.

Hodnota v sys[98] určuje, kde je poslední zapsaný znak (0x00) při posledním provedení funkce sprintf. Toho lze využít pro navázání více následných volání funkce sprintf pro zápis textů přesně za sebou, bez ohledu na různou délku těchto textů.

A naposledy ještě jednou zopakuji, rozmezí hodnot uložitelných do každé položky (indexu) pole text[] je 0 až 255 včetně.

Pole text[] se nastaví po resetu zařízení SDS (např. po zapnutí) na samé nuly.

Další poznámka - ukončovací znak je 0 (tzn. 0x00 nebo také 0b00000000), nepleťte si to se znakem (char) '0' což má dekadickou hodnotu 48.


Pole share[]

Všechny výrobky SDS, které mají verzi SDS-C č. 08 (a nebo vyšší), mají k dispozici pole share[].

Princip použití pole share[] je identický s použitím pro pole text[].

Pole share[] ale navíc:

  • je přístupné stejně jako Sdílené Proměnné z webového rozhraní SDS (tzn. vhodné pro např. dálkovou konfiguraci SDS-C programu)
  • nelze jej využít ve zcela všech SDS-C funkcích (v porovnání s polem text[]) - nicméně se zde bavíme jen o několika funkcích z mnoha, kde to nejde


Omezení

Jazyk SDS-C má několik omezení, oproti plnému C99. Pokud chcete programovat bez těchto omezení, vyberte si SDS které pracuje s jazykem FULL-C.


Co teď ?

Vyzkoušejte si všechny předchozí příklady, uvidíte jak se skutečně chovají. Upravte je jak sami chcete, tím se to dále ještě naučite.

Používejte vždy nejnovější firmware a EXE program. Obojí stáhnete vždy zdarma z našeho webu. Pokud použijete starší verzi, tak vám některé funkce nemusí fungovat, a zbytečně budete ztrácet čas hledáním chyby.

Pokud vám SDS-C přijde příliš omezený, máte možnost přejít na FULL-C jazyk, který omezení nemá - potřebujete ale pak použít výrobky SDS druhé řady, viz Seznam Všech SDS.