Sari la conținut
ELFORUM - Forumul electronistilor

problema cu intreruperi la un PIC 16F877


vlad_2770

Postări Recomandate

Folosesc intreruperea externa de pe RB0, si intreruperea de la pinii RB(4-7). Pe RB4 am un buton pe RB5 am al doilea buton si pe RB0 am un receptor IR.In program am urmatoarele linii de cod: INTE = 1; RBIE = 1; GIE=1;si in rutina de intreruperi am : INTE=0; GIE=0; RBIE=0; if(RBIF) { cod pentru a executa ceva } if(INTF) { cod pentru a executa ceva } INTE=1; RBIE =1; GIE=1; INTF=0; RBIF=0;problema este ca nu merge.am pus prima data in rutina de intrerupere doar if(RBIF) { cod pentru a executa ceva } si programul face ce trebuie,am sters apoi ai am pus in rutina de intreruperi doar codul ce trebuie executat cind INTF=1 dar fara a scrie si if(INTF) {si programul merge si face ce trebuie.daca adaug si if(RBIF) {programul o ia razna Si daca pun ambele programul nu merge. Stiu ca sigur gresesc undeva dar nu imi dau seama. As dori o sugestie ,multumesc.

Link spre comentariu
  • Răspunsuri 11
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • cirip

    4

  • vlad_2770

    4

  • psanyi

    2

  • CristianC

    1

Top autori în acest subiect

Incearca sa nu faci GIE=1 in rutina de intrerupere. Poti intra din nou in intrerupere, se revarsa stiva si prog o ia razna. De asemenea, nu e nevoie sa faci GIE=0 la intrare. Asta se face automat. Nu uita sa resetezi flagurile de intrerupere prin soft.Cirip

Link spre comentariu
Vizitator alex

Scapa de

INTE=0;GIE=0;RBIE=0; 
si

INTE=1;RBIE =1;GIE=1;INTF=0;RBIF=0;
la inceputul si sfarsitul rutinei de intrerupere.

 

Continutul rutinei de intrerupere trebuie sa arate asa:

if(RBIF){cod pentru a executa cevaRBIF=0;}if(INTF){cod pentru a executa cevaINTF=0;}
Link spre comentariu

Am incercat sa fac asa cum a zis tu alex si cirip dar :( nu mi-a mers de la inceput. Separat mi-au mers doar daca am pus pentru RB0: INTE=0; //NEAPARAT BAGATE ACESTE DOUA LINIII!!!! GIE=0; //NEAPARAT BAGATE ACESTE DOUA LINIII!!!!si la sfarsit : RBIE =1; GIE=1;altfel nu reuseam sa execut codul din rutina de intreruperi pentru RB0.in schimb daca las numai : if(RBIF) { if(RB4==0) { cod de executat } else if(RB5==0) { cod de executat } RBIF=0; }programul are o executie ciudata, in sensul ca daca apas pe buton face ce trebuie dar nu merge daca tin butonul apasat mai mult timp. Pentru o noua actiune trebuie sa apas din nou. Deci mentinerea butonului apasat nu are nici un efect. Deci daca vreau sa decrementez un contor sau sa il incrementez trebuie sa apas pe buton de n ori ca acel contor sa se incrementeze sau sa se decrementez ecu n pasi nu merge sa tin apasat si contorul sa se decrementeze. Sunt sigur ca e ceva soft ca am schimbat pic-urile si nici din montaj nu e ceva aiurea ca pe bucati merge codul, impreuna nu vrea.

Link spre comentariu

Deci mentinerea butonului apasat nu are nici un efect

Normal! Cred ca nu citesti cu atentie foaia de catalog. Exact la inceputul paragrafului care vorbeste despre INT scrie ca "the RB0/INT pin is edge triggered", adica trebuie sa se produca o schimbare pentru a genera o intrerupere.

INTE=0; //NEAPARAT BAGATE ACESTE DOUA LINIII!!!! GIE=0; //NEAPARAT BAGATE ACESTE DOUA LINIII!!!!

E ciudat. In manual la paragraful despre intreruperi scrie:"When an interrupt is responded to, the GIE bit iscleared to disable any further interrupt"Deci resetarea lui GIE se face automat la acceptarea unei cereri de intrerupere. In plus, daca ai resetat GIE, nu este nevoie sa resetezi si INTE. GIE este global si ai blocat orice intrerupere indiferent din ce sursa ar proveni. Sugestia mea e sa frigi un pic pe simulator si s aurmaresti ce se intampla cu GIE la intrarea intr-o intrerupere, indiferent de unde ar veni ea. Poti chiar sa creezi un stimul care sa mimeze o intrerupere pe RB0/INT.Bafta!CiripEDIT: Acum mi-am dat seama... De faci test pe RBIF daca vrei sa folosesti INT? Ala e flagul de interrupt on change la portul B, aplicabil la RB7...RB4. Daca folosesti INT, atunci trebuie sa cliruiesti INTF inainte sa iesi din intrerupere. Probabil ca comportarea ciudata se datoreaza faptului ca nu cliruiesti INTF si cum ai iesit din intrerupere, ai si intrat la loc, chiar daca evenimentul a expirat. Pe de alta parte, daca vrei sa folosesti interrupt on change in loc de RB0/INT, inainte de a clirui RBIF, trebuie sa faci o citire a portului pentru a elimina conditia de mismaci, altfel intra inapoi in intrerupere.
Link spre comentariu

cirip uite exact ce am:bucata asta de cot merge:#pragma interrupt_level 1static void interrupt executie(void){ if(RBIF) {aa: if(RB4==0) { a13(); afisare(aa); aa=0; DelayMs(50); if(RB4==0) goto aa; }bb: if(RB5==0) { a14(); afisare(aa); aa=0; DelayMs(50); if(RB5==0) goto bb; }}si asta merge fara sa pun GIE sau alte chestiidaca la asta mai pun si:#pragma interrupt_level 1static void interrupt executie(void){ if(RBIF) {aa: if(RB4==0) { a13(); afisare(aa); aa=0; DelayMs(50); if(RB4==0) goto aa; }bb: if(RB5==0) { a14(); afisare(aa); aa=0; DelayMs(50); if(RB5==0) goto bb; } if(INTF) { ir_read(); functie_taste(); afisare(aa); aa=0; DelayMs(1); INTF=0; }}nu mai merge. De simulat nu prea pot sa simulez ca ... nu am un compilator cumparat si asta spart nu ma lasa sa simulez si starile iesirilor de la porturi. Iar ce pot sa simulez este doar folosind de la inceput : INTE = 1; RBIE = 1; GIE=1;// INTF=1;// RBIF=1;si las ori INTF=1 ori RBIF=1; SI intradevar nu trebuie sa fac GIE , INTE sau RBIE egale cu 0 in interiorul rutinei.deci la codul de mai sus ma refeream ca nu merge daca le pun pe ambele, adica apas pe buton ca sa se incrementeze ceva si daca tin apasat nu continua, iar daca las doar prima parte merge OK! Stiu ai sa spui ca daca am programul spart de asta nu merge dar ... :) imi doresc sa nu fie de aici eroarea ci sa fie o greseala in codul scris de mine.

Link spre comentariu

1. Este posibil ca programul sa ramana blocat in partea de cod pe care o adaugi: if(INTF) { ir_read(); functie_taste(); afisare(aa); aa=0; DelayMs(1); INTF=0; } Este posibil sa nu revina din functia ir_read(). Incearca fara ea si vezi ce se intampla.2. In C este preferabil sa nu folosesti etichete (face codul mai greu de inteles). In loc de: bb: if(RB5==0) { a14(); afisare(aa); aa=0; DelayMs(50); if(RB5==0) goto bb; }poti sa scrii:while(RB5==0) { a14(); afisare(aa); aa=0; DelayMs(50); }

Link spre comentariu

Stiu ai sa spui ca daca am programul spart de asta nu merge dar

Nu, stai linistit, nu o sa spun asta, desi ar fi o cale usoara pentru mine de scapa, fara sa spun ca nu stiu :yawinkle: :yawinkle: :weedman: Adevarul este ca nu ma descurc, mai ales ca modul in care e scris e putin diferit de cum sunt eu obisnuit. Mai exact, asa cum spunea si CristianC, este neuzual sa pui etichete si sa folosesti goto in C.De asemenea, eu scriu numai in asamblare ptr PIC. In felul asta stiu exact cine misca si pot folosi MPLAB-ul, care are un simulator meserias. Din cate stiu exista compilatoare care conlucreaza cu MPLAB si permit simularea.In al treilea rand, fara simulator nu poti face mare lucru. Cand scriu cate un programel, simularea si testarea reactiei la diverse scenarii de stimuli externi consuma mai mult de jumatate din timpul de dezvoltare. E foarte greu sa "ghicesti" ce face procesorul, mai ales cand ai functii C in care numai programatorul stie ce a pus. De multe ori, chiar cand am scris in C, a trebuit sa simulez asm-ul rezultat in urma compilarii, ca sa vad ce nu merge. Imi pare rau, dar nu te pot ajuta mai departe de aici. Poate au vreo sugestie cei cu mai multa experienta. Parerea mea este, insa, ca fara simulator e greu sa ajungi prea departe.Cirip
Link spre comentariu

IN FINAL AM REUSIT SA REZOLV PROBLEMA.

 

FOARTE BUNA A FOST URMATOAREA REMARCA:

 

In C este preferabil sa nu folosesti etichete (face codul mai greu de inteles).

 

A fost o cauza, a doua cauza ... ar fi o chestie ciudata, in cadrul

 

if(INTF)

{

cod pentru a executa ceva

}

 

cod pentru a executa ceva de fapt erau multe linii de program si la o rulare atenta am vazut ca daca aveam liniile intr-o conditie ( if )

contor++;

contor++;

si mai jos aveam la fel in alt if

contor++;

contor++;

 

se sa rea dintr-o conditie in alta cu toate ca nu am inteles de ce;

am facut contor=contor+2 si a mers.

 

si am luat codul si l-am spart in mai multe functii micute si a mers asa cum au zis cei care au scris mai sus.

 

CIRIP ai dreptate ca daca faci simulare gasesti greseala dar e tare aiurea sa faci atata simulare pas cu pas ca imi ia o multime de timp. E pentru prima data cind am facut asta asa mult si imi este lehamite. Ai cred o rabdare de fier!!!

 

VA MULTUMESC FOARTE MULT PENTRU AJUTOR SI ... CULMEA ESTE CA DE LA FIECARE AM LUAT CITE CEVA CARE M-A AJUTAT SA REZOLV PROBLEMA. Mai ales ca prima data credeam ca sunt in zona crepusculara de nu imi iese ce vreau.

 

 

 

 

Link spre comentariu

In primul rand, felicitari ca ai gasit problemutza. Pe urma:

e tare aiurea sa faci atata simulare pas cu pas

Pai nu rulezi totul pas cu pas. De aia s-au inventat break-point-urile sau "run to here". Rulezi la viteza maxima pana in zona in care banuiesti ca e o problema, apoi rulezi 5-10 instructiuni pas cu pas. Ai dreptate ca la cateva mii de linii de cod, iti creste barba pana rulezi totul pas cu pas.Cirip
Link spre comentariu
IN FINAL AM REUSIT SA REZOLV PROBLEMA.

 

FOARTE BUNA A FOST URMATOAREA REMARCA:

 

In C este preferabil sa nu folosesti etichete (face codul mai greu de inteles).

 

A fost o cauza, a doua cauza ... ar fi o chestie ciudata, in cadrul

 

if(INTF)

{

cod pentru a executa ceva

}

 

cod pentru a executa ceva de fapt erau multe linii de program si la o rulare atenta am vazut ca daca aveam liniile intr-o conditie ( if )

contor++;

contor++;

si mai jos aveam la fel in alt if

contor++;

contor++;

 

se sa rea dintr-o conditie in alta cu toate ca nu am inteles de ce;

am facut contor=contor+2 si a mers.

 

si am luat codul si l-am spart in mai multe functii micute si a mers asa cum au zis cei care au scris mai sus.

 

CIRIP ai dreptate ca daca faci simulare gasesti greseala dar e tare aiurea sa faci atata simulare pas cu pas ca imi ia o multime de timp. E pentru prima data cind am facut asta asa mult si imi este lehamite. Ai cred o rabdare de fier!!!

 

VA MULTUMESC FOARTE MULT PENTRU AJUTOR SI ... CULMEA ESTE CA DE LA FIECARE AM LUAT CITE CEVA CARE M-A AJUTAT SA REZOLV PROBLEMA. Mai ales ca prima data credeam ca sunt in zona crepusculara de nu imi iese ce vreau.

 

 

 

 

 

Da, asta este adevarat.Depinde ce compilator este si cum are optiunile de compilare setate.Sunt optiuni de optimizare care omit linii din sursa fara rost. Folosesc avr-gcc (bineinteles pt ATMEL) care traduce limbajul de nivel inalt in limbaj de asamblare si comenteaza liniile unde s-au facut optimizari. Si inca ceva. Intr-o rutina de deservire a intreruperii e bine ca variabilele sa fie declarate ca volatile(pt ca sa ramana actualizate dupa ce se iese din rutina sau functie)

 

volatile int contor = 0;  /*variabila globala contor*/INTERRUPT(SIG_OVERFLOW0){  /*rutina de deservire timer0*/       contor++;  /* incrementare contor */}int main(void){  if(contor){ /*daca contor nu este declarat volatile aici va avea val 0*/     .....   }  for(;;){ /* bucla fara sfarsit */  }    return 0}
Succes !
Link spre comentariu

Deci mentinerea butonului apasat nu are nici un efect. Deci daca vreau sa decrementez un contor sau sa il incrementez trebuie sa apas pe buton de n ori ca acel contor sa se incrementeze sau sa se decrementez ecu n pasi nu merge sa tin apasat si contorul sa se decrementeze. Sunt sigur ca e ceva soft ca am schimbat pic-urile si nici din montaj nu e ceva aiurea ca pe bucati merge codul, impreuna nu vrea.

Pt folosirea butoanelor e bine sa folosesti o mica temporizare dupa apasarea unui buton (debounce) cam in jur de 1 ms, pt a evita contactele parazite (contacte multiple) dupa care citesti din nou portul si daca se gaseste acelasi rezultat se apeleaza functia butonului.[/code]
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări