Vai al contenuto
PLC Forum


Interrupt Con 16f876 - problemi


lukappa87

Messaggi consigliati

Salve ragazzi,

sono nuovo da queste parti...ma in questo campo già me la cavo abbastanza :lol:

Questi giorni ho messo su un modulo con pic 16F876 (XT 4Mhz) LCD hitachi (16x4) e interfaccia I2C con eprom 24c64...

Su questo pic ho "caricato" un programma fatto da me in C il quale legge le locazioni della eprom (HEX) e le converte in CHAR per poi visualizzare sull'LCD le varie parole.

Fin qui ci siamo :rolleyes:

Poi ho pensato di utilizzare le PORTE B come INPUT in modo da poter scrivere tramite una tastierina di un vecchio televisore (con i pulsanti di plastica sopra, tipo telecomando) ...comunque anche senza questa tastierina ma con interruttori normali , non riesco a gestire il programma.

Questo è un pezzo di programma che dovrebbe avviare la scrittura o lettura della eprom a seconda dei livelli forniti sulle porte B:


while(1){

   switch(PORTB){
   case 0b00000001:
   {
    LCD_CLEAR(); 
    
  DelaySec(1);
        LCD_CMD(LCD_line1); 
        LCD_PUTS("LETTURA EPROM");  
        DelaySec(1);
        
       crea(ad1,1);                       //lettura locazioni di memoria e stampa dei caratteri tramite funzione esterna
    DelaySec(1);             //dal nome "crea()"
       crea(ad2,2);
    DelaySec(1);                                                     
       crea(ad3,3);
    DelaySec(1); 
       crea(ad4,4);
    DelaySec(2); 
    LCD_CLEAR();    //fine chiamata funzione
     break;  
    }
   case 0b00000000:
    {
    LCD_CLEAR(); 
        h=41;
    let=(char)h;   
    p=1;
    LCD_CMD(LCD_line1); 
        LCD_PUTS("Srivi Eprom:");  
        LCD_GOTO(2,p);
    LCD_PUTCH(let);
    while(ok!=1){
  switch(PORTB){
                  case 0b00000100:{
      h++;
      LCD_GOTO(2,p);
      LCD_PUTCH(let);
      break;
    
      }
    case 0b00000010:{
      h--;
      LCD_GOTO(2,p);
      LCD_PUTCH(let);
      DelaySec(1);
          break;
      }
                  case 0b00001000:{
      ok=1;
      LCD_GOTO(3,1);
      LCD_PUTS("SCRITTURA OK");
      DelaySec(3);
           break;
      }
    }
      
                      }  
                             
                        }
     }   
      }    
}

...in poche parole : E' CORRETTO GESTIRE GLI INTERRUPT CON UNA "SWITCH CASE" ?

Che tensione devo faronire sulle porte di ingresso?

il mio problema sta nel fatto che quando metto a "+" le porte B:

1)L'LCD perde luminosità <_<

2)a volte si entra nelle condizioni di "case" e a volte no(quasi sempre no).

Ho letto che in assembly si gestiscono registri di interrupt.... INT ecc ecc non ricordo.

