Resultat display

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Det där är inte assembler.
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Du måste köra *all* initiering av processorn innan du kan gå in i loopen.

Se mitt exempel som jag postade. Allt mellan "start" och "goto loop".
Anpassat till 886, så klart.

Det ska *inte* ligga i interrupt rutinen !!
Där ska *enbart* hanteringen av USART data ligga...
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Saknas kontroll av IE/IF flaggor.
Varför läses RXREG tre gånger och skrivs h'00' till TXREG vid *varje* interrupt ?
D.v.s *varje gång* det kommer in ett tecken i RXREG ?

> Väntar på att tecken skall tas emot...

Man väntar *aldrig* i en interrupt rutin !
Väntan sker i main i "loop, goto lopp".

Du kommer till isr_routine när ett tecken har kommit in.
Ta hand om det och. pang, RETFIE ! Ingen väntan, inga loopar (i onödan).
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

>Saknas kontroll av IE/IF flaggor.
Var skall den vara?

>Varför läses RXREG tre gånger och skrivs h'00' till TXREG vid *varje* interrupt ?
>D.v.s *varje gång* det kommer in ett tecken i RXREG ?
Det är taget ur Thomas McGahee bsekrivning som säger så här.
if you do not initially do these three reads the
receiver may come up with an error condition on start-up.
Of course in our case we have included error recovery code
that would actually fix this problem, but putting this code
fragment here makes us more aware of the problem right up front.


Och vad gäller TXREG.
if you forget to send out an initial dummy character,
then the txif flag never goes high and your serial input routine will
go round and round in circles forever waiting for txif to go high.
This is a WONDERFUL BUG that is guaranteed to drive you nuts
and make all your hair fall out. (well, actually your hair doesn't really FALL out. You end up pulling it all out in utter frustration.)


>Man väntar *aldrig* i en interrupt rutin ! Väntan sker i main i "loop, goto lopp".
>Du kommer till isr_routine när ett tecken har kommit in.
>Ta hand om det och. pang, RETFIE ! Ingen väntan, inga loopar (i onödan).

Då kan man plocka bort den loopen.

EDIT:

Du menar den här flaggan
PIR1, RCIF ; tror det är den du kallar RxIF heter här RcIF
bsf PIE1, RCIE

Taget ur databladet.
The RCIF interrupt flag bit of the PIR1 register is set
whenever the EUSART receiver is enabled and there is
an unread character in the receive FIFO. The RCIF
interrupt flag bit is read-only, it cannot be set or cleared
by software.
RCIF interrupts are enabled by setting the following
bits:
• RCIE interrupt enable bit of the PIE1 register
• PEIE peripheral interrupt enable bit of the
INTCON register
• GIE global interrupt enable bit of the INTCON
register
The RCIF interrupt flag bit will be set when there is an
unread character in the FIFO, regardless of the state of
interrupt enable bits.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> if you do not initially ....

Mycket möjligt, men du gör det hela tiden !

> if you forget to send out an initial dummy character,

Samma sak, "initial", men du skickar en dummy hela tiden (d.v.s varje
gång det har kommit in ett tecken i RXREG).

Men å andra sidan, du lyssnar ju på en kontinuerlig dataström, så vad
gör det om du missar ett par bytes precis när PIC'en har slagits på ?
Efter ett par tecken så har det hela synkat in på dina datapaket.

Om du behöver göra detta, lägg det i din "init" kod, d.v.s innan processorn
går in i "goto loop".

> Var skall den [IF/IE kontroll] vara?

I början av ISR'en.

Nu är det ju så här, att om du *enbart* har RXIE satt som "1" (d.v.s att
du inte *kan* få interrupt från andra källor än USART-RX) så kan du
klara dig utan det. Det enda som gör att du hamnar i isr_routine är du
har fått in ett tecken via USART'en.

Om man har flera interrupt källor (säg USART och en Timer) så måste man
ju kolla vilken av dom det är som har triggat interruptet. Det ser man då
på IF flaggorna. Är RXIF = "0", så hoppar man över USART delen och
kollar t.ex TMR0IF istället. O.s.v...
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

Vad gäller dom 3 RCREG eller som du skriver RXREG, så är det som du säger man tabort dom då klockan skickar så pass mycket data att det inte spelar någon roll.

Den här hade jag ju i början av ISR och om nu inte kan ha goto hur gör man då? Eller menar du att man kan hoppa över den med?

Kod: Markera allt

uart_ready
	btfss	PIR1, RCIF	 ;Väntar på att tecken skall tas emot
	goto	datain	 ;om ej klar,vänta...
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> ; Väntar på att tecken skall tas emot

Alltså... :-)

Hela finessen med interrupt styrning är att du inte kommer till
ISR'en *ALLS* om det inte finns något tecken i RCREG !

Alltså behöver du inte vänta där. Är du med ?

Interrupt innebär att man bara gör saker vid behov, när något
har hänt (t.ex ett tecken har kommit in).

Det är USART'en själv som skickar din kod till ISR'en när den har
mottagit ett komplett tecken ! Innan dess ligger processorn
i "goto loop" i main...

Om den enda IE flaggan som är satt är RCIE, så *måste* RCIF
vara satt när du kommer till ISR'en. Det är ju det enda sättet som
du kan hamna där på.

Och, som sagt, om du har flera interrupt källor så behöver man
kolla alla (rellevanta) IF flaggor för att se vilken källa det var
denna gång. Det finns ju bara en ISR...
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

Så nu börjar det klarna i dimman, var inne på att det var mer avancerad kod som låg i ISR.

Om jag inte är ute och cyklar, så måste väl 'Global Interrupt Enable' sättas innan loop?
bsf INTCON, GIE
Ur databladet.
If the GIE bit of the INTCON
register is set, the device will call the Interrupt Service
Routine (0004h).


EDIT:
Stämmer detta?
När koden i ISR har läst in allt data i Rx_Buffer, går man ur ISR (retfie) och fortsätter med en sub code efter loopen.
Stänger av GIE, skickar datat till displayen och sedan sätter GIE och ISR koden börjar om?
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Njaa....

I ISRn:
1: Ett block tas emot via ISR
2: Ett fullt block har inkommit, då det går snabbt kan du fint kolla om det är rätt data och lägga ut dessa i lämplig buffert då detta går ganska snabbt. Därmed är input-buffern ledig igen. Detta ska ta mindre än 1 bytes tid (3,75ms) och ger alltså 3750 systemklock @ 4MHz oscillator. Klarar du inte det på den tid har du helt andra och mycket allvarligare problem.
3: När alla data är ifyllda sätts en flagga.

I mainloop:
0: Initiera allt
1: Kolla om flaggan är aktiverat
2: Om den är aktiv "call Update_Display"
3: Gör vad annat som ska göras...
4: Hopp till 1

OBS: att GIE inte flippas alls under körningen, det behövs inte!
"Update_Display"-rutinen har ~18ms på sig att skicka ut datan till displayen och det borde räcka LÅNGT, alltså ska du "skita i" GIE när allting väl är aktiverat.
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

>"Update_Display"-rutinen har ~18ms på sig att skicka ut datan till displayen och det borde räcka LÅNGT,
>alltså ska du "skita i" GIE när allting väl är aktiverat.
Du menat att om rutinen "skulle" ta mer än 18ms på sig, kan man behöva ta GIE till hjälp?
Men i det här fallet skall det inte behövas.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> var inne på att det var mer avancerad kod som låg i ISR.

Generellt sätt så ska/kan en ISR ha ganska enkel kod. Och aldrig mer
än vad som absolut måste utföras som "svar" på den händelse som
triggade interruptet. I detta fall att ta hand om det tecken som just har
kommit in till RCREG. D.v.s att spara undan det för att ge plats åt nästa
tecken. Att koda av själva meddelandet/datapakatet kan göras senare
(d.v.s utanför ISR'en).

Som Icecap skrev, sätt GIE = "1" i din init kod och låt den sedan vara.
GIE hanteras sedan automatiskt av processorn.

GIE sätts = "0" samtidigt som själva interruptet sker (så att det inte sker
interrupt medan processorn ligger i själva ISR'en).

RETFIE sätter automatiskt GIE = "1" igen i samband med "returen".
Det är den enda som skiljer RETFIE från RETURN, för övrigt...

Sen bara ett litet förtydligande av Icecap's inlägg...

> I ISRn:
> 1: Ett block tas emot via ISR

Obs att du alltså bara tar imot *ett* tecken i blocket vid *varje* ISR anrop.
Du ska inte ligga kvar i ISR'en och vänta på hela blocket.
För ett block om 5 tecken kommer det att bli 5 anrop till ISR'en.
Stewal
Inlägg: 354
Blev medlem: 17 januari 2008, 16:38:41
Ort: Nämdö

Inlägg av Stewal »

>Obs att du alltså bara tar imot *ett* tecken i blocket vid *varje* ISR anrop.
>Du ska inte ligga kvar i ISR'en och vänta på hela blocket.
>För ett block om 5 tecken kommer det att bli 5 anrop till ISR'en.
Ja det var rätt bra att få veta.
Alltså skall det bara ligga kod som tar emot data och sparar det i Rx_Buffer, skall även kod som räknar hur många gånger datat tagits ligga här med?.

Då till nästa fråga var hamnar vi efter RETFIE, är det efter goto isr_routine

Kod: Markera allt

INT_VECTOR	CODE	0x004
	goto    isr_routine       
Isåfall var skall koden som analyserar datat i RX_Buffer ligga.

Många frågor, men har lärt mig mycket.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> skall även kod som räknar hur många gånger datat tagits ligga här med?.

Ja, en typ av "pekare" eller "räknare" som håller reda på var i bufferten
du befinner dig från ett ISR anrop till nästa. Och när den har kommit till
"5" så sätter du flaggan för "full buffert" så att loopen i main kan se det
och göra det den ska (sannolikt ett call till någon rutin som tar hand om bufferten).

> Då till nästa fråga var hamnar vi efter RETFIE, är det efter goto isr_routine

OK, vi tar en sak i taget (och detta finns bra beskrivet i kapitlet om interrrupt
i dtabaldet).

När ett interrupt inträffar körs den aktuella instruktionen färdigt (d.v.s i
"goto loop" loopen), adressen till nästa instruktion sparas på stacken
och ett hopp ("goto") till h'004' sker. Sedan när ISR'en är klart avslutas
den med en RETFIE, den plockar tillbaka retur-adressen från stacken
och lägger den i PC (programräknaren). Alltså fortsätter main på
instruktionen efter den där interruptet inträffade. Klart ?

Alltså :

Kod: Markera allt

INT_VECTOR   CODE    h'004'
	code...
        ta hand om RCREG -> buffert.
        öka buffert-räknade med 1
        if buffert-räknare = 5 -> sätt "fullbuffert" = 1
        code...
        RETFIE


MAIN      CODE

        init av processor och alla register....
loop
        code...
        code...  (1)
        code...  (2)
        if "fullbuffert" = 1 -> call check_buffert (eller vad du nu vill kalla det)
        code...
        GOTO loop


BUFF_MGR   CODE

check_buffert
        code...
        ta hand om bufferten och gör vad som måste göras...
        code...
        RETURN
Säg att RCIF blir "1" då processorn kör instruktionen i (1).
Instruktionen (1) körs först klart, adressen till (2) sparas under på stacken,
och ett hopp till h'004' sker.

När ISR'en har gjort det den ska göra, avslutas det hela med RETFIE.
Den hämtar tillbaka adressen till (2) från stacken och uppdaterar
PC (programräknaren) med den. Alltså "hoppar" processorn till (2) och
fortsätter som om inget hade hänt...

Så svaret på frågan "var hamnar vi efter RETFIE" är "tillbaka dit där du var"... :-)
Skriv svar