home | area personale         schemi | tutorial | robotica | pic micro | recensioni         forum | chat irc         faq | contatti         store | Ordina PCB
username
password
cerca

 
FORUM: Pic Micro
Tutto quanto riguarda questi microprocessori... progetti, suggerimenti, aiuti, discussioni...ecc


PORTA analogica in PIC16F873A
     
Autore Messaggio opzioni
picmicro675




una ogni 10 livelli


postato il:
05.09.2018, alle ore 15:56
Mi piace !
Il concetto di milli_time è come quello di Arducoso. Una variabile che si incrementa in modo trasparente al ciclo principale. Da questo si usano dei calcoli per determinare il periodo trascorso.
Ora se mi metti altre 2 variabili da 32 bit hai qualche rallentamento che non si giustifica se alla fine non usi 4 miliardi di millisecondi di pausa. Converrebbe una misura a sufficienza per il periodo voluto. Ma il tuo ragionamento segue un altro percorso. Dovresti scegliere se prendere una variabile a cui tutti si riferiranno (come da esperienza di Arduino) oppure prendere una variabile per ogni singolo evento da temporizzare.
Quali di queste due varianti determina una soluzione ottimale?
Mi immagino quando ne hai 10 in ISR, forse diventa oneroso. Non è detto che fare in calcolo fuori ISR sia migliore, ma da considerare che conviene una ISR breve ed efficiente.
Il sorgente (non verificato) di seguito dimostra le due varianti. Del resto si calcola l' incremento di 4 bites.
#define LED1 PORTC.7
#define LED2 PORTC.6
#define u32 unsigned long
#define u16 unsigned int
#define u8  unsigned char
#define FIRST_MODE                      // definizione del metodo utilizzato

#ifdef FIRST_MODE                       // variabile di contatore unica
u32 milli_time = 0;
#else
u16 last_time;                          // variabile unica per ogni evento
u16 next_time;
#endif
INTCON.T0IE = true;
INTCON.GIE = true;
TRISA = 0;
PORTA = 0;
// calcolo ricavato da http://eng-serve.com/pic/pic_timer.html
//Timer0 Registers Prescaler= 64 - TMR0 Preset = 178 - Freq = 1001.60 Hz
// Period = 0.000998 seconds
// bit 5  TMR0 Clock Source Select bit...0 = Internal Clock (CLKO)
OPTION_REG.T0CS = 0;
//1 = Transition on T0CKI pin
// bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
OPTION_REG.T0SE = 0;
// bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
OPTION_REG.PSA = 0;
OPTION_REG.PS2 = 1;   // bits 2-0  PS2:PS0: Prescaler Rate Select bits
OPTION_REG.PS1 = 0;
OPTION_REG.PS0 = 1;
TMR0 = 178;             // preset for timer register

void delay(long time)
{
    long mytime = milli_time + time;
    while (mytime <= milli_time) {};
}

#ifdef FIRST_MODE
void ISR interrupt()
{
    if (T0IF) {
        ++milli_time;
        TMR0 = 178;
        T0IF = false;
    }
}

void main ()
{
    // variabili locali
    u16 last_time;
    u16 next_time;
    while (1) {
        // controllo che se la differenza di conteggio e` superiore
        if ((milli_time - last_time) >= 2000) {
            // allora interviene l' operazione
            LED1 = !LED1;
            // riaggiorno per il ciclo successivo
            last_time = milli_time;
        }
        // come quello sopra.
        if ((milli_time - next_time) >= 700) {
            LED1 = !LED1;
            next_time = milli_time;
        }
    }
}
#else
void ISR interrupt()
{
    if (T0IF) {
        ++last_time;
        ++next_time;
        TMR0 = 178;
        T0IF = false;
    }
}

void main ()
{
    // variabili locali
    while (1) {
        // controllo che se la differenza di conteggio e` superiore
        if (last_time >= 2000) {
            // allora interviene l' operazione
            LED1 = !LED1;
            // riaggiorno per il ciclo successivo
            last_time = 0;
        }
        // come quello sopra.
        if (next_time >= 700) {
            LED1 = !LED1;
            next_time = 0;
        }
    }
}
#endif

Le istruzioni del preprocessore, permettono una compilazione condizionale determinata dalla definizione FIRST_MODE. Se non esistesse allora si compilerà la seconda parte del sorgente contenuto tra #else e #endif
Da notare che un 16FF873A permette il debug in hardware. Se hai un pickit3 dovresti avere tale opzione, giusto da configurare i micro per lo scopo. Questo per dire che potresti verificare coi breakpoints i valori delle variabili o il loro contenuto in memoria.

