Creative Commons BY-NC-ND 2.5Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza Creative Commons Attribuzione - Non Commerciale - Non opere derivate 2.5 Italia e con le condizioni d'uso definite nel disclaimer: siete pregati di leggere entrambi questi documenti prima di usufruire dei contenuti di questo sito. Per alcuni contenuti è necessaria una registrazione gratuita: non è necessario pagare e non è necessario accumulare punteggi per accedere agli articoli e scaricare i sorgenti. Basta solo essere onesti. Se volete che questo sito continui a rimanere attivo, a contribuire ogni giorno alla diffusione della cultura libera, non copiate il materiale per ripubblicarlo in altri luoghi : chi fa questo è solo un miserabile e un perdente. Se volete partecipare su settorezero e rendere le vostre idee, i vostri progetti, fruibili da tutti senza limitazioni, come dovrebbe essere in un paese civile e acculturato, potete farlo tranquillamente.

Delay

Librerie PIC12 e PIC16 » Delay

Librerie a precisione migliorata distribuite da Microchipc.com.

Prerequisiti

Quarzo/oscillatore da 4MHz, 8MHz, 10MHz, 16MHz, 20MHz o 32MHz. Frequenze diverse da queste non sono supportate

Utilizzo

Definire nel main la frequenza del quarzo/oscillatore espressa in Hertz definendo PIC_CLK:

#define PIC_CLK 4000000 // quarzo a 4MHz

Includere delay.c nel main dopo il define del quarzo:

#include "delay.c"

Funzioni disponibili

DelayUs(x); // esegue un ritardo da x μSec (x da 0 a 255)
DelayMs(x); // esegue un ritardo da x mSec (x da 0 a 255)
DelayBigMs(x); // esegue un ritardo da x mSec (x da 0 a 65535)
DelayS(x); // esegue un ritardo da x Sec (x da 0 a 255)

Download

