PIC18F25K22 interrupt problem *LÖST* Nytt strul

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC18F25K22 interrupt problem *LÖST* Nytt strul

Inlägg av Icecap »

Nu har jag gång i det mesta och hela mitt regleringssätt har jag ändrat - och där stötar jag på patrull!

Jag har mina synk-pulser, de kommer med 100Hz som de ska och jag har startat Timer 1 & 3. Timer 3 är tänkt som mättimer, den används till att hålla reda på tiden mellan Synk-pulserna, därmed kompenseras för den interna oscillators drift. Jag använder den oversampling-rutin som jag lärde här och den fungerar skitbra!

Count mellan pulserna hamnar på 40k och varierar lite med temperaturen på kretsen, helt OK med andra ord.

Detta värde använder jag sedan till all annan timing och där kommer problemet. Jag delar först Count med 3 för att dela upp i de 3 faser, det ger alltså ett värde runt 13360 och varierar med det exakta Count.

Sedan räknar jag ut vad värdet för den givna procentsats för fördröjningen är.

Dessa värden sparas i minnet som 16 bitars unsigned.

Sedan laddar jag Timer 1 med värdet som anger fördröjningen när det kommer en Sync-puls. När Timer 1 overflower ger den en interrupt vilket laddar den med värdet för fasförskjutningen osv.

För tillfället ger den enbart en interrupt första gången efter en Synk-laddning, det gör det enklare och tydligare att se på oscilloskopet.

Jag skriver ut värden via serieporten, fungerar perfekt. MEN delayen fungerar dåligt! Alltså får man kolla mer noga och nu har jag sett att det inte fungerar att skriva till Timer 1!

Det jag gör är:

Kod: Markera allt

ISR:
...
TMR1 = Delay_Start;
... (ett par instruktioner)
Read = TMR1;
Delay_Start är en unsigned short och har rätt värde! Har skrivit ut den via serieporten och allt är OK med den.
'Read' använder jag för att kontrollera värdet som TMR1 har och nu kommer problemet: Timer 1 får bara lägsta byten! MSB är konsekvent 0!

Initieringen då?

Kod: Markera allt

void Initiate_Timers(void)
  {
  TMR1MD = false; // Timer 1 power on
  T1CON = 0x03; // Fosc/4, 1:1, 16-bit RW, Run
  TMR1 = 0;
  TMR1IF = false; // Kill any residual interrupt
  TMR1IP = true; // High interrupt priority
  TMR1IE = true; // Enable interrupt
  TMR3MD = false; // Timer 1 power on
  T3CON = 0x03; // Fosc/4, 1:1, 16-bit RW, Run
  TMR3 = 0;
  TMR3IF = false; // Kill any residual interrupt
  TMR1IP = false; // High interrupt priority
  TMR1IE = false; // Do not allow for interrupt
  }
Har testat att ladda in som två 8-bitars värden via TMR1H & TMR1L men det fungerar inte: MSB blir inte annat än noll. Och det är oberoende av vilken sekvens jag skriver med; först till TMR1H, sedan til TMR1L eller vice-versa.

Men själva timern fungerar och räknar runt med rätt intervall så MSB fungerar som sådan, bara inte när jag ska ladda den med ett värde.
Och värdet på MSB är verkligen 0x00 när jag har skrivit till den, det syns på fördröjningen.

Jag har testat att stoppa Timer 1, skriva värdet och sedan starta den igen - men det fungerar inte!

Så vad tusan har jag översett?

PIC'en har inte varit använd till annat än detta, den har inte varit utsatt för några otrevligheter och allt anat fungerar bra.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PIC18F25K22 interrupt problem *LÖST* Nytt strul

Inlägg av sodjan »

Det enda som jag hittar (som du också säkert har sett) är:

"For writes, it is recommended that the user simply stop the timer and
write the desired values. A write contention may occur by writing to
the timer registers, while the register is incrementing. This may
produce an unpredictable value in the TMRxH:TMRxL register pair."

Se också: "12.6 Timer1/3/5 16-Bit Read/Write Mode", vilket ska
vara en metod att undvika vissa problem vid läsning/skrivning
av 16 bitars timers.

Och *om* 16-bit R/W på påslaget så måste man läsa TMR1L först
vid läsning och skriva TMR1H först vid skrivning för att bufferten
ska hanteras korrekt. Men som sagt, detta har du säkert sett...

Det skulle vara intressant att se vilken kod som "TMR1 = nnn;" generar.
Kompilatorn borde ju göra rätt, så att säga...
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC18F25K22 interrupt problem *LÖST* Nytt strul *Löst*

Inlägg av Icecap »

TMR1 = Delay_Start;

ger

movff _Delay_Start,4046; Motsv. TMR1L
movff _Delay_Start+1,4047; Motsv. TMR1H

I listfilen står det även:
_TMR1 set 4046

Läsningen sker efter samma mönster: LSB överförs till LSB av variabeln, sedan överförs MSB på samma sätt.

Så kompilern gör rätt i båda fall. Har såklart testat att stoppa timern osv. men det hjälper inte heller.

EDIT: Men hallå! Kompilern gör ju inte alls rätt! Den gör ju motsatsen av hur det ska göras! Då så, får fibbla lite...

Mer EDIT: Jupp! Fick ändra variablerna till att vara en union mellan en unsigned short (WORD) och två unsigned char (BYTE).
Då använder jag WORD som 16-bit variabel vid uträkningarna och när jag ska ladda Timer 1 använder jag BYTE.

Och det gjorde tricket! Nu fungerar det och jag kan alltså ställa fördröjningen via den seriella port vid att skriva ett värde mellan 0 och 100 och trycka på Enter. Sen är det bara resten...

Tack sodjan, för att leda mina tankar på rätt väg.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PIC18F25K22 interrupt problem *LÖST* Nytt strul

Inlägg av sodjan »

Ja, om jag minns rätt från databladet så ska man göra det
i den ena eller den andra ordningen beroende på om 16RW
är satt eller inte. Kompilatorn gör nog rätt om man *inte* har
den satt, men det har ju du... Eller så tänker jag fel... :-)
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC18F25K22 interrupt problem *LÖST* Nytt strul

Inlägg av Icecap »

Jag har ju satt den bit men kompilern gjorde läsning/skrivning i "fel" följd. Men det är ju ganska enkelt att lösa när man vet att det är så. Jag ska dock kolla om det finns något direktiv man kan ge kompilern så att den gör det "rätt", annars får jag göra en snygg lite inline-funktion.
Skriv svar