Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

PIC16F84 mikroBasic: mux display 7seg

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentefranx » 9 ago 2013, 10:20

Immagine


Questo programma per il multiplex di due display sette segmenti, non funziona bene.

Il problema sembrerebbe risiedere nell'interrupt

Proteus dà la stessa risposta della realizzazione: le cifre appaiono random, quando 22, quando 33,
quando alternativamente

Grazie

Codice: Seleziona tutto

' P16F84A
' 4MHz / XT
' mikroBasic 6.0.0 (free)

program COUNTER_UP

' ---------- G L O B A L   D E C L A R A T I O N S -----------------

' Global variables (the ones shared with ISR is qualified as 'volatile')

dim display_on as byte volatile  ' which display to activate? D1 or D2
dim mask_D2 as byte volatile     '  7seg mask for D2
dim mask_D1 as byte volatile     ' 7seg mask for D1



' ----------- F U N C / P R O C / I S R  ---------------------------------------

' The well known 7seg mask function

sub function mask (dim num as byte) as byte

select case (num)
   case 0   result =  %0111111
   case 1   result =  %0000110
   case 2   result =  %1011011
   case 3   result =  %1001111
   case 4   result =  %1100110
   case 5   result  = %1101101
   case 6   result =  %1111101
   case 7   result =  %0000111
   case 8   result =  %1111111
   case 9   result =  %1101111
end select

end sub


' --- Interrupt routine (unique for all the interrupt)

sub procedure interrupt()

     if INTCON.T0IF=1  then  ' overflow timer0?
     
        INTCON.T0IF = 0          ' reset flag interrupt Timer 0

        select case (display_on)

             ' --- switch on D1
             case 1
                 PORTA.1 = 0                  'switch off D2
                 PORTA.0 = 1                  'switch off D1
                 PORTB = mask_D1           
                 display_on = 2               'next int. will be switched on  D2

             ' --- switch on D2
             case 2
                 PORTA.1 = 1                  'switch on D2
                 PORTA.0 = 0                  'switch off D1
                 PORTB = mask_D2     
                 display_on = 1               'next int. will be switched on D1

        end select
       
      end if

    TMR0 = 0                 ' reset TMR0
    INTCON.INTE = 1          ' enable again all ints.

end sub


' --------------  M  A  I  N ---------------------------------------

main:
   '   Main program
   
   dim n as byte            ' counting variable: 0..99

  ' --- set direction data
   TRISB = 0         ' RB7...RB0 all out (7seg LED)
   TRISA.0 = 0       ' RA0 out (drive D1)
   TRISA.1 = 0       ' RA1 aout (driver D2)


   ' --- clear outputs
   PORTB = 0        ' Pin RB7..RB0 all at 0V
   PORTA.0 = 0      ' Pin RA0 at 0V
   PORTA.1 = 0      ' Pin RA1 at 0V


' --- Config. Timer 0
   
   TMR0 = 0

   OPTION_REG.PSA = 0 '  int. clock is for timer0 (not for w/dog)
   OPTION_REG.PS0 = 1 '  prescaler 16 (256*16)*4*1usec <-> above 100 Hz refresh
   OPTION_REG.PS1 = 1 '     "          "
   OPTION_REG.PS2 = 0 '     "          "

   INTCON.GIE = 1                'enable all ints
   INTCON.T0IE = 1               'enable timer0 int overlow
   INTCON.T0IF = 0               'clear flag T0IF
   OPTION_REG.T0CS = 0       'start the timer (?)

   n = 0                        'count start from o
   display_on = 1           'the first display to switch on is D1

   while 1
       
         mask_D1 = mask(n / 10)
         mask_D2 = mask(n mod 10)

        delay_ms (500) '**** I have to pass 500 to obtain 1000ms  *****

        if n = 99                 ' reached 99?
           then n = 0             ' ... start again from 0
        end if
       
        n = n + 1                 ' increment of 1

   wend

end.

Avatar utente
Foto Utentefranx
465 3 10
Frequentatore
Frequentatore
 
Messaggi: 199
Iscritto il: 28 feb 2010, 17:43

0
voti

[2] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentec1b8 » 9 ago 2013, 11:30

Non ho modo di provarlo, ma proverei a cambiare questa
Codice: Seleziona tutto
mask_D1 = mask(n / 10)

in questa
Codice: Seleziona tutto
mask_D1 = mask(n div 10)


Cosa cambia (se cambia)?
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[3] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentefranx » 9 ago 2013, 12:09

c1b8 ha scritto:Cosa cambia (se cambia)?


Ti ringrazio per la risposta.

Non cambia niente. Anche mettendo un 16F628A

Con il debugger di mikroBasic le cifre vengono "splittate" correttamente. E' sull'interrupt che va in crisi.

In fondo è un codice preso per mikroC (della stessa mikroElektronica) e riadattato in mikroBasic

O sono io che non c'ho capito nulla dei timer e della gestione degli int. con i PIC16F (forse abituato troppo bene con gli AVR :D o è il mikroBasic che ha comportamenti strani.