Routine Delay Enhanced Precision (509)

  1. #1 da salvatore salzano il 21 dicembre 2010

    Ciao, ho visto che utilizzi la nuova Delay. Siccome sto facendo delle esperienze con SDCC (vorrei poter divulgare l’utilizzo di questo compilatore e sto cercando di adattare tutte le differenze che incontro) ho visto la chiamata a CLRWDT() . Non so dove trovarla, ma credo che dovrebbe semplicemente resettare il WDT, quindi potrebbe andare bene se metto il Watchdog Timer Enable bit (WDTEN) = 0? Ti ringrazio per quanto stai facendo, è un valido contributo.

    • #2 da Giovanni Bernardo il 21 dicembre 2010

      Disabilitare il watchdog timer (WDTEN=0) e resettarlo sono due cose ben diverse!! Quella che hai incontrato è una semplice macro definita in pic.h a riga 283:

      #define CLRWDT() asm(“clrwdt”)

      Ovviamente questo fa parte dell’Hitec-C, per l’SDCC non ti so dire, ma penso che pure li ci sia un’istruzione del genere… se non c’è… basta che richiami il comando assembler clrwdt con le modalità di SDCC.

      Quel comando non fa nient’altro che eseguire l’istruzione assembler che azzera il counter del watchdog. Il watchdog timer è un contatore che, quando viene abilitato (con WDTEN), incrementa da solo e quando giunge alla fine resetta il pic. Per non far resettare il pic ogni tanto dobbiamo azzerare tale contatore con la funzione CLRWDT… A cosa serve? Se abbiamo programmato male potrebbe accadere che il programma entri in stallo (un ciclo infinito ad esempio). In quel caso, non essendoci nessuna istruzione che resetta il watchdog, il pic si resetta e il programma puo riprendere. L’istruzione per azzerare il timer, quindi, va messa in punti strategici ed ha quindi una funzione di sicurezza.

      L’utilizzo di SDCC è interessante. In molti lo usano e a molti ho chiesto di scriverci su un paio di righe, giusto per capire come impostarlo e se si puo integrare in mplab o in altro IDE. Se hai qualcosa di pronto (un semplice tutorial) o lo vuoi scrivere, lo pubblico qui e fai felici in tanti sicuramente.

  2. #3 da peppino53 il 20 febbraio 2012

    salve,
    non ho capito l’utilizzo del wathdog che vedo sia nei pic che nei st6.
    è una sicurezza che si usa in fase di stesura del programma o per eventuali problemi hardware?
    grazie per l’attenzione
    cordiali saluti
    peppino53

    • #4 da Giovanni Bernardo il 21 febbraio 2012

      Il watchdog timer è un timer che resetta la CPU. Devi azzerarlo periodicamente per fare in modo che la CPU non si resetti. A cosa serve? Ad evitare che la CPU si blocchi, vuoi per un guasto, vuoi perchè chi l’ha programmata non sa programmare. In pratica: setti il watchdog timer, ogni tanto nel tuo programma devi mettere qualche istruzione che lo resetti per fare in modo che non finisca il suo conteggio causando il reset. Se il tuo programma si blocca, il watchdog timer continua a camminare perchè è indipendente. Essendo il programma bloccato, il wdt arriva alla fine del suo conteggio perchè nessuna istruzione lo resetta, cosi si resetta la CPU. Generalmente il wdt si utilizza in applicazioni con un certo livello di sicurezza ma è ovvio che si deve fare in modo, sia lato software che hardware, che il wdt non debba mai entrare in azione altrimenti vuol dire che il circuito è progettato male.

  3. #5 da killer0007 il 25 marzo 2012

    non riesco a capire perchè mplab mi dia questo errore in compilazione:Error [312] C:\……\delay.h; 180.1 “;” expected.
    il mio codice non sembra sbagliato:

    #define PIC_CLK 4000000 // quarzo a 4MHz
    #include // contiene i nomi mnemonici di registri e porte

    __CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & BOREN_OFF & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF & CP_OFF)

    #include “delay.c” // routine per ritardi
    #include “setting.h”

    void main (void)
    {
    setting();
    while(1)
    {
    int i=0;
    for(i=0;i<=9;i++)
    {
    portdis=numeri[i];
    DelayS(1);
    }
    }
    }

    • #6 da Giovanni Bernardo il 25 marzo 2012

      Su due piedi non ti saprei dire, hai fatto qualche modifica alle routine di delay?
      E poi chi ti ha insegnato a mettere il minore uguale nel ciclo??? ORRORE!
      i al valore 9 ci deve? Se ci deve arrivare (cioè il ciclo deve compiere 10 iterazioni: da 0 a 9), metti i<10. Togli quell'uguale!

      • #7 da killer0007 il 25 marzo 2012

        Non ho fatto nessuna modifica al delay. Per quanto riguarda il <= hai ragione :-)
        Comunque ho usato anche il delay che ho scaricato da un tuo articolo (lampeggio led lezione pic ) e mi dava lo stesso problema.
        Uso la versione 9.83 di hi tech c.

        • #8 da Giovanni Bernardo il 25 marzo 2012

          Allora hai qualche problema nel codice. Usi la funzione delay anche nel file settings?

          • #9 da killer0007 il 25 marzo 2012

            assolutamente no,ecco il setting.h

            //settaggi

            #define tempolamp 1000

            #define display1 RD6

            #define portdis PORTB

            //ASSEGNO L’ATTIVAZIONE DI OGNI PORTA AL NUMERO DECIMALE CORRISPONDENTE
            //PER ATTIVARE LA PORTA RB6 DEVO SCRIVERE 64. INFATTI IL NUMERO BINARIO 1000000 CHE ATTIVA RB6
            //CORRISPONDE AL NUMERO 64 DECIMALE

            #define la 1
            #define lb 2
            #define lc 4
            #define ld 8
            #define le 16
            #define lf 32
            #define lg 64

            #define point RB7

            //ora in base ai numeri da comporre attivo le relative porte
            //per comporre il numero 1 dovrò attivare il segmento B e C del display
            //quindi la porta RB1 e RB2 quindi in binario 00000110 che in decimale equivale a 6 e quindi
            //dovro fare lb+lc

            #define n0 la+lb+lc+ld+lf
            #define n1 lb+lc
            #define n2 la+lb+ld+le+lg
            #define n3 la+lb+lc+ld+lg
            #define n4 lb+lc+lf+lg
            #define n5 la+lf+lg+lc+ld
            #define n6 la+lf+lg+lc+ld+le
            #define n7 la+lb+lc
            #define n8 la+lb+lc+ld+le+lf+lg
            #define n9 la+lb+lc+ld+lf+lg

            unsigned char numeri[] = {n0,n1,n2,n3,n4,n5,n6,n7,n8,n9};
            int timerlamp=0;

            //prototipi di funzione

            void setting (void);
            void main (void);
            void interrupt isr (void);

            void setting(void)
            {
            //setto le porte come uscite

            TRISA=0;
            TRISB=0;
            TRISC=0;
            TRISD=0;
            TRISE=0;

            //setto i registri per l’interrupt

            // Generato da PicTimer 1.0.1.0
            // © Bernardo Giovanni – http://www.settorezero.com
            // Codice valido per Hitec-C

            // Fosc :4MHz
            // Timer0 preload :6
            // Prescaler :4
            // Interrupt time :1,0000mS

            // OPTION
            // bit 0 -> PS0 Prescaler Rate Select bit 0
            // bit 1 -> PS1 Prescaler Rate Select bit 1
            // bit 2 -> PS2 Prescaler Rate Select bit 2
            // bit 3 -> PSA Prescaler assegnato a Timer0 (1=Watchdog Timer)
            // bit 4 -> T0SE Timer0 Signal Edge: 0=low->high 1=high->low
            // bit 5 -> T0CS Timer0 Clock Select: internal clock (1=T0CKI transition)
            // bit 6 -> INTEDG INTerrupt Edge (1=raise 0=fall)
            // bit 7 -> RBPU PortB PullUp (0=off 1=on)

            OPTION_REG=0b00000001;

            // INTCON
            // bit 0 -> RBIF PortB Interrupt Flag
            // bit 1 -> INTF RB0/INT Interrupt Flag
            // bit 2 -> T0IF Timer0 Interrupt Flag
            // bit 3 -> RBIE PortB Interrupt Enable (off)
            // bit 4 -> INTE INT Interrupt Enable (off)
            // bit 5 -> TMR0IE Timer0 Interrupt Enable (on)
            // bit 6 -> PEIE PEripheral Interrupt Enable (off)
            // bit 7 -> GIE Global Interrupt Enable (on)

            INTCON=0b10100000;

            // Preload Timer0
            // TMR0=8; // valore con correzione

            TMR0=8;

            }

  4. #10 da killer0007 il 26 marzo 2012

    killer0007 :
    assolutamente no,ecco il setting.h
    //settaggi
    #define tempolamp 1000
    #define display1 RD6
    #define portdis PORTB
    //ASSEGNO L’ATTIVAZIONE DI OGNI PORTA AL NUMERO DECIMALE CORRISPONDENTE
    //PER ATTIVARE LA PORTA RB6 DEVO SCRIVERE 64. INFATTI IL NUMERO BINARIO 1000000 CHE ATTIVA RB6
    //CORRISPONDE AL NUMERO 64 DECIMALE
    #define la 1
    #define lb 2
    #define lc 4
    #define ld 8
    #define le 16
    #define lf 32
    #define lg 64
    #define point RB7
    //ora in base ai numeri da comporre attivo le relative porte
    //per comporre il numero 1 dovrò attivare il segmento B e C del display
    //quindi la porta RB1 e RB2 quindi in binario 00000110 che in decimale equivale a 6 e quindi
    //dovro fare lb+lc
    #define n0 la+lb+lc+ld+lf
    #define n1 lb+lc
    #define n2 la+lb+ld+le+lg
    #define n3 la+lb+lc+ld+lg
    #define n4 lb+lc+lf+lg
    #define n5 la+lf+lg+lc+ld
    #define n6 la+lf+lg+lc+ld+le
    #define n7 la+lb+lc
    #define n8 la+lb+lc+ld+le+lf+lg
    #define n9 la+lb+lc+ld+lf+lg
    unsigned char numeri[] = {n0,n1,n2,n3,n4,n5,n6,n7,n8,n9};
    int timerlamp=0;
    //prototipi di funzione
    void setting (void);
    void main (void);
    void interrupt isr (void);
    void setting(void)
    {
    //setto le porte come uscite
    TRISA=0;
    TRISB=0;
    TRISC=0;
    TRISD=0;
    TRISE=0;
    //setto i registri per l’interrupt
    // Generato da PicTimer 1.0.1.0
    // © Bernardo Giovanni – http://www.settorezero.com
    // Codice valido per Hitec-C
    // Fosc :4MHz
    // Timer0 preload :6
    // Prescaler :4
    // Interrupt time :1,0000mS
    // OPTION
    // bit 0 -> PS0 Prescaler Rate Select bit 0
    // bit 1 -> PS1 Prescaler Rate Select bit 1
    // bit 2 -> PS2 Prescaler Rate Select bit 2
    // bit 3 -> PSA Prescaler assegnato a Timer0 (1=Watchdog Timer)
    // bit 4 -> T0SE Timer0 Signal Edge: 0=low->high 1=high->low
    // bit 5 -> T0CS Timer0 Clock Select: internal clock (1=T0CKI transition)
    // bit 6 -> INTEDG INTerrupt Edge (1=raise 0=fall)
    // bit 7 -> RBPU PortB PullUp (0=off 1=on)
    OPTION_REG=0b00000001;
    // INTCON
    // bit 0 -> RBIF PortB Interrupt Flag
    // bit 1 -> INTF RB0/INT Interrupt Flag
    // bit 2 -> T0IF Timer0 Interrupt Flag
    // bit 3 -> RBIE PortB Interrupt Enable (off)
    // bit 4 -> INTE INT Interrupt Enable (off)
    // bit 5 -> TMR0IE Timer0 Interrupt Enable (on)
    // bit 6 -> PEIE PEripheral Interrupt Enable (off)
    // bit 7 -> GIE Global Interrupt Enable (on)
    INTCON=0b10100000;
    // Preload Timer0
    // TMR0=8; // valore con correzione
    TMR0=8;
    }

    ho provato a compilare il tuo progetto sulla lezione “lampeggio led” con i file scaricati in fondo alla lezione e mi da lo stesso erroe;credo sia colpa dell’hi tech c 9.83 a questo punto

  5. #12 da peppino53 il 14 aprile 2012

    ciao Giovanni,
    sto realizzando un contatore che avanza a step di 1 secondo.
    ho utilizzato le nuove delay ed, in particolare ho utilizzato un pic 16f84 a 4Mhz.
    il clock regolarmente definito in Hertz, il ritardo scelto è DelayS(1) , ma quello ottenuto è almeno 4 sec.
    è un mio problema o le routine non sono tanto precise?
    cordiali saluti
    peppino

    • #13 da Giovanni Bernardo il 17 aprile 2012

      Mi pare strano, io le provai con l’oscilloscopio e andavano bene. Non è che hai sbagliato qualche settaggio, tipo la frequenza del quarzo? Ad ogni modo hai provato a mettere pure una serie di ritardi da 1 secondo, oppure 16 delayms da 250? Giusto per capire se fa lo stesso problema

  6. #14 da peppino53 il 17 aprile 2012

    se utilizzo il delay per far semplicemente lampeggiare un led è tutto ok.
    i problemi iniziano quando il circuito cresce. In effetti vorrei far suonare un cicalino piezo ad intervalli scanditi da due tempi che setto all’inizio.
    ho preso spunto dal tuo articolo sulla visualizzazione display in multiplexer ed ho aggiunto altre righe di codice.
    tutto ok con pic16f877 e quarzo 20Mhz.
    quando passo al quarzo a 4Mhz sia con lo stesso pic16f877 che con pic16f84 si rallenta il tutto. E’ la isr che rallenta il tutto?
    ho usato anche il delaybigms con lo stesso risultato.

    • #15 da Giovanni Bernardo il 17 aprile 2012

      Non ti saprei dire… Ma è probabile che l’ISR induca i ritardi in più. Ti conviene crearti una variabile con cui tenere il conteggio dei secondi. Quando ti serve il ritardo attivi un flag che in una ISR sul timer incrementa questo conteggio settando un altro flag, questo conteggio ti dura 4 secondi. Nel main rimani bloccato sul controllo di questo flag fino a che l’ISR non ne cambia lo stato.

  7. #16 da peppino53 il 17 aprile 2012

    ho anche fatto questa prova, cioè lasciare il delayS(1) ed usare l’interrupt ad ogni millisecondo e contarne 1000.
    per avere circa 1 secondo devo contare non più di trecento, altrimenti stesso risultato di 4 secondi. questo l’ho stabilito col real-pic ma devo verificarlo caricando il firmware sul pic16f84.
    incomincio a discolpare le routine di delay e a pensare che c’è qualcosa che mi sfugge , forse a livello di dichiarazione di clock. utilizzo comunque il recente compilatore con i nuovi mnemonici.
    intanto ti saluto e ti ringrazio per la tua consueta disponibilità.
    peppino

  8. #17 da peppino53 il 17 aprile 2012

    caro giovanni,
    ho caricato il pic16f84 col firmware realizzato utilizzando l’interrupt come base dei tempi e finalmente: tutto ok.
    mi è rimasta la curiosità di sapere come mai le routine delay non rispondevano.
    un’altra domanda: ho notato che in un altro articolo (orologio con pic16f628) utilizzi delay del compilatore.
    sono migliori delle altre? esistono anche per tempi tipo 1 secondo?
    cordiali saluti
    peppino

    • #18 da Giovanni Bernardo il 18 aprile 2012

      Il motivo per il quale non rispondono non te lo so dire. Le routine di delay del compilatore sono le più precise in assoluto, solo che puoi utilizzarle esclusivamente per valori costanti (come argomento non puoi mettere una variabile -residente in ram- ma solo un valore costante -rom-). Le routine di delay del compilatore ci sono solo per ms e us

  9. #19 da R3cycl0r il 21 aprile 2012

    Salve ragazzi, ho la sensazione che queste routines non vadano bene per PIC18, ho tentato in tutti i modi, ma non sono riuscito ad utilizzarle, mi appare sempre l’errore ‘#error please define PIC_CLK correctly’ :(
    Se conoscete qualche rimedio, sarei lieto di conoscerlo :)

  10. #20 da pipporippolo il 22 maggio 2012

    Perchè a me le librerie non funzionano ne con pic16f ne con pic 18f.
    Ho provato a fare delle modifiche a delay.c e sembra che il problema sia la definizione della funzione DelayUs(), in quanto se la lascio mi restituisce ove presente dei sintax erroe del tipo “)” expected e “;” expected, mentre se la tolgo non li da più, inoltre anche CLRWDT() mi restituisce un warning; function declared implicit int..qualcuno puo aiutarmi..fino adesso non ho trovato delle librerie che funzionassero..anche la i2c.h mi ha dato problemi e ho dovuto includere tutto il contenuto del file .h e .c nal mail..mi stanno facendo inpazzire..
    La mia versione di di MPLAB è la 8.84 mentre h tech c è la 9.83..

  11. #21 da pipporippolo il 22 maggio 2012

    Scusa ma rettifico cosa il messaggio postato prima…opssibilmente toglierlo adesso l’errore che mi da è #error please define PIC_CLK correctly..
    ovviamente PIC_CLK è definito correttamente..e cioè #define PIC_CLK 16000000 come suggerito all’inizio della pagina ma ad esempio non capisco perchè bisogna inserire #include “delay.c” e non #include “delay.h”

    • #22 da Giovanni Bernardo il 22 maggio 2012

      Dipende da come sono strutturate le funzioni e da come lavori. Se il file C si include lui l’H, allora includi solo il C. Se PIC_CLK è definito ma fa lo stesso errore, può darsi che lo definisci dopo aver incluso la libreria o comunque in un punto sbagliato.

  12. #23 da zeltnerg il 18 luglio 2012

    b. sera,
    a me funziona tutto tranne il ritardo
    DelayS(1); qualsiasi numero io ci scrivi dentro non lampeggia piu nulla.
    ho settato la freq a 20mhz nel main.c come sopra detto .
    dove sbaglio? uso un 16f877a
    grazie mille

  13. #24 da odessos il 29 dicembre 2012

    Salve a tutti, non capisco come mai utilizzando questa libreria Delay non mi permette di settare un tempo in us con la funzione DelayUs(x) inserendo il valore tramite una variabile, cioè se definisco una variabile “unsigned char tempo” e gli do il valore 100 dovrebbe darmi un ritardo di circa 100us, invece me lo da di 500/600us, se invece inserisco nella funzione il valore direttamente dentro le parentesi es. DelayUs(100) il ritardo è perfetto 100Us

    saluti
    Stefano

  14. #25 da apacchio il 23 febbraio 2013

    odessos :
    Salve a tutti, non capisco come mai utilizzando questa libreria Delay non mi permette di settare un tempo in us con la funzione DelayUs(x) inserendo il valore tramite una variabile, cioè se definisco una variabile “unsigned char tempo” e gli do il valore 100 dovrebbe darmi un ritardo di circa 100us, invece me lo da di 500/600us, se invece inserisco nella funzione il valore direttamente dentro le parentesi es. DelayUs(100) il ritardo è perfetto 100Us
    saluti
    Stefano

    Anche io ho lo stesso problema… :-(

  15. #27 da peppino53 il 1 giugno 2013

    ciao Giovanni,
    abilitando il watchdog, devo preoccuparmi di inserire l’istruzione di azzerare il watchdog prima che il suo avanzamento determina il reset del micro. cioè ho tempo pochi millisecondi o pochi secondi se utilizzo il prescaler per azzerare il watchdog.
    La domanda: se mi serve un ritardo di un minuto , nella routine di delay che devo utilizzare è già presente l’istruzione di azzerare il watchdog? o si pianta tutto?
    spero di essere stato chiaro.
    cordiali saluti
    peppino

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
settorezero.com e il logo Zroid™ ©2007÷2013 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 a cui vanno aggiunte le condizioni d'uso 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.
Creative Commons BY-NC-ND 2.5
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.
Per essere aggiornato con tutte le novità di settorezero.com seguici anche anche su Facebook Twitter Tumblr Blogspot Youtube.