moro Postat Martie 5, 2014 Partajează Postat Martie 5, 2014 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
costi002 Postat Martie 5, 2014 Partajează Postat Martie 5, 2014 incearca ceva de genul (tmr1Hx255)+tmr1L Link spre comentariu
mars01 Postat Martie 5, 2014 Partajează Postat Martie 5, 2014 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
costi002 Postat Martie 5, 2014 Partajează Postat Martie 5, 2014 nu mai pot edita, dar raspunsul pentru tine cred ca este result = TMR1H*256+TMR1L (nu 255 din primul post)succes Link spre comentariu
moro Postat Martie 5, 2014 Autor Partajează Postat Martie 5, 2014 O sa incerc, si revin cu un raspuns. Multumesc !! Link spre comentariu
brad Postat Martie 7, 2014 Partajează Postat Martie 7, 2014 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
Liviu M Postat Martie 7, 2014 Partajează Postat Martie 7, 2014 Am incercat sa unesc cei doi registrii din timer1De ce nu lucrezi cu CCPRxH, CCPRxL? Sunt pusi acolo special pentru asta. Asa ai scapa si de intrebarea capcana a lui brad (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. Link spre comentariu
mars01 Postat Martie 8, 2014 Partajează Postat Martie 8, 2014 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
Liviu M Postat Martie 8, 2014 Partajează Postat Martie 8, 2014 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 intreruperiDezactivarea 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
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum