Il giorno Wed, 18 Jul 2007 19:36:18 +0200, Artemis ha scritto:
Subroutines e macro sono due cose diverse, e i programmatori le usano in base alle diverse esigenze.
Comunque in genere usare subroutines invece di macro mantiene il codice più compatto ma richiede uno stack più profondo e più perizia a passare i parametri.
Stai facendo un gran casino inutilmente, ti ho postato dei link sugli altri post dove ci sono delle routine a 16 bits e oltre, il fatto che un µC sia ad 8 bits non significa affatto che non possa eseguire calcoli complessi.
Si lo so, ho utilizzato appositamente i 2 termini diverse, per dire che ho scritto delle call "perché" non so usare le macro. Mi ricordo che erano molto molto comode in masm, ma nel micro non so usarle.
post
Ho spulciato negli altri post ma c'è il link solo del datasheet, che possiedo anche io.
Questo è interessante, se solo facessero un esempio pratico sarebbe l'ideale. Ad esempio, nella conversione 16bit binary to 5 digit BCD, scrive:
clr bytelow clr bytemid clr bytehigh
lsl loopl brcs con_carry lsl looph rjmp avanti
con_carry: lsl looph inc looph
Shift left carry into result byte 1. E qui?
Shift left carry into result byte 2 (most significant digit). E qui?
e mi viene già da solo quel famoso 0x100 dell'altra volta. Quindi devo correggere con (lo faccio simbolico, so che sono registri interni e non posso fare operazioni dirette):
push TCNT1H push ICR1H sub TCNT1H, ICR1H pop ICR1H pop TCNT1H sbc TCNT1H, ICR1H
push TCNT1L push ICR1L sub TCNT1L, ICR1L pop ICR1L pop TCNT1L sbc TCNT1H, ICR1L
Dammi una conferma...
Giusto!!! Non ci avevo pensato che se il segnale è già in ON l'interrupt non lo vede perché è impostato sul "fronte" di salita.
Good!!!
Grazie mille!!!
Il computer trip è quasi pronto, devo però affrontare ancora qualche parte spinosa (devo terminarlo entro oggi pomeriggio!):
Il giorno Thu, 19 Jul 2007 10:56:02 +0200, Artemis ha scritto:
E' la stessa cosa che in masm, devi solo usare la sintassi giusta che sicuramente c'è nell'help dell'assembler
Mi prendi in giro?
Questo sito si chiama "The AVR Assembler Site" e ci sono decine di routines già fatte in assembly, basta saper usare il copia-incolla.
formatting link
Nell'altro link puoi scaricare direttamente il sorgente in .asm per AvrStudio
formatting link
con gli esempi di uso.
Queste routines vanno, ti consiglio di usarle così come sono.
Non ho intenzione di spiegartele riga per riga, una spiegazione la da già il doc0938.pdf, ed è sufficiente. Se hai delle difficoltà con una sottrazione a 16 bit figuriamoci con una conversione BCD-BIN, ci vorrebbero per la spiegazione 10 post come minino e non ho il tempo nè la voglia.
Comunque ti consiglio di usare queste per l'aritmetica a 16 bits:
formatting link
con i sorgenti .asm
formatting link
Funzionano, al massimo devi aggiungere qualche PUSH e POP dei registri usati.
Mmm... a questo proprio non avevo pensato sai? Però il Salta se maggiore o uguale è Signed, non vorrei che l'ultimo bit venisse considerato come bit di segno e dunque il numero 244 non fosse più tale nei confronti.
Tipo, se in alcuni registri alti, riesco a fare:
ldi ax, 16
mi dà errore anche: ldi bx, 16
mi dà anche errore: ld ax, bx (bx registro dei primi 15)
ma non mi da errore: mov ax, bx
mi da errore: mov bx, 16
e poi questo compilatore non è neppure il massimo, racchiude TUUUUUUTTI gli errori in: "Illegal argument or count"
qualunque errore (tranne proprio quelli terra terra) dà questo messaggio.
Bisogna capire a che indirizzo comincia la ram, come poterle chiamare con un certo nome (non penso di dover usare indirizzi al posto di alias...)
Ce ne sono decine e decine, ma se non sai come passare dalla porta della stanza, non puoi sapere come si usa il computer che c'è dietro :)
No, è che hai fatto riferimento ai link degli altri post che ho letto dopo quello nel quale ti ho risposto. Nei post precedenti non c'era questo indirizzo, c'era un solo link ed era quello del datasheet.
Ci proverò!
Forse non per un ignorante come me :)
Ho difficoltà con il linguaggio di programmazione, se guardi le domande sono molto simili (sottrazione con carry, registri che non vanno, gli interrupt e i timer/counter etc.)
Quella che ho postato non poteva funzionare, infatti ho implementato la tua soluzione prima che scrivessi il post. Solo che nella mia soluzione non c'è la parte dell'Rcpl.
Questa parte dell'Rcpl che hai scritto falsa il risultato:
0012 - FF12 = 100 (risultato corretto)
Seguendo la tua soluzione viene fuori:
0012 - FF12 = FEFF
a me serve il risultato in valore assoluto, perché siccome il timer dell'interrupt capture non si ferma mai, può capitare la misura attuale sia inferiore alla precedente poiché il timer ha raggiunto il suo limite e si è azzerato.
Sì, hai ragione, non c'è bisogno di complementare il risultato, il bello di lavorare in complemento a 2 è proprio questo, il wrap-around viene da se senza preoccuparsene :-)
Esiste anche quello senza segno se non ricordo male.
Queste sono le basi dello sviluppo, prima di fare un'applicazione tutto sommato complessa come la tua queste cose dovrebbero essere stra-stra-stra chiare ed assodate.
E' come se stessi costruendo una casa e, al momento di fare il tetto, chiedessi: ma come si impasta il cemento? Come si usa la mestola? Mi chiedo come hai fatto ad arrivare fino a qui :-)
Forse sei partito troppo presto a spippolare senza aver ben compreso il datasheet e l'instruction set.
E' un progetto per un corso di soli 4 crediti, però a me sembra di fare una tesi, 20 giorni per costruire il circuito funzionante, smontare l'iniettore della macchina e fare 8 ore di caratterizzazione. Inoltre il micro è imposto dal corso, magari esistono micro più specifici, con registri a 16, molti int e timer e istruzioni float.
Quando ti ci fissi e stai fino alle 5 del mattino per 3 giorni, qualcosa ne viene sempre fuori :) Poi la passione c'è, quindi... Comunque sembra che funzioni, almeno finora va alla grande. Mancano le ultime parti.
Purtroppo il datasheet dal canto mio lascia un pò a desiderare, dà molte cose per scontato.
Diciamo che queste esperienze tour de force insegnano molto più di un intero corso. Ti ammazzano il cervello, però quello che fai puoi star tranquillo che ti rimane impresso, perché ricordi fisicamente le limitazioni che hai incontrato durante il tragitto. E' un pò come fare l'apprendista meccanico, quello che impari giorno dopo giorno lo impari e rimane. Quello che invece impari di teorico all'università, in 2 mesetti di corso, pur studiando tutti i giorni, dopo poco svanisce, la pratica invece rimane sempre... è come andare in bicicletta (a buon intenditor ;)
esempio di fixed point su 8 bit 4 prima della virgola 4 dopo
1,0 0001.0000
2,0 0010.0000
+
3,0 0011.0000 come vedi la presenza del punto decimale non cambia il funzionamento della somma ( e della differenza 9 la moltiplicazione da fare 8bit x 8 bit -> 16 bit richiede una normalizzazione ovvero ti tocca shiftare a destra il risultato di 4 bit, il a destra della virgola.
2,0 0010.0000
3,5 0011.1000
0000-0111-0000-0000 le parte piu' a sinistra e a destra si eliminano
7.0 0111.000
questa operazione puo' essere realizzata in maniera 'virtuale' aggiustando opportunamente l'algoritmo della moltiplicazione e salvando solo le parti necessaria
analoghe considerazioni valgono per qualsiasi combinazione di numeri di bit totali e numeri di bit a destra della virgola:
16 bit 8 + 8
16 bit 12 + 4
la divisione e' analoga alla moltiplicazione con uno shift a sinitstra pero'.
l'algoritmo di conversione da binario a BCD si modifica cosi: la parte intera ( a sinstra della virgola ) va gestita con le divisioni per 10 successive la parte decimale ( a destra della virgola ) va gestita con MOLTIPLICAZIONI per 10 successive
ma tu ci metti anche una robusta resistenza in serie ?
-VCC | D
---[RRR]---+-----ALL'ingresso logico ( CMOS ) D | -GND
vedi che questa struttura non interferisce con quello che sta a monte
per questo dico di usare diodi esterni che sono piu' robusti dei diodi presenti nei chip, la resistenza in serie provvede poi all' "isolamento"
a parte che gl'impulsi per la velocita' sono abbastanza lenti da poter essere contati con glì'interrupt
qui hai gia' trovato la risposta
pero'affrontando un progetto avresti dovuto:
1) documentati BENE sul micro scelto leggendo datasheet e user manual UFFICIALI e non sentiti dire su questo o quel sito ( velato rierimento al numero di timer presenti :-) )
1a) sia per l'hardware
1b) sia per il linguaggio macchina
1c) sia sul modello di programmazione ( registri, flags, ram ... )
2) documentarti sulle potenzialita' del sistema di sviluppo ( uso e sintassi dell'assemblatore, simulatore ... )
3) mettere a punto un minimo di tecniche di programmazione specifiche di quel micro, mi suona molto male una persona che non sappia come si fanno le addizioni multibyte :-) o che non sappia come gestire variabili al di fuori dei registri
4) documentarti su tecniche di programmazione un po' ( ma poco ) piu' avanzate
francamente da come ti sei mosso mi sembra che questa fase preparatoria sia stata un po' trascurata
E' la soluzione che sto per implementare, ci ho pensato stamattina. Solo che ha un'altra limitazione:
se uso come base dei tempi 1 s, la risoluzione è 10.8 km/h, quindi potrò avere un impulso a 10.8 km/h, due impulsi a 21.6 km/h etc.
mentre con una base dei tempi di 2 secondi, ottengo una risoluzione di
5.4 km/h, solo che il tempo di refresh è più lento ed è lo svantaggio.
Se refresho ad un secondo e conto 2 secondi per trovare lo spazio, camminando a 17 km/h avrò questi valori sul display:
10.8 km/h, 16.2 km/h, 10.8 km/h, 16.2 km/h
se scendo sotto i 16.2 km/h ottengo sempre 10.8 km/h. Peggio ancora se cammino verso i 21 km/h:
10.8 km/h, 16.2 km/h, 10.8 km/h, 16.2 km/h
totalmente errata la misura, quindi lo sarà anche il consumo se considero non la velocità ma solo gli impulsi. Supponiamo che ad 1.1 s scatti il secondo impulso, la benzina finora consumata sarà rapportata ad uno spazio di 3 metri anziché 6. Quindi più benzina meno strada. Il secondo successivo avviene l'opposto, ovvero la benzina di un secondo e
2 impulsi, il precedente e l'attuale. Più spazio meno benzina, rendimento alto ma errato.
E' un bel problema questo... infatti mi sto lambiccando per una soluzione safe.
Il giorno Thu, 19 Jul 2007 13:15:23 +0200, Artemis ha scritto:
Sono d'accordo, fare un progetto del genere significa incontrare molte delle problematiche dei µC che una volta apprese ti consentiranno di fare anche cose + complesse, ci vuole solo della pazienza e non bisogna scoraggiarsi quando qualcosa non va ma si deve cercare di capire il perchè.
E quello che conta è il metodo, leggere e imparare il datasheet è fondamentale, io ho utilizzato AtMega8535 nel 2004 ma ricordavo che aveva 3 timers.
Sono del parere che il detto "val più la pratica delle garammatica" è sempre validissimo.
A suo tempo ho scelto quello essenzialmente perchè consentiva l'assembler condizionale quando AVR Studio non l'aveva.
In più ci sono assembler e linker e puoi scomporre il programma in diversi moduli .ASM assemblarli e linkarli successivamente, cosa molto comoda in progetti complessi.
Considera che io in questo modo ho riutilizzato dei software scritti in ASM per Z80 parecchi anni fa sugli AVR facendo delle macro di simulazione delle istruzioni, se ti interessa ne ho parlato qui:
formatting link
formatting link
Inoltre gli obj si possono linkare anche con dei compilati C, ma qui la cosa si complica un pò e ci vuole un compilatore C IAR che non è free.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.