Così fatto, non devi preoccuparti che l'evento avvenga con ritardi. Neppure dover verificare quanti cicli macchina passano. I timer0 scandisce i periodi in modo corretto.
Come è scritto, dovrebbe succedere che il ciclo principale si ripete all' incirca in 40 istruzioni (ad un microsecondo per istruzione). E di fatto il resto non fa nulla che lo impegni in un ciclo bloccante. Addirittura se l' evento non combina c'è solo la comparazione del tempo con il valore scelto. Ma per certezza lo puoi anche mettere a visualizzare all' oscilloscopio, quando termina il ciclo di while.

NOTA, vedo che di solito si usa una indentazione di 2 caratteri e per me non sembra sufficientemente visibile. Forse non esiste una regola che normalizzi come viene scritto un sorgente. A volte porta a difficoltà di lettura con solo 2 caratteri.
Poi se XC8 è una ciofega, perché non passare a mikroC?
Ha solo il limite di 2 kilowords di programma, versione free.

Il passo successivo sarebbe di aggiornare il display ogni secondo oppure a secondo se un evento ne determina la necessità di aggiornamento. Per quello si può usare un flag (che deve consumare solo un bit)



Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675




una ogni 10 livelli


postato il:
05.09.2018, alle ore 16:08
agric:
il tmr0 prosegue il suo compito.


Infatti una volta ricaricato il valore nuovo si incrementa di uno ad ogni ciclo macchina.

Del resto potrebbe aver raggiunto qualche decina quando esce dalla ISR.
Per questo si assume che la ISR deve durare il meno possibile, quando i tempi di interrupt sono frequenti. Altrimenti non sarebbe in grado di dare spazio al resto del programma.
Ovviamente con 1 millisecondo ci stanno 1000 istruzioni (qualcuna in meno), che possono essere fatte fuori da ISR.
Se invece si determina che è necessaria una cadenza più lasca, ben venga che l' ISR diventa meno disturbante sul resto del programma. Sono considerazioni da valutare a secondo delle necessità di impiego del micro.
Vista la AN736, che prevede la possibilità di asservire 12 dispositivi su I2C, penso che 5 sia fattibile. Dato che la frequenza è più bassa di 2 volte e mezza. Poi magari si valuta che gli eventi non sono così ricorrenti quindi la base di interrogazione potrebbe anche non essere i 100 millisecondi della AN736 ma qualcosa come il doppio.



Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675




una ogni 10 livelli


postato il:
05.09.2018, alle ore 16:18
Ah! per esempio io preferisco una cadenza ogni 10 millisecondi, la quale impiega solo un ciclo macchina per aggiornare il conteggio. Infatti risulta solo di 99.



Anno nuovo, forum nuovo.
Mi sa che lascio.
agric





postato il:
05.09.2018, alle ore 17:09
picmicro675:
agric:
il tmr0 prosegue il suo compito.


Infatti una volta ricaricato il valore nuovo si incrementa di uno ad ogni ciclo macchina.
...


...in base all'impostazione del prescaler.



meglio essere un granello di pepe che una cacca d'asino
e.ferriani





postato il:
05.09.2018, alle ore 19:21
Questa è l'interrupt in assembler. E' una modifica del programma che ho messo prima, con una sola variabile incrementata e, come suggerito, il settaggio del timer prima di tutto.
Spero che Grix lo metta in ordine correttamente.

Quanti cicli macchina sono?




  1245  0060                     ;MASTER_T4_1_Interrupt_Interrupts.c: 34:   if (T0IF)
  1246                            btfss (90/8),(90)&7 ;volatile
  1247  0060  1D0B                goto u7_21
  1248  0061  2863                goto u7_20
  1249  0062  2864               u7_21:
  1250  0063                      goto i1l171
  1251  0063  286C               u7_20:
  1252  0064                      line 49
  1253                           
  1254                           i1l836:
  1255  0064                     ;MASTER_T4_1_Interrupt_Interrupts.c: 35:   {;MASTER_T4_1_Interrupt_Interrupts.c: 49:    
                                  TMR0 = 195;
  1256                            movlw low(0C3h)
  1257  0064  30C3                movwf (1) ;volatile
  1258  0065  0081                line 54
  1259                           
  1260                           i1l838:
  1261  0066                     ;MASTER_T4_1_Interrupt_Interrupts.c: 54:     milli_sec++;
  1262                            movlw low(01h)
  1263  0066  3001                movwf (??_ISR+0)+0
  1264  0067  00B1                movf (??_ISR+0)+0,w
  1265  0068  0831                addwf (_milli_sec),f
  1266  0069  07AF                line 58
  1267                           
  1268                           i1l840:
  1269  006A                     ;MASTER_T4_1_Interrupt_Interrupts.c: 58:     T0IF=0;
  1270                            bcf (90/8),(90)&7 ;volatile
  1271  006A  110B                goto i1l171
  1272  006B  286C                line 59
  1273                           ;MASTER_T4_1_Interrupt_Interrupts.c: 59:   }




