Picbasic interrupt met timer

Hallo,

Ik ben momenteel bezig met picbasic, maar ik zit vast met de timer. Nou wilde ik om te proberen een simpel proggramma schrijven waar een led na een aantal seconden aan en uit gaat. Beetje moeilijk gezocht, maar het gaat om het principe.

Het programma blijft in de while loop hangen en maakt(volgens mijn mening) na (128(prescaler)*256*100(hij telt tot 100 mbv hulp variabele) cycles het ledje vervolgens 5 seconden laag.

code:

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
CLEAR	           ;We gebruiken een 16F628A type


ON_INTERRUPT  GOTO LED_UIT

;        76543210              
TRISA = %00010000                          
TRISB = %11111111  
  

 SYMBOL T0IE = INTCON.5         ' TMR0 Overflow Interrupt Enable 
 SYMBOL T0IF = INTCON.2         ' TMR0 Overflow Interrupt Flag 
 SYMBOL GIE = INTCON.7          ' Global Interrupt Enable 
 SYMBOL PS0 = OPTION_REG.0      ' Prescaler ratio bit-0 
 SYMBOL PS1 = OPTION_REG.1      ' Prescaler ratio bit-1 
 SYMBOL PS2 = OPTION_REG.2      ' Prescaler ratio bit-2  
 SYMBOL PSA = OPTION_REG.3      ' Prescaler Assignment (1=assigned to WDT 0=assigned to oscillator)  
 SYMBOL T0CS = OPTION_REG.5     ' Timer0 Clock Source Select (0=Internal clock 1=External PORTA.4) 
 SYMBOL LED = PORTA.1 'pin 18 
 DIM hulp AS WORD
   
hulp=0
GOTO MAIN	
 

LED_UIT:
   hulp= hulp+1
    T0IF=0
    CONTEXT RESTORE
 	  END


MAIN:

 GIE = 0          ' Disable global interrupts 
 WHILE GIE = 1    ' Make sure they are off 
 GIE = 0          ' Continue to clear GIE 
 WEND     

 GIE = 0                         ' Turn off global interrupts 
 PSA = 0                         ' Assign the prescaler to Interne WDT oscillator 
 PS0 = 1                         ' Set the prescaler 
 PS1 = 1                         ' to increment TMR0 
 PS2 = 1                         ' every 128h instruction cycle 
 T0CS = 0                        ' Assign TMR0 clock to internal source 
 TMR0 = 0                        ' Clear TMR0 initially 
 T0IE = 1                        ' Enable TMR0 overflow interrupt 
 GIE = 1                         ' Enable global interrupts 
 LED=1
 
 WHILE 1=1
 
 IF hulp < 100 THEN 
 LED=1
 ENDIF
 
 IF hulp >= 100 THEN 
 hulp = 0
 LED=0 
 DELAYMS 2000
 ENDIF

 WEND

END  

Weet iemand of ik iets fout doe met de timer, of met de intterupt. Of dat er misschien een fout in het programma zit. Alle suggesties zijn welkom, want ik wordt er helemaal gek van :P

PS let niet op de structuur van het programma, beetje slordig door alle aanpassingen.

/edit: even de code aangepast nav reactie van arco

Arco

Special Member

In een interrupt kun je geen tijdrovende acties uitvoeren en zeker geen mega-delays van 1 of 5 seconden.
Doe dat in main (zoals het hoort).
De tijd die je in een interrupt doorbrengt dient zo kort als mogelijk te zijn...

[Bericht gewijzigd door Arco op vrijdag 24 oktober 2008 16:07:37 (23%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ok, bedankt Arco. Dat ga ik even proberen.

Hulp = 0. Bij een interrupt komt er dan 1 bij. Dan moet je pic 1s wachten en dan pas word de flag gecleared zodat de volgende interrupt kan komen. Je moet dus 100x1s wachten voordat het ledje uit gaat. En als je ledje uit is gaat ie niet meer aan.

GIE = 0 ' Disable global interrupts
WHILE GIE = 1 ' Make sure they are off
GIE = 0 ' Continue to clear GIE
WEND

Lijkt mij vrij nutteloos. 1x GIE = 0 is zat.

The prescaler is shared between the Timer0 module
and the Watchdog Timer. The prescaler assignment is
controlled in software by the control bit PSA
(OPTION<3>). Clearing the PSA bit will assign the
prescaler to Timer0.

Jij gebruikt de prescaler dus PSA = 0.

In je lijstje in main ook even T0IF = 0 toevoegen voor de zekerheid.

Ok, bedankt.

Ik zal de code even aanpassen. Verder die while loop heb ik uit de help om een device reset te verkomen. Ik geloof dat ze dit deden omdat het mogelijk was dat er een interrupt zou kunnen zijn precies om het moment dat GIE gecleared wordt. Maar dit zou wel kunnen, maar zou echt toevallig zijn.

PS de code is aangepast om lappen tekst te voorkomen

SUPER!

Hij werkt, goed bezig. Dan begrijp ik nu hoe het werkt. Dan kan ik er zelf een beetje mee spelen.

Ik neem aan dat timer1 volgens hetzelfde principe werkt?

En klopt het dat wanneer je GEEN externe occilator gebruikt de waarde van de prescaler maar tot 128 is in te stellen ipv 256?

[Bericht gewijzigd door Rupke Flupke op vrijdag 24 oktober 2008 16:41:04 (28%)

Arco

Special Member

Prescaler gaat tot 256 voor timer 0, en tot 128 indien gebruikt voor de WDT...
Intern/extern clock maakt geen verschil.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

EDIT:

Ik krijg hier zonet alle antwoorden op mijn vragen te lezen in de help van ProtonIDE...

Ik pik hier even in. Ik ben ook bezig met PICBASIC en momenteel met timers.
Wat de prescaler betreft, voor WDT 0-128 en oscillator 0-256, klopt volgende redenering dan?

code:


PS0 PS1 PS2 WDT OSC
 0   0   0   0   2 
 1   0   0   2   4
 0   1   0   4   8 
 1   1   0   8   16
 0   0   1   16  32
 1   0   1   32  64 
 0   1   1   64  128
 1   1   1   128 256

Kan iemand bevestigen of deze while-lus nu wel of niet nodig is? Bestaat de kans dat er werkelijk iets fout gaat als er een interrupt komt op het moment dat GIE gereset wodt?

code:

 GIE = 0          ' Disable global interrupts 
 WHILE GIE = 1    ' Make sure they are off 
 GIE = 0          ' Continue to clear GIE 
 WEND     

 GIE = 0                         ' Turn off global interrupts 

En kan die laatste GIE = 0 niet weggelaten worden?

Het gebruik ervan begrijp ik ook niet helemaal en in vind het niet in de DS van de 16f62x.
Waarom worden global interrupts ge-enabled en ge-disabled op bepaalde tijdstippen?

Als je wilt dat er even geen interrupts zijn, dan kan je ze met het GIE bit uitzetten.

Zoals ik begrepen had zit de while loop erin dat er voorkomen wordt dat er een interupt komt precies om het moment dat de GUI bit gecleared wordt.

Sommige zeggen dat de while overbodig is, maar de kans dat dit gebeurd is klein, maar is er dus wel.

Die laatste GUI = 0 kan inderdaad weggelaten worden. Dit is een beetje dubbelop.

Kan die eerste ook niet worden weggelaten?
Dus alleen de while loop overlaten met daarbinnen de GIE=0?

Volgend project: funcgen met ad9833 afmaken...

Lijkt me wel, maar het kan nooit kwaad om hem te laten staan.