Impostare la word di configurazione e il clock per i pic a 16bit (dsPic/Pic24)

Giovanni Bernardo | 14 settembre 2010
Categorie: dsPIC / PIC24

Vediamo in questo articolo come impostare le word di configurazione per i dsPic33 e per i pic24F. Anche se vi interessa soltanto la configurazione dell’una o dell’altra tipologia di pic a 16 bit è bene che leggiate l’articolo per intero dal momento che le cose in comune (molte a dire il vero) le esporrò una volta sola. Non dimentichiamoci, difatti, che ciò che viene detto per i pic24  vale anche per i dsPic: i dsPic, difatti, non sono nien’altro che Pic24 con un core DSP, anche se alcune piccole cose possono variare a seconda delle funzioni specifiche sull’uno o l’altro modello di pic e deducibili dal datasheet relativo. Questa quindi è solo un’infarinatura di base per capire in che modo, con quali funzioni, si settano le word di configurazione per i pic a 16bit.

Configurazione dsPic33

Prenderò ad esempio i registri di configurazione del dsPIC33FJ128GP802. Andiamo quindi subito nel datasheet, come sempre alla voce “Special Features \ Configuration bits” e vediamo un po’ cosa abbiamo di fronte:

Vediamo che si tratta di parecchi registri ad 8 bit (forse gli unici!). Le impostazioni di configurazione per i dsPic, facendo uso del C30, vengono settate  utilizzando funzioni che hanno lo stesso nome del registro da impostare, preceduto da un underscore. Per impostare il registro FOSCSEL, ad esempio, basterà utilizzare la funzione :

_FOSCSEL(x);

nella quale la x verrà sostituita dal valore da assegnare al registro, o meglio: dai nomi mnemonici che è possibile trovare come sempre nel file header del pic interessato. Nel mio caso, dato che sto usando un dsPIC33FJ128GP802, il file header da cui prendere le informazioni  è p33FJ128GP802.h.

I file header dei pic a 16 bit si trovano di default nella cartella creata dall’installazione del C30:

C:\Programmi\Microchip\MPLAB C30\support\

gli header dei dsPic33 si troveranno quindi nella sottocartella:

\dsPIC33F\h

e quelli dei pic24F in:

\PIC24F\h

e così via per le altre famiglie. Non illustrerò la configurazione di tutti i registri ma solo di quelli principali, normalmente utilizzati per scopi didattici, gli altri possono essere lasciati ai valori di default. D’altronde la trattazione su tutte le funzionalità sarebbe un’impresa davvero ardua.

Registro di configurazione FOSCSEL

Viene utilizzato per selezionare la sorgente di clock del pic. Vediamo quali bit possiamo settare:

Bit IESO – Two-speed Oscillator Start-up Enable bit.  Possibili valori:

IESO_ON = Avvia il pic con l’oscillatore interno FRC (Fast RC) e in automatico passa all’oscillatore da noi selezionato una volta che questo è pronto.
IESO_OFF = Avvia il pic direttamente con l’oscillatore da noi selezionato.

Bits FNOSC – Initial Oscillator Source Selection bits. Serve a selezionare il tipo di oscillatore utilizzato dal momento che sui pic a 16 bit esistono varie sorgenti di clock che possono essere scambiate tra loro anche a runtime.  E’ possibile difatti  far funzionare il pic con:

  • oscillatore esterno primario (quarzo XT, quarzo HS o ancora: oscillatore esterno – EC) collegato ai pin OSC1 e OSC2
  • oscillatore esterno secondario. Pensato per un utilizzo a basso consumo e per un quarzo da 32768Hz da collegare ai pin SOSCI e SOSCO
  • oscillatore interno FRC (Fast RC) a 7.37MHz
  • oscillatore interno LPRC (Low Power RC) funzionante a 32768Hz

Possibili valori:

FNOSC_PRI = Oscillatore primario (XT, HS, EC)
FNOSC_PRIPLL = Oscillatore primario (XT, HS, EC) con PLL
FNOSC_SOSC
= Oscillatore secondario (LP – a bassa potenza)
FNOSC_FRC
= Oscillatore interno Fast RC
FNOSC_FRCPLL = Oscillatore interno Fast RC (FRC) con PLL
FNOSC_FRCDIV16
= Oscillatore interno Fast RC con divisione fissa per 16
FNOSC_LPRC
= Oscillatore interno LPRC
FNOSC_LPRCDIVN
= Oscillatore interno LPRC con divisione impostabile per N (vedremo dopo come)

Esempio di settaggio del registro FOSCSEL:

_FOSCSEL(IESO_OFF & FNOSC_PRIPLL); // avvio direttamente con oscillatore primario + PLL

Registro di configurazione FOSC

Serve ad impostare la modalità di funzionamento dell’oscillatore.

Bit FCKSM –  Clock Switching Mode bits

Il clock switching è una funzione che permette di cambiare la sorgente di clock anche con programma in esecuzione (possiamo passare dal clock primario a quello secondario ad esempio per ridurre i consumi o in caso di malfunzionamenti). In aggiunta, come anche su altri pic ad 8 bit, abbiamo anche il fail-safe clock monitor che è un sistema di monitoraggio di malfunzionamenti del clock primario. Possibili valori:

FCKSM_CSDCMD = funzione di clock switching disabilitata
FCKSM_CSECMD = abilitata solo la funzione di clock switching
FCKSM_CSECME = abilitate sia la funzione di clock switching che la funzione di fails safe clock monitor

Bit IOL1WAY – Single configuration for remappable I/O

Come abbiamo visto in un articolo precedente, è possibile rimappare su alcuni pin determinate periferiche (funzione PPS – Peripheral Pin Select). Esiste una funzione di sicurezza, aggiuntiva, che ci permette di eseguire una sola volta questa operazione (non una sola volta nella vita ma una sola volta per reset!), gestita appunto da tale bit. Possibili valori:

IOL1WAY_ON : è possibile eseguire una sola volta la funzione di remapping
IOL1WAY_OFF : è possibile eseguire più volte la funzione di remapping

In pratica, se tale bit è abilitato, permette un’unica scrittura, per reset, nei registri RPINRx and RPORx utilizzati per il pin remapping. Bisogna sempre e comunque effettuare lo sblocco come già spiegato.

bit OSCIOFNC – OSC2 Pin Function bit.  Tale impostazione non è applicabile se si utilizza l’oscillatore in modalità XT o HS in quanto il pin OSC2 è appunto occupato dal quarzo, torna utile nel caso di utilizzo di un oscillatore esterno. Possibili valori:

OSCIOFNC_ON : Il pin OSC2 può essere usato come normale I/O
OSCIOFNC_OFF : Il pin OSC2 è usato come uscita del clock

Bits POSCMD – Primary Oscillator Mode Select bits. Serve a selezionare il tipo di oscillatore primario. Possibili valori:

POSCMD_EC : modalità External Clock (oscillatore esterno sul pin OSC1)
POSCMD_XT : modalità con quarzo XT (quarzo da 3 a 10MHz)
POSCMD_HS : modalità con quarzo HS (quarzo da 10 a 40MHz)
POSCMD_NONE : oscillatore primario non usato

Esempio di settaggio del registro FOSC:

// FCKSM_CSDCMD : funzione clock switching disattivata
// IOL1WAY_OFF : è possibile effettuare più di una volta le funzioni di remapping
// OSCIOFNC_OFF : il pin OSC2 è utilizzato normalmente come uscita del clock
// POSCMD_XT : stiamo usando un quarzo con un valore da 3 a 10MHz
_FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT);

Registro di configurazione FWDT

Serve ad impostare il funzionamento del WatchDog Timer. Personalmente non utilizzo mai questa funzione per cui setto questo registro unicamente in questo modo:

_FWDT(FWDTEN_OFF); // Watchdog timer disattivato

Se vi serve usare il watchdog timer, sappiate che oltre a poterlo semplicemente attivare, ne potete settare anche altre caratteristiche. Controllate sempre il datasheet e il file header del pic utilizzato per controllare tutt i valori impostabili.

Altri registri di configurazione

I registri FBS, FSS e FGS servono a proteggere determinate locazioni di memoria, personalmente li lascio sempre non programmati, e quindi ai valori di default, in maniera che sia sempre tutto sprotetto. Alcuni di questi registri non sono disponibili su tutti i dspic.

Il registro FPOR serve ad impostare sia il tempo di poweron-reset che il “posizionamento” dei pin destinati all’I2C. Come abbiamo visto nell’articolo precedente, l’I2C non può essere rimappata ma ha un’assegnazione fissa. Agendo sul bit ALTI2C del registro FPOR, però, si può fare in modo che l’I2C sia mappato diversamente:

ALTI2C_ON:  I2C rimappata sui pin ASDA1/ASCL1
ALTI2C_OFF: I2C mappata sui pin SDA1/SCL1 (condizione di default)

Ovviamente, trattandosi di un’impostazione di configurazione, non può essere eseguita a runtime come invece è possibile fare per le altre periferiche gestibili tramite PPS.

Esempio di configurazione del registro FPOR:

// PowerOn Reset di 128mS + I2C rimappata sui pin ASDA1/ASCL1
_FPOR(FPWRT_PWR128 & ALTI2C_ON);

Il registro FICD serve ad abilitare il JTAG (uno standard nato per la comunicazione / programmazione / debug degli integrati, vedi su wikipedia per maggiori informazioni. Una lacuna, finalmente colmata, per la quale spesso la Microchip è stata “additata”) e per selezionare i pin di comunicazione con l’ ICD (In-Circuit Debugger – difatti l’ICD su questi dispositivi si può collegare su 3 diverse coppie di pin).

Configurazione PIC24F

Prenderò ad esempio il PIC24FJ64GB004 che è “quasi” pin-to-pin compatibile con il dsPic illustrato fin’ora. Nei PIC24 ai registri di configurazione non è stato dato un nome che riflette la funzione specifica del registro come nei dsPIC, ma sono stati chiamati semplicemente: CONFIG1, CONFIG2, CONFIG3, CONFIG4 (w l’originalità!)  o CWx (Configuration Word 1,2,3 e 4) probabilmente perchè ogni registro, come sui pic ad 8 bit, assolve a più funzioni.  I registri inoltre,  sono in minor numero rispetto ai dsPic perchè qui sono a 24bit. Anche in questo caso, col C30, i registri saranno configurati tramite funzioni aventi lo stesso nome dei registri, preceduti da un underscore:

