Sari la conținut
ELFORUM - Forumul electronistilor

Probleme intrerupere pic16f84A


wwwglro

Postări Recomandate

Salut.Am realizat un program care face urmatoarele:-seteaza port a ca intrare si port b jumata intrare jumate iesire (RB4-RB7 ca intrare).-Am definit 2 taste pe intrarile A0 si A1 si 2 leduri pe B0 si B1.Atunci cand apas tasta 1, ledul nr 1 lumineaza ptr 5 secunde si apoi se stinge.Cand apas tasta 2m, ledul 2 lumineaza pentru 5 secunde si apoi se stinge.As vrea ca atunci cand apas tasta 2 cat timp ledul nr. 1 lumineaza, acesta sa se stinga (intrerupere) si sa lumineze ledul 2 si invers, cand apas tasta 1 cat timp ledul nr. 2 lumineaza, acesta sa se stinga (iar o intrerupere) si sa se aprinda ledul 1.Programul l-am facut in CCS.Daca aveti idee cum as putea lucra cu intreruperi in acest caz...raman dator...Merci

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

Top autori în acest subiect

  • wwwglro

    8

  • ohamoha

    5

  • ratza

    2

Top autori în acest subiect

Nu ai spus ce oscilator folosesti. Sa zicem ca ai unul de 4Mhz. Asta inseamna ca intreruperea se va activa de 4000000/4*256=3906 ori pe secunda.

Acestea fiind zise, eu as face asa:

long bec0=1;long bec1=1;#int_rtccvoid clock_isr() {  bec0--;  bec1--;  if(bec0<1) bec0=1;  if(bec1<1) bec1=1;  if(bec0>1)    output_high(pin_b0);    else    output_low(pin_b0);  if(bec1>1)    output_high(pin_b1);    else    output_low(pin_b1);}void main(){set_rtcc(0);setup_counters (RTCC_INTERNAL, RTCC_DIV_1);enable_interrupts (INT_RTCC);enable_interrupts(GLOBAL);do {  if(input_state(PIN_a0)==0) //daca butonul este legat ca in imaginea atasata, cu o rezistenta "pullup"  {    bec0=19530; //3906*5 secunde    bec1=1;  }  if(input_state(PIN_a1)==0)  {    bec1=19530; //3906*5 secunde    bec0=1;  }} while(1);}

N-am compilat sursa asta, am scris-o acum la repezeala. Scuze daca am scapat greseli. Dar ai prins ideea.

Link spre comentariu

Salut si merci pentru raspuns.

Programul merge foarte bine dar...ca sa inteleg si eu:

- oscilatorul este de 4MHz.

- ai initializat timerul 0

- nu prea inteleg de ce folosesti variabilele bec0 si bec1; cumva incrementezi sau decrementezi o variabila de cate ori se reinitiaza timerul 0 adica cant trece de la 255 la 0 si numara iar?

- daca se doreste un timp mai mic in care sta aprins ledul se face 3906 * (timpul cat vreau sa fie aprins ledul)? si de ce se face chestia asta?

-de ce decrementezi in functia intrerupere cele 2 variabile la inceput?

Daca vreau ca montajul sa faca altceva, trebuie modificat corpul functiei intrerupere cred...nu? In acest sens cum intervin valorile lui bec0 si bec1 de 19530 din programul principal in corpul functiei intrerupere?

- in corpul functiei intrerupere, de ce compari bec0 si bec1 cu 1?

 

Deocamdata atat...

Merci.

Link spre comentariu

bec0 si bec1 sunt doua variabile long. Adica pot lua valori intre 0 si 65535. In functie de ele aprind sau sting LED-ul.

Gandeste-te la ele ca la doua vase cu apa, care au o gaura in fund. Atata timp cat este apa in ele, LED-ul corespunzator sta aprins. Apa se scurge incetisor pana cand vasul se goleste si LED-ul se stinge.

Daca in variabila bec0 pun 19530, intreruperea decrementeze variabila cu 1 la fiecare activare. Astfel ca pana epuizeaza variabila, LED-ul sta aprins. Calculand, 19530 ajunge cam pentru 5 secunde.

Vezi ca in primele doua randuri din intrerupere fac decrementarea. Astfel "golesc" variabilele putin cate putin.

 

