Sari la conținut
ELFORUM - Forumul electronistilor

Cum bag registrii TMR1H si TMR1L intr-o singura variabila?


moro

Postări Recomandate

Va salut, am un pic16f887 caruia pe pin RC2 ( CCP1) ii aplic un semnal dreptunghiular pwm, caruia vreau sa-i citesc frecventa si s-o afisez pe un display

Am incercat sa unesc cei doi registrii din timer1 intr-o singura variabila "counter" care apoi s-o afisez pe un display 16x2 lcd

de test am pus un output pe pinul RB0 care sa fie updatat de intreruperea pe high edge si vad ca ccp-ul functioneaza ok, in sensul ca daca aplic 1526hz pe RC2, tot atat citesc si pe RB0, singura problema ramane cu timer-ul ala.

Sincer asta ar fi primul proiect cu timere....

 

void main() {T1CON=0X85;       // timer at Fosc/4 with 1:1 prescalerCCP1CON=0X05;       //     Capture mode, every rising edgeINTCON.GIE=1;  // enable global interruptsINTCON.PEIE=1; // enable peripherical interruptsPIE1.CCP1IE=1; // enable interrupts from CCP1 moduletrisc.rc2=1;trisd=0x00;trisb=0x00;portb=0x00;lcd_init();while(1) {   CCP1CON=0X05;  if (PIR1.CCP1IF) {    portb.rb0=1;    PIR1.CCP1IF = 0;    portb.rb0=0;   Hi(counter)= TMR1H; // 8 MSB   Lo(counter)= TMR1L;// 8 LSB   wordtostr(counter,freq);   lcd_out(1,1,freq);TMR1H=0; // reset timerTMR1L=0; // reset timerlcd_cmd(_lcd_clear);  }}}
Link spre comentariu
  • Răspunsuri 8
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • moro

    2

  • Liviu M

    2

  • costi002

    2

  • mars01

    2

Top autori în acest subiect

Nu stiu daca am inteles corect intrebarea dar concatenarea a 2 byte intr-un word se face asa:

 

int counter;counter = TMR1H << 8; //se shifteaza la stanga cu 8 pozitii TMR1Hcounter |= TMR1L; //se adauga TMR1L
Link spre comentariu

mars, costi:eu cred ca in solutiile date de voi (TMR1H*256 sau TMR1H<<8) trebuie facut 'casting'.adica: ((int)TMR1H<<8) + TMR1Lps: inmultirea cu 256 este tradusa de compilator tot intr-o deplasare la stanga cu 8.moro, mai ai o problema cand nu tratezi in intrerupere TMRx (adica acolo unde esti sigur ca TMRx a generat overflow) :este posibil sa incepi citirea lui TMRx cand are valoarea 0xFFFF, (TMRxH=0xFF, TMRxL=0xFF) .se poate intampla asa:1. citesti TMRxH=0xFF (si eventul faci si <<8 . deci pierzi timp)2. in timp ce ai facut pasul "1" , TMRx a devenit 0x0000 si citesti TMRxL=0x003. rezulta ca a fost TMRx=0xFF00 .... fals!4. cum crezi ca scapi de cazul asta particular ?

Link spre comentariu

Am incercat sa unesc cei doi registrii din timer1

De ce nu lucrezi cu CCPRxH, CCPRxL? Sunt pusi acolo special pentru asta. Asa ai scapa si de intrebarea capcana a lui brad :rade: (la varianta cu timer trebuie sa-i raspunzi singur).

In Capture mode, the CCPRxH, CCPRxL register paircaptures the 16-bit value of the TMR1 register when anevent occurs on pin CCPx.

@brad: oricum cred ca vorbim intre noi, moro n-a mai dat pe aici de vreo doua zile. :rade:
Link spre comentariu

mars, costi:eu cred ca in solutiile date de voi (TMR1H*256 sau TMR1H<<8) trebuie facut 'casting'.adica: ((int)TMR1H<<8) + TMR1Lps: inmultirea cu 256 este tradusa de compilator tot intr-o deplasare la stanga cu 8.moro, mai ai o problema cand nu tratezi in intrerupere TMRx (adica acolo unde esti sigur ca TMRx a generat overflow) :este posibil sa incepi citirea lui TMRx cand are valoarea 0xFFFF, (TMRxH=0xFF, TMRxL=0xFF) .se poate intampla asa:1. citesti TMRxH=0xFF (si eventul faci si <<8 . deci pierzi timp)2. in timp ce ai facut pasul "1" , TMRx a devenit 0x0000 si citesti TMRxL=0x003. rezulta ca a fost TMRx=0xFF00 .... fals!4. cum crezi ca scapi de cazul asta particular ?

De fapt casting-ul se face sau nu functie de compilator. Eu am folosit aceasta operatie cand, de ex, (procesor pe 8bit) recuperam valori pe 16bit scrise in EEPROM si nu am avut nevoie de casting cand am folosist operatii cu biti.Dar este si o greseala aici: variabila counter ar trebui sa fie un unsigned int sau un long (long-ul va fi ineficient dpdv al spatiului ocupat in memorie dar va rezolva problema). Daca TMR1H este gen 0b1xxxxxxx si rezultatul este stocat intr-o variabila tip INT, rezultatul ar avea o valoare negativa (parca Arianne s-a prabusit de la o problema de genul asta ???)Intrebarea la pct 4 este ori retorica ori cu intentie educativa dar se rezolva foarte usor cu disable / enable intreruperi (eventual salvare a starii registrului cu flaguri intrerupere inainte de disable, si restaurarea sa la finalul procesarii variabilei counter).
Link spre comentariu

De fapt casting-ul se face sau nu functie de compilator.

E "good practice" sa faci codul cat mai independent de compilator (recunosc ca si eu am tot lucrat fara casting). Ajuta, de exemplu, la portare mai usoara a codului pentru alt compilator. In cazul de fata, de exemplu, moro n-a zis ce compilator foloseste, asa ca poate la compilatorul lui o sa aibe probleme fara casting.

Intrebarea la pct 4 se rezolva foarte usor cu disable / enable intreruperi

Dezactivarea intreruperilor nu opreste timerul, acesta numara in continuare si eventuala problema ridicata de brad ramana. Ca sa nu mai numere/sa nu mai conteze ca numara, ori il opresti (pe timer), ori, in cazul de fata, faci cum am sugerat mai sus, folosesti registrii CCPRxH & CCPRxL.
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