Gentilmente,qualcuno può aiutarmi? :(

Grazie

Lukappa87

Modificato: da Gabriele Corrieri
Link al commento
Condividi su altri siti


Per gestire un tastierino devi gestire alcune righe come ingressi e altre come uscite , il tutto con relative resistenze di pull-up.

Gli ingressi li gestisci sulle porte RB4-RB7 che ti danno un interrupt quando viene modificato anche un solo Bit di queste porte.

Da programma in pratica devi alzare un'uscita alla volta e vedere se c'e' qualche interrupt , se c'e' interroghi le porte di ingresso e in base all'uscita alzata capisci quale e' il pulsante premuto.

Ciao

Link al commento
Condividi su altri siti

quindi se voglio usare le porte B come ingressi devo usare solo le porte RB4-5-6-7?

Se utilizzo il comando

TRISB=1;

le imposto come ingressi...

posso impostare da RB0 a RB3 come uscite e da RB4 a RB7 come ingressi?

le resistenze da quanto devono essere? 270 ohm bastano?

Link al commento
Condividi su altri siti

Applica la legge di ohm ==> 5v/270 = 18.5mA nominali. Non ti sembrano troppi? Moltiplica la resistenza per 10

Link al commento
Condividi su altri siti

ho provato ma non mi funziona lo stesso! :huh:

Come poso risolvere? sarà problema di fuses?

io seleziono solo il PWRT

Ragà per favore un aiutino...

Grazie :(

Link al commento
Condividi su altri siti

Ti do un suggerimento per facilitare le cose. Dimentica gli interrupt per il momento, alza un'uscita e leggi gli ingressi, poi alza l'altra uscita e leggi gli ingressi, infine alzi la terza uscita e rileggi gli ingressi. Fai questa operazione ogni 10 ms circa così puoi anche farti un antirimbalzo quasi automatico

Link al commento
Condividi su altri siti

il mio problema sta nel fatto che quando ad esempio applico alla portab 0b00000001 e la funzione ad esempio è questa:

if(portab==0b00000001) 
   LCD_PUTS("CIAO")

NON si verifica sempre....

come mai ????????

non ho capito bene il fatto delle uscite e ingressi.

ciao

Modificato: da Gabriele Corrieri
Link al commento
Condividi su altri siti

ciao

le resistenze di pullup possono essere da 4.7k a 10 k io metto 10 k

l'esempio dei ingressi e uscite :

tu disponi di 4 uscite (per esempio) e di 4 ingressi (per esempio)

con la prima uscita "alimenti" la prima serie di 4 pulsanti che ,quando premuti, mandano tensione all'ingersso

cui sono collegate.

con la seconda uscita "alimenti " la seconda serie di 4 pulsanti , che qundo premuti, mandano tensione agli stessi ingressi cui sono collegati gli altri 4 pulsanti .

ecc. ecc,

ciclicamente : accendi la prima uscita e controlli quli bit sono a 1 (dei tuoi 4 ingressi dedicati dgli input)

poi "spegni" la prima uscita e "accendi" la seconda uscita e controlli quali bit sono a 1 (dei tuoi 4 ingressi dedicati agli input)

eccetera ecceteara

solitamente si fa una matrice di diodi per evitare ritorni di tensione ndesiserati.

anchio ti suggerisco di non utilizzare gli interrupt , per ora.

ad ogni modo sappi che all'interno degli interrupt e' bene scrivere meno che si puo'

perche ' si rischia di rallentare o perdere altri interrupt che nel frattempo avvengono

ciao

dario

Link al commento
Condividi su altri siti

mi spiego meglio...

io voglio ad esempio:

dato in RB7 un livello alto visualizzare "CIAO" sull'lcd

quindi nel programma metto una "if PORTB==0b10000000" allora .... etc" giusto?

quando io collego al pin "RB7" un filo collegato a +5V non entra in quella condizione.... come mai? :unsure:

Link al commento
Condividi su altri siti

ciao

molto semplice!

se qualche altro bit di quel byte e' a 1 la tua condizione non e' vera.

cioa' se sul port b c'e' "10001000" tu non entrerai nella condizione di "vero"

devi fare cosi'

if ((PORTB and 128)== 128 ){

allora bla bla bla

}

l'esempio e' scritto in "C" ma il senso e' comprensibile

cioe' tu devi testare solo il bit che ti interessa non tutta il byte

128 (decimale) e' il peso del bit 7 cioe' il piu' significativo del byte.

il and (&) serve a mascherare tutti gli altri bit ed il paragone con"128" serve

a capire se era a 1 (per effetto del and tutti gli altri vengono visti "0"

io , pero ' , non conosco i PIC .(ma la sostanza non cambia)

ciao

dario

Modificato: da Dario Valeri
Link al commento
Condividi su altri siti

Per leggere un ingresso devi

1) Impostare i TRIS della porta mettendo 0 per uscite e 1 per gli ingressi

ES: TRISB = 0b00001111 mette i bit 0-3 come ingressi e 4-7 come uscite

2) Devi testare il singolo bit come indicato da Valeri

per esempio se hai il compilatore della CCS c'e la funzione

if(!input(PIN_B4))

{

print_lcd("CIAO");

}

!input e' necessario in quantio che se metti una resistenza di pull-up da 10K (verso il positivo) e metti il pulsante

che tira verso lo 0V , avrai sempre 1 e 0 quanto premi il pulsante (ossia lavoro il logoca negata) e il ! in c singinifica fare il negato.

Ciao B)

Link al commento
Condividi su altri siti

ciao

si devi mettere un and solo.

ad ogni modo , ripeto non conosco i pic.

in estrema sintesi devi mascherare i bit che non sono oggetto di confronto , vedi tu come.

ricorda quello che ha scritto ifachsoftware , cioe' se hai dei pullup i tuoi pulsanti

tireranno l'ingresso a zero!

ciao

dario

Link al commento
Condividi su altri siti

Lukappa87, non lavoro spesso sui PIC ma ho avuto modo di giocarci spesso per divertimento, tra l'altro proprio con il 16F876.

Mi sento di darti un consiglio: scrivi i primi programmi in assembler ed impara come lavora l'oggetto, magari aiutandoti con un simulatore o con un debugger on-line. Il C è senz'altro più performante ma ti fa perdere la "sensazione delle cose".

Ciao.

Link al commento
Condividi su altri siti

sob sob pensavo fosse il contrario cioe' che scrivendo in C oppure in assembler

ci si renda conto piu' bene di come vanno le cose, aime' sono antiquato!!

Link al commento
Condividi su altri siti

ciao

.....anchio! infatti sto dicendo la stessa cosa!

sto dicendo che altri linguaggi , come il basic non sono indicati

per capire il funzionamento del micro ma per altre cose , per esempio

produrre in tempi brevi.

mi spiace non essermi spiegato bene, mi sebrava ovvio :) :)

ciao

dario

Link al commento
Condividi su altri siti

ok....

ho provato è lo compila... c'è un problema però...

con questa sintassi riesco a gestire le "if"....però l'LCD perde luminosità quando applico un livello alto...

Ho provato con le resistenze sia da 220 sia da 10K ma è come se non applicassi nessun segnale <_<

Come posso rimediare?

Un'altra domanda.... i fuses come devo impostarli? (non utilizzo timer interni)

Per il fatto dell'assembler...avete ragione ma richiede molto tempo...

Modificato: da lukappa87
Link al commento
Condividi su altri siti

ciao

devi aver sbagliato qualche collegamento.

l'LCD non puo' perdere di luminosita'!!!

egli ha la sua alimentazione e la sua regolazione di luminosita' esterna (trimer)

Link al commento
Condividi su altri siti

non penso di aver sbagliato...perchè il trimer l'ho messo e regolo il contrasto.

Il problema si verifica quando applico una tensione sui pin del pic...

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...