_CONFIG1(x);

Andiamo quindi a controllarci sia il datasheet che il file header (p24FJ64GB002.h nel mio caso) . Vediamo che i nomi dei bit, e le funzioni, sono più o meno le stesse che vi ho già illustrato per i dsPic. In aggiunta, sul pic24 che ho citato, essendoci un modulo USB fullspeed, ci sono delle opzioni aggiuntive che permettono di avere un clock di 48MHz per il funzionamento del modulo USB sebbene il pic in questione non possa funzionare a più di 32MHz. C’è difatti in questo pic un secondo modulo PLL (PLL96MHz) che assolve a questa funzione.

Impostazione del Clock con PLL

Sui pic a 16 bit, il Clock, come abbiamo visto, è una di quelle cose che è possibile settare in mille modi diversi. In particolare l’utilizzo del PLL ci permette di moltiplicare la frequenza di clock fino a raggiungere valori davvero “spropositati” (fino ad 80MHz sui dsPic e fino a 32MHz sui pic24f) utilizzando quarzi di modesto valore e fornendoci, soprattutto, una notevole flessibilità nella scelta del quarzo da utilizzare per l’oscillatore primario.

Per settare correttamente il clock è necessario leggersi per bene sul datasheet la sezione relativa all’oscillatore (Oscillator Configuration), per cui qui fornirò solo delle istruzioni di base  facendo sempre riferimento al dsPIC33FJ128GP802. Abbiamo visto già , nella parte relativa al settaggio della word per l’oscillatore, come selezionare la sorgente di clock. Vediamo adesso come aumentare il clock proveniente dall’oscillatore primario.

Un pic a 16bit esegue già normalmente le istruzioni con una frequenza Fcy = Fosc/2  più alta rispetto ai pic ad 8 bit che operano ad una frequenza pari Fosc/4.   Con Fosc si intende la frequenza dell’oscillatore NON il solo quarzo ma tutto il sistema di oscillazione nel suo insieme (es.: quarzo + PLL).

A volte i simboli Fcy e Tcy vengono utilizzati in maniera equivalente sui datasheet creando confusione, quindi fate attenzione. Con Fcy si intende la frequenza operativa reale (Fosc/2), con Tcy il tempo di un ciclo di istruzioni (Tcy = 1/Fcy). Per cui: se Fosc vale 80MHz, Fcy=40MHz e quindi Tcy=25nS.

Per capire come funziona il PLL osserviamo lo schema concettuale presente sul datasheet:

Chiamiamo Fin la frequenza dell’oscillatore in ingresso al circuito del PLL (es.: la frequenza del solo quarzo se abbiamo deciso di utilizzare il quarzo). La frequenza Fin, prima di “andare in pasto” al PLL, dovrà essere divisa, tramite un prescaler, di un fattore N1 (variabile da 2 a 33).

Il fattore N1 viene impostato selezionando i 5 bit PLLPRE (PLL Prescaler) del registro CLKDIV (0b00000 = input/2, 0b00001 = input/3 … 0b11111 = input/33 – il valore di N1 vale in pratica il valore binario impostato + 2). Ricordiamoci che per utilizzare il PLL è necessario utilizzare un quarzo o un oscillatore tale che all’uscita del prescaler sia presente una frequenza compresa tra 0.8 e 8MHz, per cui nel caso si voglia utilizzare il PLL con un quarzo esterno è necessario selezionare un quarzo XT e non HS: questo è necessario affinchè vengano rispettate anche le condizioni imposte successivamente nella catena del PLL.

La frequenza in uscita dal PLL Prescaler andrà quindi in ingresso al VCO (Voltage Controlled Oscillator) del PLL. Il VCO ha un divisore di feedback, selezionabile tramite i 9 bit PLLDIV (unici bit del registro PLLFBD), che provvede a fornire un fattore M con il quale la frequenza in uscita al VCO viene moltiplicata. All’uscita del VCO dobbiamo avere una frequenza compresa tra 100 e 200MHz. Il valore di default di PLLDIV è 50, il suo valore può essere variato da 2 (0b000000000) a 513 (0b111111111 – anche qui basta impostare il valore binario e aggiungere 2 a tale valore per ottere M).

La frequenza in uscita al VCO viene quindi inviata in un postscaler che fornisce un secondo fattore di divisione N2, selezionabile tra i valori 2 (0b00), 4 (0b01 – valore di default) e 8 (0b11) impostando i due bit PLLPOST (del registro CLKDIV).

La frequenza in uscita dal PLL (Fosc) dovrà essere compresa tra 12.5 e 80MHz. Il calcolo del valore finale di Fosc si effettua con la formula:

