sz3bbylA Postat Aprilie 24, 2011 Partajează Postat Aprilie 24, 2011 16f877 nu are internal oscilator eu folosesc extern 20mhz iar in pdf-ul picului nu am inteles prea bine cum sta treaba cu tmr0 ma intereseaza sa folosesc o intrerupere tmr0 la 1 us si nu am inteles exact cum sa fac pe un site am gasit ca 16f877 are pt tmr0 internal 4mhz (ceea ce nu am gasit deloc in documentatia picului) http://www.microcontrollerboard.com/pic-timer0-tutorial.html - ma bulversat de tot asta incerc sa creez un timer care sa fie un etalon ca sa pot executa alte operatii pina count ajunge la 500(ca exemplu) hi-tech code: void interrupt isr(void) { if(T0IE && T0IF){ // handle timer interrupt tmr0= 5; //200ns*5=1us toif=0; count++; } } void main(){ GIE = 1; // Enable Interrupts PEIE = 1; // Enable PIE Interrupt Sources T0CS = 0; // timer mode T0SE = 1; // high to low timer mode PSA = 0; // Prescaler is assigned to the Timer0 module PS2 = 0; PS1 = 0; PS0=0; // prescaler value T0IF = 1; // Enable TMR0 Interrupt Sources if(count==500){ count=0; //do something } } nu stiu daca formulele de pe linkul pus de mine sunt valabile si in cazul meu Link spre comentariu
ramsesrr Postat Aprilie 24, 2011 Partajează Postat Aprilie 24, 2011 TMR0=256-(overflow time*Fclock)/(4*prescaler) Link spre comentariu
sz3bbylA Postat Aprilie 25, 2011 Autor Partajează Postat Aprilie 25, 2011 sincer nu am inteles formula si inca ma chinui sa inteleg care e frecventa interna pentru 16f877o incrementare in tmr0 este 20mhz/4 , sau 20mhz*4?in pdf spune Operating speed: DC - 20 MHz clock input DC - 200 ns instruction cycle Link spre comentariu
MatyC Postat Aprilie 25, 2011 Partajează Postat Aprilie 25, 2011 In cazul tau este 20Mhz/4. Ai prescaler setat la 1:2 cu iesire catre tmr0. Asa ca in tmr0 ai 20Mhz/4/2 intrare. T(sec)=1/f(Hz). Ce este in paranteze sunt unitatile de masura standard valabile in formula. 20Mhz/4/2=20Mhz/8=2,5 Mhz frecventa intrare tmr0. 1/2.500.000 Hz=0,000.000.4 s= 400 ns. Link spre comentariu
Liviu M Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 Nu e nici o vrajitorie la mijloc, cu putin "antrenament" reusesti sa intelegi despre ce e vorba.Referitor la frecventa, pentru fiecare instructiune un pic are nevoie de 4 pulsuri de ceas (asa e construit PIC-ul intern). De aici apare diviziunea cu 4 (20 MHz / 200 ns).Referitor la formula de la TMR0 - ca sa generezi o intrerupere cu un timer, trebuie ca registrele asociate timerelor sa "se umple"; urmatorul puls pe intrarea de ceas a registrului TMRx genereaza overflow => intrerupere.In cazul TMR0 ai un singur registru pe 8 biti, deci maximul care "incape" in el e 255. Asa ca TMR0 poate numara de la 0 la 255 + "pulsul de overflow" = 256. Daca vrem sa avem intrerupere dupa mai putin timp, trebuie ca registrul sa porneasca preincarcat cu o valoare X astfel aleasa incat TMR0 sa numere cat ne rebuie noua => 256 - X. Mai ramane de calculat X pornind de la ceasul de sistem. Am vazut ca instructiunile se executa in 4 cicluri de ceas. La fel se intampla si cu incrementarea registrilor timerelor. De aici 4 de la numitor.Pe de alta parte, pentru a putea "numara" timpi mai lungi, timerele au asociate prescalere/postscalere care sunt, practic, divizoare de frecventa. Folosind pre/postscalerele astea, ceasul care ajunge la timere e "mai rar" cu factorul de divizare al pre/postscalerului *). De aici "prescaler" din formula. *) Exemplu - un pre/postscaler 1:8 inseamna ca la fiecare 8 pulsuri de ceas de sistem e incrementat si registrul TMRx. Link spre comentariu
sz3bbylA Postat Aprilie 26, 2011 Autor Partajează Postat Aprilie 26, 2011 multumesc pentru raspunsuri banuiam ca e asa dar am fost bulversat de situl ala care imi zicea ca pt 16f877 ai ceas intern 4mhz - imposibil atata timp cat nu are decit extern deci pentru mine ceasul picului e 20mhz acum pt prescaler 000 am 1/2 din ce am inteles la maty 400ns =>pot folosi (265-5) pt 2us pentru prescaler 001 am 1/4 => pot folosi (256-5) pentru 4 us atunci pentru ca sa obtin 1ms folosesc timerul 500 ori (presc 000) sau 250 (presc 001) hi-tech: unsigned char count=0; unsigned int nr=0; void interupt isr(){ if(T0IE && T0IF){ count++; TMR0=5; T0IF=0; } } void main(){ T0SE = 1; // high to low timer mode T0CS = 0; // timer mode PSA = 0; // Prescaler is assigned to the Timer0 module PS2 = 0; PS1 = 0; PS0=1; // prescaler value to 400ns TMR0=5; T0IF = 1; // Enable TMR0 Interrupt Sources GIE = 1; // Enable Interrupts light=0; //becul e stins while(1){ if(count=250){ count=0; nr++; } if(nr=1000){ nr=0; light != light; //se singe sau se prinde la 1 sec } } } mai e o problema TOSE0 te lasa sa faci ceasul crescator sau descrescator TOSE0 = 0 => low to high TOSE0 = 1 => high to low a doua problema a mea este ca mai exista niste delay-uri care apar la aparitia intreruperii si la esirea din ea codul asta nu merge nu stiu une gresesc Link spre comentariu
Liviu M Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 Din cauza de timeout am pierdut tot ce scrisesem.Nu reiau tot.O greseala la tine e T0IF=1 in loc de T0IE=1 pentru activat intreruperi.Mi se pare putin ciudata metoda de folosire a intreruperii - TMR0 numara putin de multe ori.Pentru 1 ms cu prescaler 1:4 eu as incarca TMR0 cu ~5 si as incrementa o variabila de 5 ori:1000 us / 4 / 250 / 0.2 = 5.16F877 poate fi programat sa lucreze cu ceas extern - quarz sau oscilator RC - pana la 20MHz in functie de model - sau cu ceas intern de 4 MHz - pag. 120-121 in data sheet.Flancul ceasului (T0SE) are importanta daca pentru TMR0 folosesti oscilator extern dedicat conectat pe pinul T0CKI (RA4). Daca folosesti ceasul de sistem (cazul tau), poti sa-l ignori. Link spre comentariu
sz3bbylA Postat Aprilie 26, 2011 Autor Partajează Postat Aprilie 26, 2011 va multumesc pentru indrumariin sfarsit vad ledul ca se aprinde/stingesincer nu inteleg exact ce-am faut dar merge(adica mai trebuie sa fac calcule ca sa ma prind ce inseamna o secunda)dar din nou am fost intors pe dos cu internal clockpag 120,121 imi spune Oscillator Configurations, dar nu am gasit sa scrie despre internal clock 4 mhze o mare nedumerire pentru mine atata timp cat picul 16f877 spune clar ca merge doar cu oscilator externsingurul lucru pe care l-am gasit legat de intarnal osc e poza asta Link spre comentariu
Liviu M Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 Se pare ca ai dreptate, nu exista oscilator intern. Are nevoie cel putin de o rezistenta si un condensator externe.Hm, habar n-am de unde ramasesem cu ideea ca are si oscilator intern. Poate pentru ca l-am folosit tot timpul cu quarz? Link spre comentariu
francezu Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 habar n-am de unde ramasesem cu ideea ca are si oscilator intern.poate de la inlocuitorul sau PIC16F887, acesta are oscilator intern.Este foarte util si calculatorul de AICI , dar asta nu te scuteste de cunoasterea functionarii timer-ului. Link spre comentariu
Liviu M Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 poate de la inlocuitorul sau PIC16F887Mai degraba de la cele mai mici (16F627) care parca au oscilator intern, ca 16F887 n-am folosit. Link spre comentariu
sz3bbylA Postat Aprilie 26, 2011 Autor Partajează Postat Aprilie 26, 2011 okeu folosesc 16f877887-le parca are osc intacum:T0CS = 0; internal deci eu presupun ca e 4 mhzps2 = 1, ps1=1, ps0 = 1 => inseamna 4mhz/4/256 = 256us o inrementare => mai mult de 1 sfert de secaproximam:4 incrementari = 1ms8 incrementari = 2ms16 incrementari = 4ms20 incrementari = 5ms40 incrementari = 10ms 80 incrementari = 20ms 200 incrementari = 50msin program folosescT0CS = 0; internal deci eu presupun ca e 4 mhz 50*2 = 100ms=> 20 incr pe count inseamna o seca trebuit sa pun counterul pe 200 ca sa obtin aprox 1 sec(e mai putin de 1 sec desi pt 111 am mai mult de 1 sfert de sec)asta am facut babeste ca sa nu ma incurc in stiinta//program:unsigned int count=0;void interrupt isr(void) { if(T0IE && T0IF){ count++; TMR0 = 200; // handle timer interrupt T0IF = 0; } }void main(){ ADCON1 = 0x07; // all pin I/O GIE = 1; // Enable Interrupts PEIE = 1; // Enable PIE Interrupt Sources T0IE = 1; // Enable TMR0 Interrupt Sources T0SE = 0; // 1 = high to low, 0 = low to high//aceasta intructiune nu are nici o valoare T0CS = 0; // 0 = internal clock, 1 = extern clock PSA = 0; // Prescaler is assigned to the Timer0 module PS2=1; PS1=1; PS0=1; // prescaler value T0IF = 0; TMR0 = 200;while(1){ if(count==200){ count=0; if(LCD_LIGHT==1) LCD_LIGHT=0; else LCD_LIGHT=1; }}ceva nu e logic aici Link spre comentariu
Liviu M Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 acum: T0CS = 0; internal deci eu presupun ca e 4 mhz... Atentie! Internal aici inseamna ca e derivat din ceasul de sistem (20 MHz / 4 /(eventual)prescaler), nu ca e un oscilator intern pe undeva. Cu alte cuvinte, la un ceas de sistem de 20 MHz si un prescaler 1:2 frecventa cu care incrementezi TMR0 e 20 MHz / 4 / 2 = 2.5 MHz (daca n-am gresit la calcule). Adica cele 400 ns ale lui MatyC.Timer0 poate fi utilizat cu un ceas derivat din ceasul de sistem (cu frecventa de mai sus) sau cu un oscilator extern conectat la pinul T0CKI(RA4) - vezi pagina 47 in data sheet pentru o poza. ceva nu e logic aiciSper c-am mai luminat putin subiectul Link spre comentariu
sz3bbylA Postat Aprilie 26, 2011 Autor Partajează Postat Aprilie 26, 2011 Liviu M acum e ok si am inceput si eu sa ma luminez nitelsper sa mai ajute pe careva postul asta , eu am inceput sa intelegT0CS = 0 => la mine e ceasul intern adica 20mhzT0CS = 1 cind folosesc clock pe RA4in cazul meu trebuie sa folosesc T0CS = 0 cu folmula lui MatyCbafta tuturor care m-ati indrumat !CRISTOS A INVIAT ! Link spre comentariu
ramsesrr Postat Aprilie 26, 2011 Partajează Postat Aprilie 26, 2011 declara count volatile 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