gaminn, 26.8.2008 18:29:08
Zapomněl jsem takový detail - program je určený pro MCU, takže mě zajímá realizace v assembleru.
Muflon, 26.8.2008 18:34:12
Zapoměl jsi další věc a to o jaký MCU se jedná.
lol, šmajrá taková prkotina...
>>jo a ještě si zapomněl říct, jestli to je pamět SRAM uvnitř kontroléru, nebo nějaká externí pamět, ale předpokládám že tohle umíš
A nenapadlo tě takhle použít SHIFT LEFT/RIGHT? Víceméně pořesně to dělá to, co potřebuješ
u 8051 jsou to instrukce Rl, RR, RLC, RRC
u AVR jsou to ROL, ROR
u piců nevim, s těma nedělám, (btw pro mě sou FUJ) :)
chybička se vloudila, u 8051 to Rl je RL (ale to L je malé)
gaminn, 26.8.2008 19:22:57
Muflon: To není ptořeba, zajímá mě princip. Jinak ale dělám na freescalech, HC08.
Jan16: Jasně, že cosi se shiftem mě napadlo - obsah buňky by se posouval, pokud bych byl na pozicích, které chci přenést, testoval bych carry bit a podle něho se rozhodoval, jestli do cílového místa zápíšu jedničku nebo nulu. Takže efektivněji to nelze? :)
cože si to plácnul? :)
Zjevně nechápeš jak funguje shift...
Mám registr s obsahem:
01111000
a potřebuju bity 6,5,4,3 dostat na pozice 3,2,1,0 tj o 3 místa vpravo, ta prostě dám 3x shift vpravo, a víc to neřešim, na co zas ten carry?? :)
Doufám že sem to vymyslel správně...
Prostě vždy provedeš shift o tolik míst a směr jaký je potřeba pro posunutí těch bitů...
gaminn, 26.8.2008 20:05:00
Ale no tak, Jeníku. Nedělej ze mě vola a raději si ještě jednou přečti, co potřebuju. :)
paměťové místo A: 01011001
paměťové místo B: 10100001
Požadavek: Bity na pozici 6,5,4 paměťového místa A přesunout na pozice 3,2,1 paměťového místa B
Po provedení:
paměťové místo A: 01011001
paměťové místo B: 10101011
ehm, 26.8.2008 20:19:09
v AVR:
ANDI RXB,0b11110000
SRBC RXA,6(Skip if Register Bit Clear)
ORI RXB,0b00001000
SRBC RXA,5
ORI RXB,0b00000100
SRBC RXA,4
ORI RXB,0b00000010
SRBC RXA,3
ORI RXB,0b00000001
1) neřikej mi jeníku, to nesnášim, ty ty.. g něco :)
2) Hluboce se Vám omlouvám, že jsem si nepřečetl Vaše celé zadání.
gaminn, 26.8.2008 21:05:37
ehm: Sice neznám AVR, ale princip bude nejspíš takový, na jaký jsem sám přišel.
Jan16: Jen jsem oplácel...No, ale přečíst si zadání, na které odpovídám, je docela dobrý zvyk, uznej.
ASD, 26.8.2008 21:34:34
A)
lds R0, memA
lds R1, memB
lsr R0
lsr R0
lsr R0
andi R0, 0B00001111
andi R1, 0B11110000
or R1, R0
sts memB, R1
B)
lds R0, memA
lds R1, memB
bst R0, 6
bld R1, 3
bst R0, 5
bld R1, 2
bst R0, 4
bld R1, 1
bst R0, 3
bld R1, 0
sts memB, R1
ehm, 26.8.2008 21:49:42
no, sposobov je viac... mozes napriklad pouzit moj, ktory vopred vymaze bity v cielovom registri a potom zistuje, ci su v prvom registri nastavene a ak ano, tak ich zapise. ak nie, preskoci zapis..
potom mozes pouzit nieco, co tu napisal kolega ak som spravne pochopil.. vymazes bity v cieli, skopirujes prvy register do temp, vymazes vsetko ostatne okrem prenasanych bitov, posunies doalva alebo doprava o potrebny pocet a cez OR hodis do ciela..
Jirka, 26.8.2008 23:06:49
Takhle bych to řešil přímo s HC08:
LDA memB ;paměťové místo B do střadače
AND #11110000 ;vynuluje bity dolni nibble (bity 3-0)
STA memB ;uloží zpět do memB
LDA memA ;paměťové místo A do střadače
LSLA ;posun střadače vlevo C<Acc<0
NSA ;prohození nibble ve střadači Acc=Acc(3,0):Acc(7,4)
AND #00001111 ;vymaskuje horní nibble Acc
ORA memB ;nastavi bity 3-0 v memB dle dolniho nibble Acc
Původní místo memA zůstává nedotčeno, v memB je nový stav s aktualizovanými bity 3-0
Jirka, 26.8.2008 23:15:00
Správný zápis binárního operandu je samozřejmě takhle:
AND #%11110000 ;vymaže bity dolni nibble (bity 3-0)
V příspěvku výše mi chybí ten znak procenta.
ASD, 27.8.2008 00:00:17
To Jirka: Tak to je dobrý napad to LSLA + NSA
Jirka, 27.8.2008 00:56:02
Dík za pochvalu. V zadání bylo "co nejefektivněji"
gaminn, 31.8.2008 14:54:42
Nechci zakladat dalsi thread....
Vykonavani meho programu se za normalnich okolnosti zacykli v jedne smycce... Nyni přijde přerušení (od klávesnice - KBI), vykoná se rutina, ktera ho obsluhuje. Ta se provede a potom se samozřejmě MCU vrátí k vykonavani instrukce, kterou měl dělat před přerušením. To ale nechci - potřeboval bych buď:
a) Přerušení pozdržet až se vykoná hlavní smyčka programu a nechat jej vyvolat na konci této smyčky
b) Z přerušení se nevracet na místo, kde byl program před přerušením, ale vrátit se na konec smyčky.
Připomínám, že používám HC08. Napadá mě jedině tak ve funkci obsluhující přerušení modifikovat zásobník na pozicích, kde je nahrána adresa, kam se má program po přerušení vrátit, tj. nahrát si tam svoji adresu.
Podle mě by zajíisté ten program šel napsat tak, aby tam tohle nebylo
pokud bude třeba ukončit přerušení, a aby program pokračoval potom vždy ze stejného místa, tak co třeba JuMP na pevně danou pozici za tu tvojí smyčku, a ž až tam potom to RETI
a to zadání za A jsem nepochopil. Jak pozdržet přerušení než se to dokončí. Přece nemůžou běžet dvě věci najednou ne?
ehm, 31.8.2008 15:27:05
zadanie A - povol prerusenie iba na konci programu.. ked dojde k podmienke, prerusenie sa zapise, ale bude muset pockat kym ho procesor povoli.. aspon tak to funguje u AVR
gaminn, 31.8.2008 18:15:45
Jan16:
Dobře, v obsluze přerušení skočím kamsi. Když pak ale zavolám RTI, tak se mi přece opět nastaví program counter na hodnotu, která byla uložena na zásobníku a výsledek je totožný, jako kdybych rti volal hned v obslužné rutině přerušení.
ehm:
Tohle mě taky napadlo a zkoušel jsem - ovšem bez úspěchu, ale nevím, jestli jsem něco nedělal blbě. Takže neví někdo, jestli HC08 podporuje to, aby se přerušení vyvolávalo se zpožděním - až když bude povoleno?
Jirka, 31.8.2008 22:27:14
Jestli je zadání A a B ekvivalentní, tak se v obsluze toho přerušení prostě jenom nastaví nějakej flag a zakáže další přerušení. Flag se pak bude testovat na konci té hlavní programové smyčky. V případě, že bude nastaven, provede se obslužná rutina (která měla být původně v obsluze toho přerušení), shodí se ten flag a povolí další přerušení.
Další možností je, že se nebude nastavovat jenom flag, ale zapíše se i kolikrát přerušení přišlo a případně z jakého zdroje. Pak by se přerušení už nezakazovalo. Vše se zase vyhodnotí na konci programové smyčky.
Jenom netuším k čemu je to dobré. Tohle přeci popírá samu podstatu přerušení a myslím, že by se to dalo řešit jinak.
gaminn, 1.9.2008 08:56:13
OK, takze asi to resim blbe, pomozte mi to napravit :)
V hlavni smycce se neustale vykonava rutina vypisujici na displej aktualni cas. Nekdy uprostred jejiho vykonavani prijde stisk tlacitka = preruseni. To zpusobi, ze na displej se vypise nejaky staticky text. Po preruseni se uz logicky nechci vracet k vypisovani hodin nekde odprostredka. Jak to byste to tedy resili?
Jirka, 1.9.2008 10:11:48
Řešil bych to přesně naopak: v hlavní smyčce se bude testovat stisk kláves a připravovat ten statický obsah displeje. V přerušení, pověšeném na časovači, bude výpis na displej a čas. Přes nějaký ten flag se pak bude určovat jestli se budou vypisovat hodiny, nebo ten statický text uložený v nějaké proměnné. O zápis textu do proměnné, stejně jako o nastavování flagu, se tedy bude starat hlavní smyčka. Výpis zajistí přerušení, které bude závislé jen na časovači. Takhle je to správné. Takhle má pracovat přerušení a takhle se podobné případy opravdu řeší.
Jirka, 1.9.2008 10:18:03
Ještě perlička. Nedávno jsem řešil problém s HC08 (8-pinový typ QT 4 kb Flash). Po cca ročním provoze v zařízení, najednou zařízení přestalo pracovat. Zjistil jsem, že nepracuje procesor. Dal jsem ho do programátoru a normálně jsem s ním komunikoval. Nebyl zamčený ani poškozený, ale byl předpisově smazaný! Všude $FF. Nechápu, jak k tomu mohlo dojít. Programovací napětí, se na příslušný pin během provozu zařízení dostat nemohlo (byla tam LED). Procesor jsem znovu vymazal, naprogramoval, verifikoval a už to zase nějakou dobu normálně funguje...
ASD, 1.9.2008 11:14:59
To Jirka: Tak tohle se děje, když se na libovolný pin MCU dostane velké napětí, klidně stačí špička. Je to tím, že každý pin je přes diodu spojen s VCC a velké VCC obecně MCU nedělá dobře. Mě pomáhá na každý vodič, který opouští DPS a není to zem vrazit transil.
gaminn, 1.9.2008 11:31:00
U tohoto reseni bych mel dve nejasnosti:
Kdyz se teda ma stisk klaves cyklicky testovat v hlavni smycce programu, k cemu ma procesor modul KBI (keyboard interrupt)? Vychazim jen z toho, ze se jmenuje 'keyboard ...' tak bych cekal, ze se tim budou prave obsluhovat tlacitka.
A za druhe. Co kdyz prijde stisk tlacitka ve chvili, kdy je program zrovna v tom preruseni realizujicim vypis na displej? Takovy stisk tlacitka mi utece ne?
gaminn, 1.9.2008 11:32:02
Jinak ja s HC08 (nebo vlastne obecne s jednocipy) teprve zacinam, takze podobne zkusenosti s tim mazanim zatim nemam.
gaminn, 1.9.2008 11:42:48
Kdyz nad tim tak premyslim, tak nebylo by spravnejsi ponechat tlacitkum to, ze po jejich stisku se vyvola preruseni? V obluze by se nastavil nejaky flag, vylezlo by se z preruseni, dodelala by se "rozdelana" prace (dovypsaly by se hodiny) a v dalsim cyklu by se na zaklade jinak nastavenoho flagu uz nelezlo do vypisu hodin, ale udelala by se jina akce (vypis statickeho textu).
ASD, 1.9.2008 12:11:02
To Gaminn: Mě se osvědčilo tohle:
MCU v hlavní smyčce zadá práci časovači a veškerému dalšímu hardware a uspí se. Při přerušení se MCU probudí, zpracuje rutinu přerušení a nastaví příznaky. Poté MCU sám pokračuje ve hlavní smyčce programu, která zkontroluje příznaky a podle příznaků něco udělá, třeba obslouží stisk klávesy. Až to má hotové, tak se zase uspí.
ASD, 1.9.2008 12:13:45
To Gaminn: Tohle prece nepotrebujes delat trvale, to staci 5x-10x za sekundu na zaklade casovace.
V hlavni smycce se neustale vykonava rutina vypisujici na displej aktualni cas.
gaminn, 1.9.2008 19:55:48
ASD: Ma nejaky vyznam to vypinani MCU, krome snizeni spotreby (a je to snizeni spotreby vyznamne?). Jinak tuto variantu určitě použiju.
Jeste k tlacitkum, ktera vyvolavaji preruseni - cim se osetruje stisk (a samozřejmě i druhý směr - povolení) tlacitka, aby to byl opravdu jeden cisty prechod z jedne urovne do druhe a nebylo to doprovazene nejakymi nahodnymi spickami? Takovy "neosetreny" stisk vyvola treba 5 přerušení za sebou...Nemluvě o povolení tlačítka, které by samozřejmě vyvolat přerušení nemělo.
ASD, 1.9.2008 20:20:40
To uspání pro funkci není nutné, ale pro bateriovou aplikaci povinné.
Ošetření tlačítek se dělá třeba na základě časovače, tj. skenuješ tlačítka 10x za sekundu. Případné špičky nebo zákmity jsou v řádu mikrosekund, takže se tomu tímto elegantně vyhneš. Jde to odstranit i hardwarově RC členem.
zdenda, 1.9.2008 22:01:00
myslím že se dá použít i nějaký R-S klopný obvod, učili nás to kdysi na střední.
gaminn, 2.9.2008 09:19:57
No, nejschudnejsi by mi prislo pri preruseni (mozny stisk tlacitka nebo jenom nejaky zakmit na tlacitku) v cyklu treba 20x za sebou testovat, jestli je na vstupnim pinu MCU stale stav sepnuto (nula), nebo jestli to byl jenom zakmit.
já kdysi vymyslel úplně geniální způsob na obsluhu tlačítek pro mikro kontroléry. Nechce se mi to sem celý popisovat, je to na dlouho, to okecat, ale princip jednoduchej.
Pokud máš zájem, písni mi na mejla nebo ajsko: 225-664-188 probereme to spolu...
>>Je použit jeden časovač, přerušení by mělo vznikat přibližně 100x za sekundu. Je to jen "pár" řádků kodu. takže to přerušení nebude zbytečně dlouho zdržovat.
Filtruje to velmi účinně zákmity a indukované špičky. Jednoduše lze napsat rutinu, která se provede při stisknutí tlačítka, uvolnění tlačítka, nebo se provede vždy, když je tlačítko stisknuté.(nestisknuté)
Jirka, 2.9.2008 17:39:37
ASD: O tom už jsem mockrát uvažoval, ale byl jsem vždycky línej tam ty transily dát. Přitom transil je bezvadná součástka. Ten procesor opravdu běhá v zařízení, ve kterém není o indukované špičky nouze. Zatím jsem se vždy zaměřoval jen na filtraci napájení a na citlivých vstupech používám opta. Doplním ještě ty transily. Díky.
Jirka, 2.9.2008 17:40:05
gaminn: Vidím, že jsi na to přišel. Přerušení od klávesnice můžeš opravdu použít jen v případě, že máš hardwarově ošetřený zákmity tlačítek. Pokud připojíš tlačítka přímo k MCU, musíš jejich ošetření udělat softwarově. Osobně používám univerzální rutinu, která vyhodnotí stav tlačítka, resp. jiného kontaktního vstupu, (sepnuto nebo rozepnuto) až po určitém počtu stejných čtení, kdy se stav kontaktu nemění. Můžu tě ujistit, že 20x je pořád málo. Na mikrospínač používám 50-100 čtení, na obyčejné tlačítko klidně i plné 8-bitové rozlišení, tedy 255 čtení. Ta HC08 to v pohodě zvládne. Nemusíš se bát nějakých zpoždění. V každém průchodu hlavní smyčkou se čte jednou, nebo vícekrát (podle délky hlavní smyčky) a používají se stavové proměnné k uchování stavu.
Ve tvém případě, bych hodiny řešil jedním přerušením s nejvyšší prioritou od časovače a ukládal je do proměnných. Tato časová rutina by byla zcela autonomní.
Další časovač bych použil k přerušení vyvolávající obsluhu displeje. Ještě jsi nenapsal, jestli je displej statický (třeba LCD s řadičem, nebo multiplex). Tohle přerušení by mělo nižší prioritu a jen by se braly hodnoty z předem daných proměnných a zobrazovaly na displej. Rutina by byla opět zcela autonomní.
V hlavní smyčce by pak bylo to testování kláves, ošetření zákmitů a příprava textu pro výpis. Dále by se do stavové proměnné pro displej zapsalo, jestli má obslužná rutina vypsat čas, nebo nachystaný text. Ale to už se opakuju.
Myslím ale, že to je pro začátečníka docela sousto. Doporučuji nejprve se naučit ošetřování tlačítek, pak obsluhu displeje (a vypisovat stav těch tlačítek) a nakonec přidat práci s přerušením a naprogramovat hodiny.
Ještě dotaz, jaký používáš vývojový kit?
To co používáš ty, není zrovna moc efektivní způsob. Sám jsem podobné blbosti kdysi zkoušel. NA co to číst 200x? Já to přečtu jednou za čas, a okamžitě hned je vyhodnocen reálný stav tlačítek venku. Bez zákmitů. Proti zakmitávání je tam naprogramováno cosi jako R-S KO. KDyž to vyzkoušíš, určitě neprohloupíš. Navíc časovač, u kterého vniká přeršení jednou za 10ms se dá upotřebit i jinak. Třeba pro "pohon" hodin (taktovací jednotka)
ASD, 2.9.2008 17:58:50
To Jirka&Gaminn: Stonásobné čtení vstupu vůbec není potřeba, to spíše kdyby mě zajímal průběh zákmitu. Prostě na základě časovače oskenuji klávesnici, za 100 milisekund znovu, porovnám a je to.
ASD, 2.9.2008 18:02:17
To Jan16: Jeden časovač samozřejmě neznamená, že se používá jenom na jednu věc, poměrně snadno se dá napsat efektivně asi 10 virtuálních časovačů s pomocí jednoho hardwarového.
2 ASD: 100ms je už moc hodně. Zbytečně. 10ms stačí. Dokážu celkem bez problémů stisknout tlačítko na dobu kratší než 100ms. Tobě by to tento stisk ani nezaregistrovalo. (mám odzkoušeno)
Ještě jedna výhoda mého způsobu: K vyhodnocení reálného stavu tlačítka mi stačí jedno přerušení, nemusí se čekat na další, až se to porovná.
Je vidět, že bych sem měl ten způsob jak to řeším já napsat..
gaminn, 2.9.2008 18:20:01
Jan16: Napíšeš ho teda sem? Asi to bude zajímat víc lidí, tak by to bylo fajn.
OK, napíšu to tam, jdu večeřet, tak vydržte :)
Jirka, 2.9.2008 18:35:06
Začal jsem to používat, když jsem byl nucen v několika zařízeních číst hodně nekvalitní kontakty a osvědčilo se to. Bylo to jednodušší a levnější než náhrada původních kontaktů. Přerušení je na čtení pár tlačítek a koncáků opravdu škoda. Jó mikrospínače... to je selanka
HAHAHA lol, "prý text je moc dlouhý... hodim to k sobě na web, a dám sem odkaz... Ještě že jsem si to předem zazálohoval :)
gaminn, 2.9.2008 20:01:20
Diky....bude pro mě asi trochu náročnější to přelouskat :) Ale jdu na to...
Jirka, 2.9.2008 21:50:40
Jan16: a pokud budeš mít třeba 8 tlačítek (celý port), tak bude ta rutina osminásobně dlouhá?
gaminn, 2.9.2008 22:43:59
Proměnná HW se nastavuje před tím blokem kodu, který uvádíš (v přerušení od časovače)?
úplně mimo problematiku tlačítek: Nějak se nemohu dopátrat toho, proč instrukce DAA (úprava BCD čísla) po odečtení jedničky od 00000000 (vznikne tedy 11111111 s příslušnými flagy v CCR registru) udělá 01100101 (65 v BCD). Používám to při listování čísel na displeji, kdy si uživatel volí čísla v rozmezí 0-99. Když je navoleno číslo 0 a uživatel zmáčkne tlačítko "dolů", tak by mu měla naskočit 99. Očekával bych, že instrukce DAA si s tímhle poradí.
jo.. jinak vzhledem k tomu že si AT89S51 poradil při 12MHz s 6ti tlačítkama bez problému, tak si myslim, že třeba takový AVRko na 16MHz, který je cca 24x rychlejší to zvládne daleko líp.
Jinak to že bude 8x delší, myslim že ta metoda před tim, 200x číst tlačítko, no nevim, co zabere procíku víc času
8 tlačítek bude cca odhaduju u AVR (HC08 či co neznám) pocet instrukci na tlacitko na cca 10-15, max 20 (dáme 20) 8*20=160 instrukcí přibližně na 8 tlačítek. KDybych bral v potaz 200 přečtení portu "in Rd, pinx" při 8mi tlačítcích, už jen to nám dává 200*8 = 1600, tj 10x víc, a to sem bral v potaz jenom instrukci čtení portu...
asi takle: všechny proměnný se před prvním spuštěním přerušení musejí inicializovat, pro každé tlačítko zvlášť. Hodnoty tam napsaný jsou. Hdnota toho "HW" bitu se inicializuje sama tim, že do ní prostě načteš stav toho onoho bitu z IO portu. Možná sem blbě vysvětlil, ale v každym přerušení, bude potřeba hned na začátku zaktualizovat "HW" proměnné podle aktuálního stavu venčí... Jinak to logiky fungovat nemůže :)
>>tady je vidět jasná výhoda 8051 - nemá oddělený registry,porty, a podobně. Takže u 8051 se nemusejí hodnoty aktualizovat, dlá to HW sám při vykonávání instrukce, hodnotu si načte přímo z portu... ALe taky proto jsou ty 8051 tak pomalý :) a proto sem přešel na AVR :)
Pepa, 3.9.2008 07:11:28
Skvělá dedukce o příčinách nižší rychlosti 8051.
ASD, 3.9.2008 10:13:50
DAA je Decimal Adjust After Addition a to z principu vysvětluje, proč to nefunguje na odčítání.
8051 je pomalé proto, že s tím u Intelů začli snad v 80-tých letech a tehdy to rychleji nešlo. Dneska existují klony 8051, které mají 4 takty na instrukci a běží na nějakých 80 MHz, takže rychlost je pak prakticky stejná jako u AVR na 20 MHz.
gaminn, 3.9.2008 10:16:54
ASD: No jo :) Tak to s tim DAA me nenapadlo... Ovsem ta instrukce funguje pri odcitani (u me dekrementace) v pohode, jen je ten problem s prechodem z 0 na 99. Takze tenhle prechod si musim osetrit sam?
ASD, 3.9.2008 11:59:52
To Gaminn: Normálně se to počítá binárně a když se to chce ukázat na displeji, tak teprve pak se to převede do DEC.
gaminn, 3.9.2008 12:13:45
No a k cemu je pak instrukce DAA? Ja si radeji osetrim jen ten prechod 0 -> 99, nez delat celou funkci na prevod do BCD.
gaminn, 3.9.2008 14:19:23
Diky, ale pravdepodobne mi to je k nicemu, kdyz instrukce daa "skoro" funguje.
2 někdo - má dedukce byla ze srandy. S tim jsem to vážně nemyslel :)
2 někdo jiný: Jo? pokud vim, tak se dělalj klony i co běží 1 takt/instrukce, a jede to na 20MHz a víc..... někde mám možná od toho zázraku datasheet..
gaminn, 4.9.2008 23:49:27
Asi dost blbý dotaz - flash paměť MCU se nedá měnit při vykonávání programu? Čili jediný způsob zápisu do ní je napevno zapsaná hodnota při nahrávání programu do MCU?
ASD, 5.9.2008 00:06:59
To Gaminn: Naopak, dotaz je velice správný a u některých MCU to jde, třeba ATmega, nicméně zapisovat se obvykle dá jenom po určitých stránkách třeba 256 byte a takže se to hodí hlavně na aktualizace software. Na ukládání dat se víc hodí EEPROM.
gaminn, 5.9.2008 08:55:20
OK, a konkrétně HC08 QY4? Neví někdo? Z datasheetu mi připadá, že na trvalo si hodnotu, ktera je vystupem meho programu, nikde neuložím.
ASD, 5.9.2008 09:05:53
HC08 neznám, ale jestli to má EEPROM, tak tam jde zapisovat zaručeně a Flash se musí přečíst v DS.
gaminn, 5.9.2008 09:46:55
Má to flash...to DS je co za zkratku? :)
ASD, 5.9.2008 11:13:19
DS je Datasheet.
gaminn, 5.9.2008 11:42:37
Aha :)