Per esempio, prima che non funzionasse, avevo dovuto mettere 500ms di ritardo per averne uno da 1s

Sul forum di mikroBasic ho trovato uno che aveva avuto lo stesso problema
Avatar utente
Foto Utentefranx
465 3 10
Frequentatore
Frequentatore
 
Messaggi: 199
Iscritto il: 28 feb 2010, 17:43

0
voti

[4] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentec1b8 » 9 ago 2013, 12:31

Che fosse necessario indicare un valore inferiore a 1000 nella delay per ottenere un ciclo da 1 s me lo aspettavo, ma metà sinceramente mi sembra troppo.
Hai verificato nelle proprietà del progetto quale frequenza di clock è indicata debba lavorare il micro? e questa corrisponde poi alla reale frequenza?

Nella routine di interrupt non vedo nulla di particolare, vediamo se ho capito bene il problema:
i due display presentano sempre la stessa cifra e sembra casuale non si incrementa come ti aspetti.
E' giusto?
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[5] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentefranx » 9 ago 2013, 13:42

c1b8 ha scritto:i due display presentano sempre la stessa cifra e sembra casuale non si incrementa come ti aspetti.
E' giusto?


Allora ho tolto incremento di n, delay() ecc. ed ho messo la visualizzazione di un numero costante

Codice: Seleziona tutto
n = 45


la variabile n è inizializzata prima di entrare nel while 1

Il comportamento che ottengo (simulato con Proteus, ma è lo stesso identico della realizzazione, l'ho ricostruito facendo una simulazione passo-passo con Proteus.

Lo descrivo di seguito:

Codice: Seleziona tutto
Si accende solo D2: 5

Si spengono entrambi

Si spengono entrambi

Si accende solo D1: 5

Si accendono contemporaneamente D1 e D2: 4  e 4

Si accende solo D1: 5

Si accende solo D1: 4

Si accendono contemporaneamente D1 e D2: 4 e 4

Si spengono entrambi

Si spengono entrambi

Si accendono contemporaneamente D1 e D2: 4 e 4

Si accende solo D1: 5

Si accende solo D2: 4

Si accende solo D1: 5

Si accende solo D1: 4

Si accendono contemporaneamente D1 e D2: 4 e 4

Si spengono entrambi

Si spengono entrambi

Si accende solo D1: 5

Si accende solo D1: 4

Si accende solo D2: 5


I tempi fra le varie accensioni sono percettibili, all'ordine del secondo o poco meno.

Il simulatore di Proteus va in warning, indicando un eccessivo uso della CPU.

PS Provo a dis-installare mikroBasic e installare l'ultima versione
Avatar utente
Foto Utentefranx
465 3 10
Frequentatore
Frequentatore
 
Messaggi: 199
Iscritto il: 28 feb 2010, 17:43

2
voti

[6] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentec1b8 » 9 ago 2013, 13:55

Potresti provare a cambiare la routine di interrupt come segue:
Codice: Seleziona tutto
    sub procedure interrupt()

         if INTCON.T0IF=1  then  ' overflow timer0?
         
            select case (display_on)

                 ' --- switch on D1
                 case 1
                     PORTA.1 = 0                  'switch off D2
                     PORTB = mask_D1           
                     PORTA.0 = 1                  'switch off D1

                 ' --- switch on D2
                 case 2
                     PORTA.0 = 0                  'switch off D1
                     PORTB = mask_D2     
                     PORTA.1 = 1                  'switch on D2

            end select

            display_on = display_on xor 3
           
            TMR0 = 0                 ' reset TMR0
            INTCON.T0IF = 0          ' reset flag interrupt Timer 0
          end if
    end sub
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

0
voti

[7] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentefranx » 9 ago 2013, 17:09

c1b8 ha scritto:Potresti provare a cambiare la routine di interrupt come segue:


excellent...funziona

mi è piaciuto molto l'ex-or, che risolve con molta eleganza la commutazione del display :ok:

P.S. Ho guardato riga per riga il tuo codice. Mettendo questo tuo pezzo di codice:

Codice: Seleziona tutto
TMR0 = 0                 ' reset TMR0
INTCON.T0IF = 0          ' reset flag interrupt Timer 0


invece di quello che avevo messo io:

Codice: Seleziona tutto
TMR0 = 0                 ' reset TMR0
INTCON.INTE= 1       ' abilitazione di int. su RB0 ?!?!?!


Facevo il clear del flag T0IF, all'ingresso dell'ISR e non all'uscita

All'uscita andavo ad abilitare l'int su RB0 (infatti stavo facendo delle prove con un interrupt su un pulsante posto su RB0)

Era lì l'inghippo :D

Grazie 1000
Avatar utente
Foto Utentefranx
465 3 10
Frequentatore
Frequentatore
 
Messaggi: 199
Iscritto il: 28 feb 2010, 17:43

0
voti

[8] Re: PIC16F84 mikroBasic: mux display 7seg

Messaggioda Foto Utentec1b8 » 9 ago 2013, 17:19

:ok:
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 10 ospiti