Enea Ferriani
agric





postato il:
05.09.2018, alle ore 20:42
Secondo me è incompleto dov'è l'etichetta i11171


meglio essere un granello di pepe che una cacca d'asino
agric





postato il:
05.09.2018, alle ore 21:22
Se non sbaglio 12 fino all'ultimo goto i11171


meglio essere un granello di pepe che una cacca d'asino
picmicro675




una ogni 10 livelli


postato il:
06.09.2018, alle ore 08:17
A ma salta l' occhio ad un goto u7_21, anziché un salto diretto a goto i1l171. Ma questo è comprensibile dato che sono costrutti automatizzati il quale il primo passaggio definisce il salto fuori dallo stato condizionale ed il secondo viene scoperto quando sono stati calcolati il totale dei bytes allocati.
Secondo difetto, non calcola l' incremento di una long. Come è scritto è al quanto criptico capire l' esatta operazione che sta svolgendo.
Ho fatto un lavoro di conversione dei listati della AN736.
http://www.grix.it/UserFiles/picmicro675/File/TransitFiles/A…

Quei files che terminano in s sono riferiti allo slave, mentre quelli che terminano in m sono definiti per il master.
Ora ci saranno buoni spunti di studio che danno una idea come si può gestire in modo ordinato un certo numero di eventi. Ovvio che l' application note ha uno scopo leggermente diverso.
Rimane comunque un valido esempio per impostare come fa dialogare tra diversi circuiti integrati. Forse meno interessante quello di collegare una seriale.

Altro compilatore valido
http://www.sourceboost.com/Products/BoostC/BuyLicense/Licens…
Già con 70 USD hai un versione Full, manca solo il supporto per le librerie. Comparato ai 995 di microchip..... Oppure i 249 di mikroE
https://www.mikroe.com/mikroc-pic
Comunque ha le librerie, sebbene Boost lo da per 149 $

Tanto per avere un compilatore che fa il suo lavoro senza aggiunger trucchi.



Anno nuovo, forum nuovo.
Mi sa che lascio.
agric





postato il:
06.09.2018, alle ore 10:22
picmicro675:
A ma salta l' occhio ad un goto u7_21, anziché un salto diretto a goto i1l171. Ma questo è comprensibile dato che sono costrutti automatizzati il quale il primo passaggio definisce il salto fuori dallo stato condizionale ed il secondo viene scoperto quando sono stati calcolati il totale dei bytes allocati.
Secondo difetto, non calcola l' incremento di una long. Come è scritto è al quanto criptico capire l' esatta operazione che sta svolgendo.
.


la domanda
e.ferriani:
Quanti cicli macchina sono?


Credo di aver risposto per il codice cosi com'è, per quello che si vede con ottimizzazione del piffero, con tutta probabilità la goto i11171 prosegue con la chiusura dell'isr ripristinando i vari registri.

La parte da ottimizzare cmq è solo questa e a mio avviso in questo modo

;MASTER_T4_1_Interrupt_Interrupts.c: 34:   if (T0IF)
                              btfss (90/8),(90)&7 ;volatile 
                 goto i1l171  // TOIF =0  esco da isr 

Btfss = Bit Test Flag Skip Set
tradotto - se TOIF = 1 salta (skip) l'istruzione successiva altrimenti eseguo la goto i11171 ed esco dall'isr senza incrementare nulla perchè l'interrupt non era del timer0.

per quanto riguarda l'incremento della long l'operazione è criptata dal software.
E forse Enea ha cambiato la LONG con INT



meglio essere un granello di pepe che una cacca d'asino
e.ferriani





postato il:
06.09.2018, alle ore 10:49
Visto quanto mi fa arrabbiare la combinazione MPLABX5.05 e XC8v2.00 non mi meraviglierei se ci fossero dei bugs da qualche parte.
Confermo che anche al mio collega firmwarista usando questa combinazione la compilazione si blocca. Negli output sembra che vada a cercare picc nella cartella avr.
Lo stesso progetto compilato con MPLABX4 e XC8v2.00 funziona.

Agric, non credo dfi aver fatto quello che dici. Se ricordo bene i due LED1 e LED2 erano LONG è sempre stati LONG.



Enea Ferriani
segui questo thread con grixFC, per questa funzione devi aver installato il software grixFC

torna su
     

Come utente anonimo puoi leggere il contenuto di questo forum ma per aprire una discussione
o per partecipare ad una discussione esistente devi essere registrato ed accedere al sito




 







 
 
indietro | homepage | torna su copyright © 2004/2024 GRIX.IT - La community dell'elettronica Amatoriale