Eugen_B Postat Ianuarie 28, 2011 Partajează Postat Ianuarie 28, 2011 Pai cum sa introduca intarzieri cand citeste temperatura ? ca doar e pe intrerupere.Cand valoarea la timer0 trece de la 0xFF la 0x00, apoi nu conteaza ce face programul , se intrerupe executia lui (ca daia ii zice intrerupere) si se executa functia de intrerupere. Nu m-am uitat peste tot programul care l-ai postat tu , dar ce am observat: INTCON = 0 ' not using interupts. Just monitoring int flag bitspai normal ca intarzie , ca tu nu lasi mechanismul hardware al intreruperii sa functioneze...tu faci ceva software cu flagul.Edit: Schema este postata, oricine doreste poate scrie un soft functional si sa il posteze aici.Pe mine nu ma intereseaza acest proiect ,eu doar vreau sa ajut daca pot cu problemele software intalnite, dar daca nu este codul pus la vedere , nu pot decat sa zic cum as face eu. Link spre comentariu
Liviu M Postat Ianuarie 28, 2011 Partajează Postat Ianuarie 28, 2011 Dar, citirea senzorilor de temperatura (la rezolutie de 9 biti =93.75 ms, 10 biti =187.5 ms, 11 biti =375 ms, pentru fiecare !) introduce intarzieri in program, pe care nu le-am putut corecta software.In proiectul meu (folosesc DS1631, da' functionarea e asemanatoare, difera doar interfata) dau comanda de achizitie (comanda Convert T [44h] ) in secundele pare si citesc valorile in secundele impare (sau invers), In conditiile astea, intarziere introdusa de senzrul de temperatura e durata unei comunicatii (ca nu mai trebuie sa astept dupa date, ma asteapta ele pe mine).In cazul de fata as proceda similar pentru fiecare senzor:- sec. 1 - Convert T sensor 1- sec. 2 - read sensor 1- sec. 3 - Convert T sensor 2- sec. 4 - read sensor 2In felul asta ai date proaspete pentru fiecare senzor la 4 secunde, da' nu cred ca-i grav.Da' citirea chiar o fac sincronizata de ceas; la ceas folosesc quart de 32kHz (32,178, mai exact), da' principiul e acelasi cu ce am explicat anterior referitor la valorile de start in TMR0. La mine ceasul functioneaza chiar exact. Link spre comentariu
gr1ph0n Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 @Eugen_B: Ceea ce a postat fratello sunt niste variante. Daca intr-adevar vrei sa vezi cum functioneaza ceasul din soft mergi la http://darreltaylor.com/DT_INTS-14/elapsed.html.Tu spui Pai cum sa introduca intarzieri cand citeste temperatura ? ca doar e pe intrerupere eu spun ca poate sa introduca intarzieri, intre comanda de conversie si citirea senzorilor apare o pauza de pana la 750ms. Incearca sa vezi la o intrerupere de 256us sa vezi cam cate pierzi si nu sunt contorizate (din cate stiu eu daca apare o intrerupere si picul executa o comanda intai termina si apoi intra in intrerupere) Din cate stiu eu orice procesor permite executarea intreruperii in perioada in care este idle, daca nu executarea intreruperii trebuie sa mai astepte. @Liviu_M: acelasi lucru il fac si eu prima secunda se trimite comanda de conversie si in a doua secunda se citeste senzorul.Cu un cristal secundar de 32.768 KHz intreruperea are loc la o secunda, iar picul pana apare intreruperea poate executa pana la 1.000.000 de instructiuni. Dar la o intrerupere de 10 ms?Sper ca m-am exprimat corect. Daca nu imi cer scuze. Link spre comentariu
Liviu M Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 Cu un cristal secundar de 32.768 KHz intreruperea are loc la o secunda, iar picul pana apare intreruperea poate executa pana la 1.000.000 de instructiuni. Dar la o intrerupere de 10 ms?Sper ca m-am exprimat corect. Daca nu imi cer scuze.Te-ai exprimat corect si clar, da' cred ca vezi probleme acolo unde nu sunt. In 10ms (mie mi-au iesit 15) ai timp de 10000 (zece mii) de instructiuni la un ceas de 4Mhz. Eu cred ca ai timp sa faci o gramada de chestii in timpul asta. Plus ca tratarea intreruperii dureaza cateva uSecunde, dupa care programul continua nestingherit de unde a ramas.Tratarea intreruperii generate de TMR0 dureaza ~5 comenzi; in cazul meu, quarz dedicat, arata cam asa (e in c, da' cred ca se poate intelege):if(TMR1IF && TMR1ON) /*ceas*/ { T1CON = 0b00001110; // stop the timer TMR1L = 0x00; TMR1H = 0x80; // ~ 1 sec T1CON = 0b00001111; // start the timer ucClkInt = 1; //"anunt" programul principal ca a mai trecut o secunda TMR1IF = 0; }In cazul vostru:- folositi TMR0 (un singur registru si alte comenzi de start/stop); in registru incarcati valoarea de start a numararii. Din asata se "calibreaza" ceasul. - in programul principal, undeva in cadrul buclei aleaia nesfarsite, mai trebuie o bucata de cod care sa numere cele 75 Ticks (vezi calculul meu de la pag. 24 parca) si sa semnalizeze o secunda noua cand se fac cele 75 Ticks;- semnalul ala de secunda noua se foloseste mai departe in program pentru "sincronizarea" functionarii:if(ucClkInt){ Ticks++; // incrementez ticks if(Ticks == 75) //testez daca s-a terminat secunda { SecundaNoua = 1; // semnalizez secunda noua Ticks = 0; //reset tikc } ucClkInt = 0; // reset flag intrerupere ceas} Link spre comentariu
gr1ph0n Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 Tratarea intreruperii generate de TMR0 dureaza ~5 comenzi; in cazul meu, quarz dedicat, arata cam asa (e in c, da' cred ca se poate intelege):In codul tau cred ca e vorba de TMR1.Initial s-a folosit TMR0 dar acum se foloseste TMR1 si sunt 10ms intre intreruperi nu 15. 100 Ticks/sec.Am mai spus si risc sa ma repet, nu ceasul in sine este problema ci ceea ce face pic-ul intre intreruperi.In unele cazuri si cred ca si aici 10000 de instructiuni nu sunt de ajuns. PBP-ul nu poate lucra cu variabile float si atunci sunt introduse niste artificii de calcul pentru a trece peste acest obstacol (gen inmultire cu 100 si altele). Link spre comentariu
Liviu M Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 si atunci sunt introduse niste artificii de calcul pentru a trece peste acest obstacol (gen inmultire cu 100 si altele).In loc sa inmultiti cu 100, eu as face o variabila noua (unsigned char - 8 biti fara semn) compusa din cei 3 biti LSB al byte-ului MSB ai senzorului (bitii 2^6..2^4 in data-sheet) (ma rog, se lucreaza cu 4) si 4 biti MSB din Byte-ul LSB al senzorului:ucIntregiGrad =((MSB_SENZOR << 4) + (LSB_SENZOR >> 4);In felul asta intregii sunt obtinuti destul de repede, mai ramane sa-i afisati; >> 4 e shift dreapta cu 4 biti, <<4 e shift stanga.Pentru partea de dupa virgula, eu am facut mers pe rezolutie de 0,25° => am 4 cazuri mari si late pe care le tratez cu if()..else.Poate ideile astea va ajuta sa economisiti ceva timp?LE Si tot nu ma prind de ce ti se pare ca e o diferenta intre 10 ms si 1 sec din punct de vedere al intreruperilor (in afara de un test suplimentar si 2 incrementari). Link spre comentariu
fratello Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 Am incercat asa : ClockCount: ' Note: this is being handled as an ASM interrupt@ INT_START @ RELOAD_TIMER ; Reload TIMER1 R0save = R0 ; Save 2 PBP system vars that are used during R1save = R1 ; the interrupt Ticks = Ticks + 1 if Ticks = 100 then Ticks = Ticks-100 Seconds = Seconds + 1 SecondsChanged = 1if seconds=10 or seconds=40 then gosub init_1if seconds=15 or seconds=45 then gosub init_2if seconds=20 or seconds=50 then gosub temp_1if seconds=25 or seconds=55 then gosub temp_2 if Seconds = 60 then Minutes = Minutes + 1 MinutesChanged = 1 Seconds = 0 endif...etc...si, de data aceasta, ceasul o ia inainte !!! Se intelege , cred, init_1 si temp_1 sunt initializarea/citirea senzorului 1... L.E. : Poate cineva "vede" mai clar unde ar trebui introduse rutinele de citire a senzorilor de temperatura : '****************************************************************'* Name : ELAPSED.PBP *'* Author : Darrel Taylor *'* Notice : Copyright (c) 2003 *'* Date : 12/16/2003 *'* Notes : *'****************************************************************Define INTHAND _ClockCount ' Tell PBP Where the code starts on an interruptInclude "ASM_INTS.bas" ' ASM Interrupt StubsTicks var byte ' 1/100th of a secondSeconds var byteMinutes var byteHours var byteDays var wordR0save var wordR1save var wordSecondsChanged var bitMinutesChanged var bitHoursChanged var bitDaysChanged var bitSecondsChanged = 1MinutesChanged = 1Hours =12 : Minutes =00 : ZIUA = 01 : Luna = 01Goto OverElapsed' ------------------------------------------------------------------------------Asm IF OSC == 4 ; Constants for 100hz interrupt from Timer1TimerConst = 0D8F7h ; Executed at compile time only EndIF If OSC == 8TimerConst = 0B1E7h EndIF If OSC == 10TimerConst = 09E5Fh EndIF If OSC == 20TimerConst = 03CB7h EndIF ; ----------------- ADD TimerConst to TMR1H:TMR1LADD2_TIMER macro CHK?RP T1CON BCF T1CON,TMR1ON ; Turn off timer MOVLW LOW(TimerConst) ; 1 ADDWF TMR1L,F ; 1 ; reload timer with correct value BTFSC STATUS,C ; 1/2 INCF TMR1H,F ; 1 MOVLW HIGH(TimerConst) ; 1 ADDWF TMR1H,F ; 1 endm; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 RELOAD_TIMER macro ADD2_TIMER BSF T1CON,TMR1ON ; 1 ; Turn TIMER1 back on CHK?RP PIR1 bcf PIR1, TMR1IF ; Clear Timer1 Interrupt Flag endm; ----------------- Load TimerConst into TMR1H:TMR1L LOAD_TIMER macroEndAsm T1CON.0 = 0 ; Turn OFF Timer1 TMR1L = 0 TMR1H = 0Asm ADD2_TIMER endmEndAsm' ------[ This is the Interrupt Handler ]---------------------------------------ClockCount: ' Note: this is being handled as an ASM interrupt@ INT_START @ RELOAD_TIMER ; Reload TIMER1 R0save = R0 ; Save 2 PBP system vars that are used during R1save = R1 ; the interrupt Ticks = Ticks + 1 if Ticks = 100 then Ticks = Ticks-100 Seconds = Seconds + 1 SecondsChanged = 1 if Seconds = 60 then Minutes = Minutes + 1 MinutesChanged = 1 Seconds = 0 endif if Minutes = 60 then Hours = Hours + 1 HoursChanged = 1 Minutes = 0 endif if Hours = 24 then Days = Days + 1 DaysChanged = 1 Hours = 0 endif endif R1 = R1save ; Restore the PBP system vars R0 = R0save@ INT_RETURN ; Restore context and return from interrupt'-----====[ END OF TMR1 Interrupt Handler ]====---------------------------------StartTimer: T1CON.1 = 0 ; (TMR1CS) Select FOSC/4 Clock Source T1CON.3 = 0 ; (T1OSCEN) Disable External Oscillator PIR1.0 = 0 ; (TMR1IF) Clear Timer1 Interrupt Flag PIE1.0 = 1 ; (TMR1IE) Enable TMR1 overflow interrupt INTCON.6 = 1 ; (PEIE) Enable peripheral interrupts INTCON.7 = 1 ; (GIE) Enable global interrupts T1CON.0 = 1 ; (TMR1ON) Start TIMER1return; -----------------StopTimer: T1CON.0 = 0 ; Turn OFF Timer1return; -----------------ResetTime: R0save = T1CON.0 ; Save TMR1ON bit T1CON.0 = 0 ; Turn OFF Timer1 TMR1L = 0 TMR1H = 0@ LOAD_TIMER ; Load TimerConst T1CON.0 = R0save ; Restore TMR1ON bit Ticks = 0 Seconds = 0 Minutes = 0 Hours = 0 Days = 0 SecondsChanged = 1returnOverElapsed: Link spre comentariu
gr1ph0n Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 Poate ca sunt eu mai talamb, si nu inteleg diferenta intre intrerupere la 10 ms si 1sec. Spatiul de lucru intre intreruperi in primul caz e de 10 ms si in al doilea caz e de 1 sec evident.Atunci cand apare o intrerupere microcontroler-ul trebuie sa salveze variabilele. Cu cat sunt mai multe variabile in sistem cu atat ii ia procesorului mai mult timp sa salveze aceste variabile.Diferenta am observat-o atunci cand am facut softul pentru un ceas&dual thermometer folosind un cristal suplimentar de 32.768 KHz si utilizand acelasi algoritm de citire al senzorilor. Am observat ca intreruperile nu mai sunt afectate de ceea ce face pic-ul in perioada dintre intreruperi.Multumesc Link spre comentariu
Liviu M Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 Dupa parerea mea, faci prea multe operatii in cadrul rutinei de tratare a intreruperii.Eu as face doar incrementarea lui Ticks si, eventual, a secundelor. Restul prelucrarilor - o data pe secunda cand vine secunda noua. ' ------[ This is the Interrupt Handler ]---------------------------------------ClockCount: ' Note: this is being handled as an ASM interrupt@ INT_START@ RELOAD_TIMER ; Reload TIMER1 R0save = R0 ; Save 2 PBP system vars that are used during R1save = R1 ; the interrupt Ticks = Ticks + 1 if Ticks = 100 then Ticks = 0; Seconds = Seconds + 1 ; asta e optional, se poate face jos SecondsChanged = 1 endif R1 = R1save ; Restore the PBP system vars R0 = R0save@ INT_RETURN ; Restore context and return from interruptRestul l-as face in main, de fiecare data cand "se umple" o secunda: if SecondsChanged = 1 ; numai cand se schimba o secunda secondChange = 0; if Seconds<59 ; inca nu s-a umplut inutul, mai putem incrementa secundele Seconds = Seconds + 1 else ; s-a umplut un minut, secundele o iau de la o si testam minutele Seconds = 0 if Minutes < 59 ; nu s-a facut o ora Minutes = Minutes+1 else Minute = 0 if Hours < 24 Hours = Hours +1 else ... ; si asa mai departe endif endif endif; ... @gr1ph0n: oricate operatiii ai face intre intreruperi, ele vor veni intotdeauna la 10 ms (asta daca nu dezactivezi intreruperile pe parcurs pentru timp indelungat).Dupa cum scrie in documentatie, in cazul in care primeste o intrerupere, PIC-ul salveaza adresa curenta pe stiva si "sare" la adresa 0x04. Si atat. E treaba ta sa nu lungesti preat tare rutina de tratare a intreruperilor (in Midrange User Manual scrie ca intreruperile sunt dezactivate automat):When an interrupt is responded to, the GIE bit is cleared to disable any further interrupt, thereturn address is pushed into the stack and the PC is loaded with 0004h. Link spre comentariu
fratello Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 @ Liviu :primele comentarii sunt pentru mine ?! Multumesc frumos, dar autorul codului este mentionat in antetul acestuia. Din cate stiu eu, Darrel Taylor este "Number 1" cand vine vorba de PicBasicPro ...de aceea am ales codul lui pentru ceas. Discutiile pe topicul dedicat codului pentru ceas "elapsed_int.bas" (am pus link mai sus) aratau cat de greu este de pastrat acuratetea ceasului introducand si partea de citire a senzorilor de temperatura... Daca cineva STIE cum se face asta CORECT, de ce nu pune codul aici ?! Nu pentru mine (sau si pentru mine) ! Dar, mai ales, pentru cei care vor sa mai invete ceva... Un cod complet, eventual comentat, ar opri scrierea atator posturi si ar rezolva problema. Nu ne putem da toti cu parerea asupra unor portiuni de cod, mai ales cand sunt scrise in limbaje "nefamiliare" ...Parerea mea ... Link spre comentariu
gr1ph0n Postat Ianuarie 29, 2011 Partajează Postat Ianuarie 29, 2011 @gr1ph0n: oricate operatiii ai face intre intreruperi, ele vor veni intotdeauna la 10 ms (asta daca nu dezactivezi intreruperile pe parcurs pentru timp indelungat).Dupa cum scrie in documentatie, in cazul in care primeste o intrerupere, PIC-ul salveaza adresa curenta pe stiva si "sare" la adresa 0x04. Si atat. E treaba ta sa nu lungesti preat tare rutina de tratare a intreruperilor (in Midrange User Manual scrie ca intreruperile sunt dezactivate automat): When an interrupt is responded to, the GIE bit is cleared to disable any further interrupt, thereturn address is pushed into the stack and the PC is loaded with 0004h. Ai dreptate!Imi cer scuze, am facut o confuzie crasa intre intreruperile ASM care sunt intreruperi reale si comanda PBP ON INTERRUPT care este o pseudo intrerupere si care asteapta executarea comenzii si apoi are loc gestionarea intreruperii. Link spre comentariu
vasile eugen Postat Ianuarie 30, 2011 Partajează Postat Ianuarie 30, 2011 eu am in test ceas cu termometrul versiunea aceasta cu pic 16f628A :acesta la probat cineva?la opt ore imi inainteaza circa 4 minute sa fie din soft? Link spre comentariu
XAN77 Postat Ianuarie 30, 2011 Partajează Postat Ianuarie 30, 2011 nu cred sa fie softul, si eu ma pregatesc sa fac acel ceas. Ai umblat la cele doua variabile de calibrare ? Ai setat XT la oscilator? Link spre comentariu
vasile eugen Postat Ianuarie 30, 2011 Partajează Postat Ianuarie 30, 2011 nu cred sa fie softul, si eu ma pregatesc sa fac acel ceas. Ai umblat la cele doua variabile de calibrare ? Ai setat XT la oscilator? da am setat oscilator extern,termometrul merge bine Link spre comentariu
Liviu M Postat Ianuarie 30, 2011 Partajează Postat Ianuarie 30, 2011 Un cod complet, eventual comentat, ar opri scrierea atator posturi si ar rezolva problema.Ai dreptate, asa ar fi cel mai bine.Din pacate, n-am senzori, n-am LCD disponibil, n-am... Incercam sa ajut pe cineva care "are tot" sa optimizeze putin codul.Cum nu sunt sigur ca in varianta mea ar merge mai bine decat variantele voastre, as fi vrut sa pot sa si testez ce incerc.Nu de alta, da' eu incercam sa ma prind de ce nu reusiti sa-i dati de cap si incercam sa va ajut cu ceva idei, Cum nu sunt Number 1 in nimic, sunt sanse mari ca ce zic eu sa fie batut de campi; in cazul asta, mi-ar prinde bine daca cineva mi-ar arata ce gresesc. Asa, pentru cultura mea generala (si evitarea unor eventuale batai de cap pe viitor).Pen'ca nu am nici o contributie utila pe topicul asta, imi cer scuze pentru "poluare" si ma duc pe topicuri la care ma pricep mai bine (adica nicaieri ). 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