NEzobrazování mrtvývh nul ve výsledném čísle na displeji.

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
DavidChlup
Příspěvky: 69
Registrován: 03 zář 2019, 00:00
Bydliště: Karlovy Vary

NEzobrazování mrtvývh nul ve výsledném čísle na displeji.

#1 Příspěvek od DavidChlup »

Ahoj,

mám tu další oříšek, mám tu převod 16bit binárního čísla přímo na ASCII. Principu rozumím, ale nevímm jak se zbavit těch nepotřebných nul před hodnotou. Když tam mám např číslo, jehož převod je 300 (dec), tak mi to vyzobrazí 00300. Určitě existuje nějaká finta, jak to vyrušit, dokud budou první výsledky v REG "nulové".

Kód: Vybrat vše

d5ascii: 
   ldi reg, $2F          ;Init ASCII conversion ('0'-1)
loop10k:
   inc reg               ;count up 10k "counts"
   subi ZL, $10
   sbci ZH, $27
   brcc loop10k           ;IF >=10000 THEN subtract again
   subi ZL, $F0           ;subtract -10000 (add 10000)
   sbci ZH, $D8
   rcall senddata              ;send 10k ASCII char

d4ascii:
   ldi reg, $2F          ;Init ASCII conversion ('0'-1)
loop1k: 
   inc reg               ;count up 1k "counts"
   subi ZL, $E8
   sbci ZH, $03
   brcc loop1k            ;IF >=1000 THEN subtract again
   subi ZL, $18           ;subtract -1000 (add 1000)
   sbci ZH, $FC
   rcall senddata      

d3ascii:
   ldi reg, $2F          ;Init ASCII conversion ('0'-1)
loop100:
   inc reg               ;count up 100 "counts"
   subi ZL, $64
   sbci ZH, $00
   brcc loop100           ;IF >=100 THEN subtract again
   subi ZL, $9C           ;subtract -100 (add 100)
   sbci ZH, $FF
   rcall senddata      
                  ;(ZH==0) so ignore ZH from here

d2ascii:
   ldi reg, $2F          ;Init ASCII conversion ('0'-1)
loop10: 
   inc reg               ;count up 10 "counts"
   subi ZL, $0A
   brcc loop10            ;IF >=10 THEN subtract again
   subi ZL, $F6           ;subtract -10 (add 10)
   rcall senddata      
   mov reg, ZL
d1ascii:
   subi reg, $D0           ;convert 1's digit to ASCII
   rcall senddata      
   ldi reg, ' '
   rcall senddata              ;send out a space
   ret
Naposledy upravil(a) DavidChlup dne 05 lis 2019, 20:36, celkem upraveno 6 x.
Uživatelský avatar
samec
Příspěvky: 6671
Registrován: 19 pro 2017, 00:00

#2 Příspěvek od samec »

Myslím, že loop1M, prípadne loop10M a niečo v ňom by to mohol vyriešiť.
petrfilipi
Příspěvky: 2901
Registrován: 13 zář 2005, 00:00

#3 Příspěvek od petrfilipi »

Nemůžeš provést typovou konverzi String na Integer?
Jaký typ je výsledek? Je to Integer (=číslo) nebo String (=text)?

PF
termit256
Příspěvky: 10029
Registrován: 06 pro 2007, 00:00

#4 Příspěvek od termit256 »

Az to cislo budes mit prevedene do ascii proste kontroluj zleva jednotlive cislice a pokud to bude nula, nahrad ji mezerou. Pokud to bude jine cislo nez nula, ukonci kontrolu. Nevim v cem vidis problem.
petrfilipi
Příspěvky: 2901
Registrován: 13 zář 2005, 00:00

#5 Příspěvek od petrfilipi »

Ten program funguje tak, že předpokládá číslo max. 99999. A odečítá 10000 tolikrát, až se dostane do záporných čísel. Přitom počítá, kolikrát odečetl těch 10000. Když se dostane do mínusu, přičte 10000, odečte 1 z počítadla desetitisíců a má počet desetitisíců. To samé pak dělá s 1000, to samé se 100, s 10 a pak mu zbyde počet jednotek. Takže na konci každé odečítací procedury bys měl kontrolovat, zdali není výsledek 0. Pokud je, neodesílat nic (nebo mezeru), jinak odesiláš počet v počítadle odečítání.
Nebo bys mohl na začátku odečítání kontrolovat, zdali je číslo vyšší než 10000. Pokud ano, odečítá s. Pokud ne, nevracíš nic (nebo mezeru).

PF
Uživatelský avatar
petula
Příspěvky: 828
Registrován: 22 kvě 2016, 00:00
Bydliště: Čelákovice / Brandýs n.L / Stará Boleslav
Kontaktovat uživatele:

#6 Příspěvek od petula »

vtip je v tom, že nemáš sestavený algoritmus a projekt, ale hned kóduješ program "z hlavy". Kdyby jsi postupoval řádně, sepsal nejprve algoritmus a projekt programu, a teprve potom podle projektu zakódoval program, tak by jsi tyhle potíže neměl.
Jenže to je důsledek pofiderní rychlokvaškové výuky na českých školách. Začíná se od konce, vše se dělá "zadkem napřed", obráceně. Programy se zhotovujé bez projektu, bez algoritmů, kódováním z hlavy.

Představ si, že by jsi stejným způsobem stavěl dům, bez projektu. Skládal by jsi cihly z hlavy, tak jak tě napadne. To by byly konce, co? :D Anebo by jsi takto bez projektu tvořil auto. Prostě by jsi bez výkresů, bez projektu soustružil, frézoval díly a snažil se je sestavit a chtěl, aby vzniklo jezdící auto. Ve strojírenství a stavařině si bez projektu troufnou pracovat leda tak blázni. V elektronice a prgramování to je v Česku "normální".
termit256
Příspěvky: 10029
Registrován: 06 pro 2007, 00:00

#7 Příspěvek od termit256 »

Co je to za vyraz "zakodoval program" :-) ? To jsi slysel v nejakem serialu na Nove?

Ja zadne projekty ani "algoritmy programu" nezakodovavam, ale na ty nuly proste vzdycky zapomenu. Tech par radku na jejich vymazani dopisu az je uvidim na displeji.
Uživatelský avatar
lesana87
Příspěvky: 4395
Registrován: 20 zář 2014, 00:00

#8 Příspěvek od lesana87 »

Když se použije pro převod/zobrazování čísel algoritmus dělení deseti (obecně základem č. soustavy) dokud není podíl 0, problém s nevýznamnými nulami nevzniká.
Uživatelský avatar
Osmdesat
Příspěvky: 1537
Registrován: 19 led 2016, 00:00
Bydliště: Liberecko

#9 Příspěvek od Osmdesat »

Jak píše lesana, v cyklu děl číslo deseti, podíl schovej pro další dělení, zbytek vždy vem a přičti k němu ASCII hodnotu znaku "0" a "předpoj" k výstupnímu řetězci. Jakmile je podíl 0, skonči. Pokud chceš zarovnávat napravo, vpisuj číslice do předpřipraveného řetězce pevné délky vyplněného mezerami.
Uživatelský avatar
rnbw
Příspěvky: 37414
Registrován: 21 bře 2006, 00:00
Bydliště: Bratislava

#10 Příspěvek od rnbw »

No ak ten procesor nema instrukciu delenia...
Vkladanie znakov na zaciatok retazca nie je uplne jednoducha operacia.

Pridal by som tam nejaky flag - na zaciatku vynulovat. Pokym nie je nastaveny, namiesto nuly generovat medzery. Pri nenulovom cisle ho nastavit.
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#11 Příspěvek od ZdenekHQ »

Ovšem pokud procesor má instrukci dělení, je dělení 10 pro n-bytové číslo víceméně triviální záležitost na pár řádků. Zbytek po dělení se přes push uloží do stacku, načež se pozpátku vyzvedne a dokud jsou nuly, zobrazuje se mezera. První nenulové číslo nastaví flag a pak už se nuly zobrazují, nesmí se ale zapomenout na poslední místo, kde už se nula musí zobrazit, pokud je číslo nulové.

Dá se tam i přihodit desetinná tečka (fakt nemám rád čárku) a podobné operace...
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
petula
Příspěvky: 828
Registrován: 22 kvě 2016, 00:00
Bydliště: Čelákovice / Brandýs n.L / Stará Boleslav
Kontaktovat uživatele:

#12 Příspěvek od petula »

tady jsou dva podprogramy, které normálně používám. První je pro integer 16-místné číslo a druhý pro real 16-místné číslo. V real číslu se musí detekovat desetinná tečka, aby se nemazaly nuly v případě hodnoty 0.00.
Princip dekodování vychází z hardwarového řazení obvodů 7447, které zháší nevýznamné nuly hardwarově.

pro 16 mistny integer:

sub leadzero [P]
for i=15 to 1 step -1; if P[i]=0; sf[i]; ascii(127)->P[i]; ret[P];
cf[i]; next; ret[P];
endsub;

pro 16 mistny real:

sub leadzero [P]
for i=15 to 1 step -1; if P[i]="."; ret[P];
if P[i]=0; sf[i]; ascii(127)->P[i]; ret[P];
cf[i]; next; ret[P];
endsub;


v assembleru p-proměnných 1 podprogram vypadá takto:

cyci{0f};dec i;eqz{P[i]};1->f{i};00h->{P[i]};rtn{P[i]};
0->f{i};rtcy-1;rtn{P[i]};


2. podprogram se liší pouze tím, že se detekuje desetinná tečka, tedy příkazy

....
eq{P[i]}=00101110b;0->f[i];00h->{P[i]};rtn{P[i]};
0->f{i};rtcy-1;rtn{P[i]};
Uživatelský avatar
Mahoney
Příspěvky: 759
Registrován: 26 říj 2019, 00:00

#13 Příspěvek od Mahoney »

termit256 píše:Az to cislo budes mit prevedene do ascii proste kontroluj zleva jednotlive cislice a pokud to bude nula, nahrad ji mezerou. Pokud to bude jine cislo nez nula, ukonci kontrolu. Nevim v cem vidis problem.


Jde to ještě jednodušeji, není potřeba žádných kontrol ani jiných algoritmů. Prostě při úvodní inicializaci naplní proměnné pro displej (kromě řádu jednotek) místo nulami prázdným znakem, to je celé (tedy za předpokladu, že začíná od nul, tedy pokud např. nenačítá poslední použitou hodnotu z EEPROM a podobně, a taky za předpokladu, že s proměnnými pro displej neprovádí výpočty, např. inkrementaci, ale jen do nich zapisuje hodnotu).

V jednom programu jsem to řešil ještě jinak - prostě jsem nespínal tranzistory pro ovládání segmentovek, a to za podmínky "dokud není poprvé použito", tedy zařídil jsem si na to flag registr (což lze, protože první číslo "k použití" nikdy není nula, a to i když se s těmi registry provádí nějaká operace typu INC apod - tedy samozřejmě zase kromě řádu jednotek, na něj jsem tu podmínku prostě neuplaňoval vůbec).
termit256
Příspěvky: 10029
Registrován: 06 pro 2007, 00:00

#14 Příspěvek od termit256 »

Pokud to tak udelas, bude ti cislo pri obnovovani blikat. Ten algoritmus neni nijak slozity, je to par radku kodu.
Ja mam napsane podprogramy pro prevod do bcd, ascii a vymazani tech nul a jednoduse pouziju bez vetsiho premejsleni ty ktere zrovna potrebuju pro danou aplikaci. Ctrl+c, ctrl+v je mnohem rychlejsi nez to psat pro kazdou znovu jako soucast jedineho procesu zobrazovani.
Uživatelský avatar
lesana87
Příspěvky: 4395
Registrován: 20 zář 2014, 00:00

#15 Příspěvek od lesana87 »

ZdenekHQ píše:Ovšem pokud procesor má instrukci dělení, je dělení 10 pro n-bytové číslo víceméně trviální záležitost na pár řádků.

To by mě docela zajímalo, nikdy mě žádné triviální řešení nenapadlo.
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“