Daca vrei un timp mai scurt in care LED-ul sa stea aprins, modifici valoarea 19530. Cu cat e mai mica, cu atat "pui" mai putina apa in vasele bec0 si bec1 si se scurge mai repede.

 

Sursa asta se aplica la cerinta ta de a aprinde alea doua leduri. Daca vrei sa faca altceva, probabil trebuie regandit algoritmul. Depinde de ce vrei sa faci.

 

In programul principal, modificand variabilele bec0 si bec 1 "umplu" sau "golesc" cele doua vase. Cerinta ta era ca atunci cand este un LED aprins, automat celalalt trebuie stins. Asa ca in momentul in care "umplu" bec0, trebuie sa "golesc" bec1, actiune care va determina stingerea LED-ului 1.

Compar bec0 si bec1 cu 1 pentru ca nu vreau sa le las sa ajunga la 0.

if(bec0<1) bec0=1;if(bec1<1) bec1=1;
Pentru ca daca bec0 este 0, si execut bec0--, bec0 nu va deveni -1 ci 65535. Pentru ca long-ul este unsigned in sursa mea.

Poti sa scrii mai simplu: (eu m-am complicat cand am scris sursa :nas: )

if(bec0>0) bec0--; //decrementeaza numai daca bec0 este mai mare decat 0. daca e 0, lasa-l 0
Ideea e sa nu lasi variabila sa pice sub 0.
Link spre comentariu

Cînd cade sub zero e de preferat s? reini?ializezi cu valoarea maxim? pe care o poate lua variabila, de exemplu 65535 (0xFFFF) pentru 16 bi?i f?r? semn, aka unsigned int. long e pe 32 de bi?i.

Link spre comentariu

Am postat cam repede pe forum inainte sa rumeg un pic programul.Am inteles ce fac cele 2 variabile. (nu stiam partea cu sa nu cada sub zero cele 2)Se complica treaba daca vreau sa fac ca cele 2 leduri sa clipeasca intermitent (pe rand )...

Link spre comentariu

Nu neaparat. Eu personal ma feresc sa pun delay-uri in intreruperi, dar de dragul rapiditatii, poti sa faci si asta.

Inlocuieste codul asta:

  if(bec0>1)    output_high(pin_b0);    else    output_low(pin_b0);  if(bec1>1)    output_high(pin_b1);    else    output_low(pin_b1);
Cu asta:

  if(bec0>1)    output_high(pin_b0);  if(bec1>1)    output_high(pin_b1);    delay_ms(250);    output_low(pin_b0);    output_low(pin_b1);    delay_ms(250);
Dar trebuie recalculat numarul ala 19530, pentru ca acum intreruperile vor surveni mult mai rar datorita delay-ului. Pentru 5 secunde bec0=10 daca ma gandesc bine.
Link spre comentariu

Am mai modificat un pic valorile lui bec pana a fost bine. (bec=7 si delay de 300ms) Problema care am observat-o la simulare este urmatoarea: cand apas scurt pe buton nu se intimpla nimic. Trebuie sa tin apasat pe buton un timp mai lung (aproape o secunda) pentru ca ledul aferent sa inceapa sa clipeasca(la fel se intimpla cand apasa celalalt buton - adica cand apelez intreruperea). Merci

Link spre comentariu

Daca nu am definit in main() care sunt porturile de intrare si care sunt cele de iesire, e normal ca programul de mai sus (postul nr. 2) sa functioneze?E suficient sa declar if(input_state(PIN_a0)==0 pentru a sti microcontrolerul ca pinul A0 este de intrare?Eu stiam ca porturile trebuiesc initializate la inceputul programului in main(){}.set_tris_a(0x00); //initializare port A ca intrareset_tris_b(0xff); //initializare port B ca iesireoutput_b(0x00); //seteaza port B in zeroMerci.

Link spre comentariu

Va mai cer ajutorul un pic.

La programul din postul 1: daca se apasa o tasta sa lumineze un led ptr 5 secunde, daca se apasa cealalta tasta (intrerupere) sa lumineze celalalt led DAR daca se detecteaza ca apasarea de tasta a durat mai mult de jumatate de secunda, ledul aferent tastei respective sa se stinga cand se elibereaza tasta aferenta.

Merci

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