Facciamo un esempio pratico che vale sempre più di mille parole. Supponiamo di utilizzare un quarzo esterno da 10MHz. Abbiamo quindi Fin=10MHz. Impostiamo (in C30) i seguenti valori per i fattori M, N1 e N2:

_PLLPRE=0x00; // N1=2
_PLLDIV=0x1E; // M=32
_PLLPOST=0x00; // N2=2

Avremo che all’ingresso del VCO ci saranno 10/N1 = 5MHz (rientriamo nel range 0.8 – 8). All’uscita del VCO : 5*32=160MHz (rientriamo nel range 100-200). Infine all’uscita del postscaler: 160/2 = 80MHz (rientriamo nel range 12.5 – 80).

Il nostro Fosc, quindi, utilizzando un quarzo da 10MHz e settando opportunamente il PLL, è di ben 80MHz fornendoci una ragguardevole velocità di elaborazione pari a 40MIPS (25 nanosecondi) !

Se avete letto la nota1 dell’immagine precedente, capite che sia la frequenza Fosc che tutti i valori vanno scelti in modo che i 3 range di frequenza in uscita dai vari blocchi siano tutti rispettati contemporaneamente.

Il registro OSCCON – Ancora impostazioni per l’oscillatore!

Il registro OSCCON permette ulteriori impostazioni dell’oscillatore:

I bits COSC sono di sola lettura e riflettono (una volta che il clock si è stabilizzato) l’impostazione dei bits FNOSC data nel registro di configurazione FOSCSEL. Indicano in pratica l’oscillatore attualmente in funzione.

Quindi, se si esegue il clock switch, una volta che questa operazione è conclusa,  tali bits rifletteranno il nuovo valore impostato.

E’ buona norma controllare tali bit prima dell’esecuzione del main, nel caso in cui , ad esempio, abbiamo scelto di far partire il pic prima con l’oscillatore FRC e quindi con l’oscillatore da noi selezionato (impostazione di configurazione IESO_ON in FOSCSEL):

while (OSCCONbits.COSC != 0b011); {continue;} // controllo che sia entrato in funzione l'oscillatore primario con PLL

I bits NOSC vanno impostati allo stesso, identico modo, dei bits FNOSC :

e servono per selezionare il “nuovo” oscillatore mediante la funzione di clock switching di cui abbiamo discusso prima. Quindi se vogliamo passare ad un altro oscillatore, dovremo impostare questi bits su un nuovo valore prima di effettuare il clock switch.

Il bit CLKLOCK funziona solo con il clock switch abilitato e il fail safe clock disabilitato (ovvero impostazione di configurazione FCKSM_CSECMD nel registro di configurazione FOSC) e serve ulteriormente per abilitare (0) o disabilitare (1) il clock switching.

Del bit IOLOCK ne abbiamo già discusso nell’articolo precedente: serve a bloccare (1) o sbloccare (0) la funzione PPS.  Il blocco/sblocco va eseguito tramite la sequenza in assembler che abbiamo già visto o tramite le builtin: non è possibile modificare questo bit direttamente.

Il bit LOCK, di sola lettura, indica se il PLL è “agganciato” (1) e quindi sta funzionando in maniera stabile o non è ancora in lock (0). Va controllato prima dell’esecuzione del main nei nostri programmi nel caso in cui stiamo utilizzando il PLL. Per cui è sempre bene porre un’istruzione del tipo:

while(OSCCONbits.LOCK!=1) {continue;} // controllo che il PLL sia agganciato

prima dell’esecuzione del main.

Il bit CF viene settato dall’hardware e va resettato via software: indica un malfunzionamento del clock principale rilevato dal FSCM (Fail Safe Clock Monitor).

Il bit LPOSCEN serve per abilitare (1) o disabilitare (0) il clock secondario a bassa potenza.

Il bit OSWEN serve per eseguire il clock switch (ponendolo a uno). Quando il clock switch è completo tale bit viene riportato a zero dall’hardware.

Il registro CLKDIV

Abbiamo già visto le funzioni “principali” di questo registro, ovvero l’impostazione del prescaler  (PLLPRE) e del postscaler (PLLPOST) del PLL. In tale registro ci sono altri bit “interessanti” che possono essere settati:

DOZEN : abilita (1) o disabilita (0) il rapporto tra la frequenza del processore e la frequenza usata dalle periferiche (si può difatti fare in modo che il processore operi a frequenza più bassa rispetto alle periferiche). Il valore di divisione di frequenza operativa del processore viene impostato tramite i bit DOZE nello stesso registro. Impostando DOZEN a 0 in pratica processore e periferiche lavoreranno con lo stesso clock. Questa caratteristica è stata introdotta per ridurre ulteriormente i consumi di corrente.

ROI : se posto ad 1, al verificarsi di un interrupt il bit DOZEN viene resettato (posto a zero) e quindi riporta il funzionamento del processore alla frequenza standard. Ponendolo a zero gli interrupt non hanno nessun effetto sul valore di DOZEN.

FRCDIV : questi 3 bits servono ad impostare il postscaler (divisore) per l’oscillatore interno FRC (000 = nessuna divisione, valore di default).

Puoi andare alla fine dell'articolo e lasciare un commento. I trackback e i ping non sono attualmente consentiti.

  1. #1 da Igor il 19 settembre 2010

    Wow, complimenti, queste pagine sui dsPIC sono ORO COLATO, non vedevo l’ora! :D
    Purtroppo la documentazione che si trova online è solo in inglese (reference e datasheet) sarebbe fantastico avere delle lezioni in italiano ma già questi appunti sono veramente ma veramente utili, continua così! ;)

  2. #2 da Gianmarco il 8 ottobre 2010

    Ciao, grazie mille per i tuoi appunti, ho da poco iniziato la conversione da serie 18 a DS33e questa non è altro che bibbia per me!!

  3. #3 da Gianmarco il 11 ottobre 2010

    ho provato a scrivere un programma di prova con i settaggi iniziali così come li hai spiegati, ma non capisco perché in compilazione mi torna questi errori:

    test_printf.c: In function ‘main’:
    test_printf.c:22: error: section attribute cannot be specified for local variables
    test_printf.c:22: warning: ignoring space attribute applied to automatic _FOSCSEL
    test_printf.c:28: error: section attribute cannot be specified for local variables
    test_printf.c:28: warning: ignoring space attribute applied to automatic _FOSC
    test_printf.c:30: error: section attribute cannot be specified for local variables
    test_printf.c:30: warning: ignoring space attribute applied to automatic _FWDT
    test_printf.c:33: error: section attribute cannot be specified for local variables
    test_printf.c:33: warning: ignoring space attribute applied to automatic _FPOR
    test_printf.c:33: warning: unused variable ‘_FPOR’
    test_printf.c:30: warning: unused variable ‘_FWDT’
    test_printf.c:28: warning: unused variable ‘_FOSC’
    test_printf.c:22: warning: unused variable ‘_FOSCSEL’

    eppure l’header del dspic (33fj128gp802) è incluso. :S

    • #4 da Gianmarco il 12 ottobre 2010

      trovato il problema… utilizzavo queste istruzioni nel main…….. guardando altri esempi ho visto che vanno messe fuori.. asd

      • #5 da Giovanni Bernardo il 13 ottobre 2010

        Scusa ma…. La word di configurazione da che mondo è mondo, su tutti i pic, si mette sempre prima del main… Pensavo fosse una cosa assolutamente ovvia e inutile da specificare. Difatti ho detto in questi articoli che parlano dei pic a 16bit che erano rivolti a chi già sa usare i pic ad 8 bit.

  4. #6 da Luca il 13 novembre 2010

    Eccoci, dato l’ennesimo esame, procuratosi quel cavolo di quarzo 10Mhz, per l’occasione anche a basso profilo, ho finalmente messo mano a tutto ciò.

    Premesso che ho impostato, come in quei files che mi inviasti, un osc_init_10.c fatto pressappoco così (un estratto):


    _ROI = 0x00; // Recover on Interrupt bit
    _DOZE = 0x03; // Processor Clock Reduction Select bits
    _DOZEN = 0x00; // DOZE Mode Enable bit
    _FRCDIV = 0x00; // Internal Fast RC Oscillator Postscaler bits
    _PLLPOST = 0x00; // PLL VCO Output Divider Select bits (N2)
    _PLLPRE = 0x00; // PLL Phase Detector Input Divider bits (N1)
    _PLLDIV = 0x1E; // PLL divider (M=32)

    RCONbits.SWDTEN=0; // Disable Watch Dog Timer

    e quindi se:

    XTAL = 10 MHz
    e
    PLLPRE = 1/2
    PLLPORT = 1/2
    allora
    Fosc = Fin * ( PLLDIV / (PLLPRE*PLLPOST) )
    Fcy = Fosc / 2

    10 MHz * ( 32 / (2*2) ) = 10 MHz * 32/4 = 80 MHz

    CLOCK_FREQ = 10 MHz
    Fosc = CLOCK_FREQ*M/(N1*N2) = 10M*32/(2*2)=80Mhz

    ALLORA:
    Fcy = Fosc / 2 = 40Mhz!!!!!!!!!!!!

    ma se il main è:
    #include
    #include “gen_init.c”
    #include “osc_init_10.c”

    _FOSCSEL(IESO_OFF & FNOSC_PRIPLL);
    _FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT);
    _FWDT(FWDTEN_OFF);
    _FPOR(FPWRT_PWR128 & ALTI2C_ON);

    int main()
    {
    gen_init();
    AD1PCFGL = 0x03C0;
    osc_init();

    LATA = 0x0000; LATB = 0x0000;
    TRISA = 0b1111111111101111;
    TRISB = 0b1111111111101111;

    while(1)
    _LATA4^=1;

    }

    perchè su lata4 ho un’onda quadra soltanto ad un 1Mhz??

    e perchè se il while lo trasformo in
    while(1){
    _LATA4=0;
    _LATA4=1;
    _LATA4=0;
    _LATA4=1;
    …. etc per tante tante volte }

    mi esce un’onda quadra a 10Mhz???

    Non avevamo detto che per fcy=40Mhz, indipendentemente se faccio la xor o assegno direttamente un valore, dovrei poter visualizzare un’onda quadra a 40Mhz?

    Grazie per la tua sempre cordialissima attenzione,
    LG

    • #7 da Giovanni Bernardo il 13 novembre 2010

      Uhmmm… è alquanto strano… Hai provato con MPLab SIM cosa succede?

      • #8 da Luca il 14 novembre 2010

        Come faccio ad eseguire un’analisi nel tempo con mplab sim? Ovviamente le uniche cose che evidenzio che le istruzioni ad uno step into\over vengono eseguite sia la xor che l’assegnazione in un colpo solo ( di clock ?) in testa a lui, ma non è così! Lo noto che praticamente nel caso delle assegnazioni se faccio =0 =1 =0 =1 lui ci mette tot tempo per ogni assegnazione, poi per ritornare in testa al while impiega molto tempo in più che quello impiegato ad una singola assegnazione; per non parlare poi del confronto tra un =0; ed una^=1; abissalmente diversi (stimerei 1:10) è come se l’esecuzione delle diverse istruzioni richiedesse tempo diverso.

        Uff! che fatti!
        Questi dsPic sono chiari come studiare cuneiforme prima della stele di rosetta.

        Cosa ne pensi?
        Grazie mille,
        LG

      • #9 da Giovanni Bernardo il 14 novembre 2010

        Con MPLab sim io in genere utilizzo lo stopwatch per calcolare i tempi. Metti due breakpoint prima e dopo il punto che vuoi controllare, avvii, arrivato al primo breakpoint si ferma e azzeri il counter, premi di nuovo play, lui si blocca al secondo breakpoint e quindi ti leggi il tempo che ci ha messo… Penso pure io che siano troppo complicati… ma penso anche che per quello che sono in grado di fare, la complicazione era necessaria…

      • #10 da Luca il 16 novembre 2010

        Ok, ho fatto vari test, grazie al libro di “Di Jasio”, oggi leggevo proprio dello stopwatch

        tornando a noi: chiamando questo post “5 minuti di allibimento”:

        _LATB5=1; //richiede 1 Instructions Cycle
        _LATB5^=1; //ne richiede QUINDICIII?!?!?!? (leggilo alla doc…emmett brown… “1.21 jiggawaats?”)

        ovviamente per riprendere daccapo il while ne servono 2

        Inoltre, cercando soluzioni migliori:

        if(_LATB5)_LATB5=0; //7+3se zero
        else _LATB5=1; // 1
        Sempre meglio della xor…

        Ma la ALU sta per “assurde logic unit”? (…waddaf*ck!)

        In ogni caso non mi trovo con una cosa:
        pensiamo all’onda quadra generata con una serie di _LATB5=1;_LATB5=0;_LATB5=1;_LATB5=0;… ; se per ogni istruzione servono 1 istruzione, e lo stopwatch (impostato la freq del processore ad 80Mhz) mi dice che ci ha messo 0.05uS allora 1 / (0.05 * (10^(-6))) = 20Mhz, e mi trovo perchè anche a me sull’oscilloscopio vengono 20 (10Mhz frequenza onda quadra, due istruzioni per periodo=>20Mhz) ! Ma teoricamente non dovrei ottenerne il doppio? avendo 1 istruzione eseguita in 2 colpi di clock? 80/2=40Mhz? e non 20?
        Grazie per la dritta dello stopwatch!

        Strano per davvero però,
        G

        Un’altra domanda, è normale che lo stopwatch mi indichi processor frequency su 120Mhz?

      • #11 da Luca il 16 novembre 2010

        Come non detto, avevo sbagliato a far funzionare lo stopwatch, mi dice giustamente che la ci ha impiegato per quell’unica operazione di _LATB5=x; 0.025uS e quindi 40Mhz, ma invece io me ne ritrovo solo 20. :S

      • #12 da Giovanni Bernardo il 17 novembre 2010

        Mi dispiace che non posso nemmeno fare qualche prova io con la mia scheda di sviluppo e il mio oscilloscopio (avrò il laboratorio inaccessibile per un po’)… Ma provando quell’esempio che ti dissi, dei led lampeggianti sul dspic, controllando con l’oscilloscopio mi ricordo che era tutto ok… però potrei ricordare male…

      • #13 da Luca il 17 novembre 2010

        Ti ringrazio lo stesso, sei sempre fin troppo gentile, farò qualche altra prova dopo l’ennesimo esame (di oggi), e ti farò sapere.
        Keep in touch.

        LG

      • #14 da Luca il 21 novembre 2010

        Ok, tutto risolto, e a dir la verità non capisco come. Tutto riquadra, anche se tutti quei colpi di clock per una xor proprio non la capisco. Ora sono impuntato su un problema ben peggiore, (leggasi ASSURDO).
        Come fà a non fungere un main del genere? Bah…

        int main()
        {
        gen_init();
        AD1PCFGL = 0b1111111111111111;
        osc_init();

        LATA = 0x0000; LATB = 0x0000;
        TRISA = 0b0000000000000000;
        TRISB = 0b0000000001000000;
        _LATB5=1;
        while(1){
        if(!_LATB6){_LATB5=0;while(!_LATB6){}}
        _LATB5=1;
        }
        Mah…a te come và, ancora in esilio dal lab?

      • #15 da Giovanni Bernardo il 21 novembre 2010

        Ora sto in esilio “parziale”… e comunque sia ho bisogno di rilassarmi un po’ e realizzare progetti più semplici… il tempo è molto poco.
        Come hai risolto?
        In quest’altro codice premi un pulsante su B6 e porti a massa B5 fintanto che il pulsante è premuto? Non appena rilasci il pulsante B5 ritorna a 1 … cosa c’è che non funziona… il circuito come si comporta?

      • #16 da Luca il 22 novembre 2010

        Semplicemente il dspic è insensibile agli ingressi, nemmeno una cosa del genere
        if(!BTN){LED=0;}
        if(BTN){LED=1;}
        sembri funzionare! (il led è sempre spento)
        Qui invece
        if(!BTN){LED=1;}
        if(BTN){LED=0;}
        (il led è sempre acceso)

        Insomma, l’ingresso è sempre valutato come 0, anche se lo forzo con pulsanti e roba varia! :S
        Comunque mi sto proprio demoralizzando, con tutta la santa pazienza e l’interesse che ho, non ci siamo proprio! nemmeno sui pulsanti ed un semplice if… non voglio nemmeno immaginare il resto!
        (per curiosità, ma cos’è quel “giochino” con la matrice di led e tasti?)
        LG

      • #17 da Giovanni Bernardo il 22 novembre 2010

        è normale che si comporti in maniera strana… fai due if uno dietro l’altro sullo stesso ingresso, hai provato a mettere un “else” sul secondo? Fai sta prova e fammi sapere.

        Il giochino a led è per mia figlia, fissata coi pulsanti… preme un pulsante e si accende il led corrispondente… niente di che ma la ficata è che l’ho fatto con un 12F675 e mi sono pure avanzati 2 I/O che penso utilizzerò per il sonoro.

      • #18 da Luca il 22 novembre 2010

        visto che è un’oretta che sento piacevolmente elenchi di… su raitre, stasera faccio la mia

        l’elenco dei modi (fallimentari) con i quali luca ha provato a far accendere un led al dspic reagendo ad un pulsante:

        while(1){
        if(!BTN){LED=1;}
        if(BTN){LED=0;}
        USC^=1; //lo uso per vedere se il ciclo “cicla”
        }

        while(1){
        if(!BTN){LED=1;}
        else{LED=0;}
        USC^=1;
        }

        while(1){
        if(BTN){LED=1;}
        else{LED=0;}
        USC^=1;
        }

        while(1){
        if(!_LATB6){_LATB5=0;while(!_LATB6){}}
        else _LATB5=1;
        }

        while(1){
        if(!_LATB6){_LATB5=0;}
        else _LATB5=1;
        }

        …e tanti altri… ma evito.

        Niente proprio, ho cambiato gli ingressi, ho variato gli stati logici, ho debuggato, ho provato a resettarlo, a mandarlo in esecuzione tenendolo sottosopra saltando sulla gamba destra, ho scritto a gesù di farlo funzionare…ma tutto si è risolto in maniera fallimentare.
        Questo dspic non mi capisce è “inSensibile” (che battuta pessima).

      • #19 da Giovanni Bernardo il 22 novembre 2010

        il USC^=1; lo verifichi con l’oscilloscopio?

        if(!BTN){LED=1;}
        else{LED=0;}

        dovrebbe funzionare correttamente… c’è la resistenza di pullup? Ma che scheda stai utilizzando?

      • #20 da Luca il 22 novembre 2010

        si con il mio fido ATTEN ADS1042C superrisparmio. =)

        In ogni caso non funge nemmeno l’if da te indicato. la resistenza c’è, è tutto montato su breadboard, e mi sono messo a controllare pure il segnale del pulsante in ingresso e quello sul led. Non sò più cosa controllare!

        #include
        #include “gen_init.c”
        #include “osc_init_10.c”

        #define BTN _LATA4
        #define LED _LATB5
        #define USC _LATB7

        _FOSCSEL(IESO_OFF & FNOSC_PRIPLL);
        _FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT);
        _FWDT(FWDTEN_OFF);
        _FPOR(FPWRT_PWR128 & ALTI2C_ON);

        int main()
        {
        gen_init();
        AD1PCFGL = 0b1111111111111111;
        osc_init();

        TRISA = 0b0000000000010000;
        TRISB = 0b0000000000000000;
        LATA = 0x0000; LATB = 0x0000;

        while(1){
        if(!BTN){LED=1;}
        else{LED=0;}
        USC^=1;
        }

        Questo è il codice e il led rimane sempre acceso! Il pulsante funziona, attivo alto, alla pressione arriva a 0V, l’onda di USC è perfettamente quadra a circa 1MHz, e il segnale sul led è perfettamente al livello alto, stabile in qualsiasi situazione. Tu dove cercheresti il problema? Forse nella word? Vabbe dai, cerco di risolvermela io, ti ho già dato fin troppo disturbo. Grazie mille infinitamente, ti devo totalmente tutti i miei ringraziamenti, sognavo di programmare pic da almeno 10 anni, fin da quando clonavo le wafercard per “D+”, ed ora mi ritrovo a sbattere felicemente la testa su una riga di codice.
        Buona serata! Attendo ansiosamente i tuoi progressi su questi meravigliosi (e collaborantissimi) dsPic! =)

      • #21 da Giovanni Bernardo il 23 novembre 2010

        Come regola generale il
        LATA = 0x0000; LATB = 0x0000;
        andrebbe messo prima di
        TRISA = 0b0000000000010000;
        TRISB = 0b0000000000000000;

        ma non penso sia questo il problema… secondo me hai qualche problema sulla scheda. Hai detto che usi una breadboard… male… molto male… su questi dispositivi che poi funzionano pure ad alta frequenza e a bassa tensione una breadboard non è molto indicata. Secondo me il pin dove sta collegato il led sta in corto con l’alimentazione, prova a cambiare pin o a spostare il circuito su un’altra parte di breadboard… se è davvero così c’è pure buona probabilità che hai bruciato il pin.

  5. #22 da Cristian il 27 dicembre 2010

    Ciao Giovanni, grazie mille per le info che condividi! Sei diventato il mio mentore sui PIC.
    Purtroppo quando metto in pratica quanto spiegato trovo sempre qualche problema.

    Come in questo caso, ho realizzato questo stupidissimo programma per generare un onda quadra che controllo con il mio oscilloscopio.
    Il problema è che con il timer impostato al minimo ottengo un ritardo di 1us mi sembra inaudito visto che uso le impostazioni per lavorare al massimo del clock del dsPIC30f4011

    Sicuramente ho sbagliato qualche impstazione del Timer1

    Allego il listato:
    #include

    _FOSC(CSW_FSCM_OFF & FRC_PLL16); /* Internal Osc PLLx16 = 30MIP */
    _FWDT(WDT_OFF); /* Watchdog Off */
    _FBORPOR(PBOR_OFF & MCLR_EN); /* Brownout Disabled – MCLR Enabled */
    _FGS(CODE_PROT_OFF);

    void Init_T1(void)
    {
    T1CON = 0;
    T1CONbits.TCKPS=0; // prescaler = 256
    TMR1 = 0; // clear timer 1
    PR1 = 1;
    IFS1bits.T1IF = 0; // clear interrupt flag
    IEC1bits.T1IE = 1; // set interrupt enable bit
    T1CONbits.TON = 1; // start Timer1
    }

    void _ISR _T1Interrupt(void) // interrupt routine
    {
    IFS1bits.T1IF = 0; // clear interrupt flag
    _RB0=~_RB0;
    }

    int main(void)
    {
    TRISB=0;
    PORTB=0;

    Init_T1();

    while(1)
    {
    };

    return 0;
    }

    • #23 da Giovanni Bernardo il 27 dicembre 2010

      Non vedo l’inizializzazione dell’oscillatore.
      Vedi qui un codice di esempio:
      http://www.droids.it/cmsvb4/content.php?186-990.012-MuIn-dsPIC-esempio-programmazione

      • #24 da Cristian il 27 dicembre 2010

        Cosa intendi per inizializzazione dell’oscillatore?
        qui indico il tipo di oscillatore:
        _FOSC(CSW_FSCM_OFF & FRC_PLL16); /* Internal Osc PLLx16 = 30MIP */

        e poi c’è la sub:
        void Init_T1(void)
        {
        T1CON = 0;
        T1CONbits.TCKPS=0; // prescaler = 256
        TMR1 = 0; // clear timer 1
        PR1 = 1;
        IFS1bits.T1IF = 0; // clear interrupt flag
        IEC1bits.T1IE = 1; // set interrupt enable bit
        T1CONbits.TON = 1; // start Timer1
        }

        che inizializza i registri per la gestione del timer e avvia l’attesa dell’interrupt

        Comunque ho scaricato l’esempio che mi suggerivi e lo sto adesso provando…

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
Settorezero.com e il logo Zroid™ ©2007÷2017 Giovanni Bernardo - E' vietata la copia e la distribuzione anche parziale dei contenuti di questo sito web senza l'esplicito consenso dell'autore. I contenuti di settorezero.com sono distribuiti sotto una licenza Creative Commons Attribuzione-Non Commerciale-Non Opere derivate 2.5 Italia e sono soggetti alle condizioni definite nel disclaimer. Settorezero.com e tutti i suoi contenuti sono tutelati dalla legge sul diritto d'autore per cui i trasgressori sono perseguibili a norma di legge. Settorezero fa uso dei cookie leggi l'informativa estesa. Il tema di questo sito è basato sul tema Fusion per wordpress, realizzato originariamente da digitalnature e fa uso del plugin Wassup per il computo delle statistiche. Per contattare l'autore siete pregati di utilizzare la sezione contatti. Siamo presenti anche su Facebook e, meno assiduamente, anche su Twitter - Tumblr - Google+ - Blogspot - Youtube.
Creative Commons BY-NC-ND 2.5