Voor wederom een projectje met ledjes wil ik gebruik maken van een encoder (die van voti) voor de kleurinstelling.
Ik maak gebruik van een software interrupt voor de PWM. Nu wil ik graag de encoder toevoegen en heb al gauw begrepen dat deze om hem bij te houden met een hardware interrupt gebruikt dient te worden.
Heeft iemand een hint hoe een hardware en software interrupt te realiseren is.. hoe zet je de deze beide interrupt parameters?
Alvast bedankt.
16f648A + Proton (picbasic)
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Wat versta jij onder een software interrupt? De 648 heeft voor zover ik weet geen swi in de instructieset.
Als je een externe decoder hebt met een irq uitgang, dan kun je die gewoon met een irq ingang van de pic verbinden. En dan de port juist configureren en de irq enablen.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Een PIC heeft inderdaad geen SWI, zoals bijv. bij de 68HC11. Een hardware interrupt kun je gewoon opwekken door de betreffende interrupt bits aan te zetten. (Een van de timers, of welke andere bron je wilt gebruiken)
Een rotary encoder? tweakers
Boven aan in je interrupt afhandeling zet je.
If (timerxflag == 1){
//als de interrupt van de timer komt doe timerinterupt
//afhandeling
else {
//als de interrupt niet van de timer is, is het van de
// rotary encoder
Bedankt voor de input. Inderdaad.. ik gebruik tmr0 als sourse voor de interrupt flag.
Ik heb onderstaande code en zou hier dus graag de rotary encoder bij willen maken. Ik heb hiervoor het voorbeeld uit de handleiding gebruikt.
Hoe kan ik hier een interrupt on change bij maken?
Alvast bedankt.
DEVICE 16F648A
CONFIG HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
XTAL 20
ALL_DIGITAL TRUE
DIM RED AS BYTE
DIM GREEN AS BYTE
DIM BLUE AS BYTE
DIM TELLER AS BYTE
SYMBOL A = PORTB.4
SYMBOL B = PORTB.5
RED = 0
GREEN = 0
BLUE = 0
ON_INTERRUPT GOTO LED_PWM
' Assign some Interrupt associated aliases
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)
GOTO Over_interrupt ' Jump over the interrupt subroutine
LED_PWM:
TMR0 = 160
IF RED < TELLER THEN
LOW PORTA.0
ELSE HIGH PORTA.0
ENDIF
IF GREEN < TELLER THEN
LOW PORTA.1
ELSE HIGH PORTA.1
ENDIF
IF BLUE < TELLER THEN
LOW PORTA.2
ELSE HIGH PORTA.2
ENDIF
TELLER = TELLER + 1
T0IF = 0 ; INTERRUPT RESET
CONTEXT RESTORE ' Restore the registers and exit the interrupt
Over_interrupt:
' Initiate the interrupt
GIE = 0 ' Turn off global interrupts
PSA = 0 ' Assign the prescaler to external oscillator
PS0 = 0 ' Set the prescaler
PS1 = 0 ' to increment TMR0
PS2 = 0 ' every 32th 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
Inf:
IF B = 0 THEN
IF A = 0 THEN
RED = RED +5
ELSE
RED = RED - 5
ENDIF
ENDIF
DELAYMS 10
GOTO Inf
END
Gewoon het stukje dat bij de rotary encoder hoort er in zetten en de config bits even goed instellen voor beide interrupts. En dan boven in je interrupt afhandeling gewoon kijken wel van de 2 de interrupt veroorzaakt heeft (if else).
Toch wel lekker zo'n zondagje vrij... Rugby wedstrijd afgelast dus tijd over voor de andere hobby...
Ik heb de datasheets nog eens doorgenomen en heb getracht de interrupt bits te begrijpen... Op zich is dit wel duidelijk alleen is de vraag hoe je dit nou juist in een programma verwerkt?
Onderstaand heb ik een stukje code wat werkt. Mijn vraag is nu is dit de juiste manier... en kan ik hier mee verder..
Alvast bedankt.
DEVICE 16F648A
CONFIG HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
XTAL 20
ALL_DIGITAL TRUE
DIM RED AS BYTE
DIM GREEN AS BYTE
DIM BLUE AS BYTE
DIM TELLER AS BYTE
DIM bd1 AS BYTE
DIM richting AS BYTE
RED = 0
GREEN = 255
BLUE = 255
ON_INTERRUPT GOTO ISR
;ON_INTERRUPT GOTO ENCODER
' Assign some Interrupt associated aliases
SYMBOL RBIF = INTCON.0 ;Bit 0 van INTerrupt CONtrol register heet: RB Interrupt Flag
SYMBOL RBIE = INTCON.3 ;Bit 3 van INTCON register heet: RB change Interrupt Enable
SYMBOL INTE = OPTION_REG.4 ; EXTERNAL INTERRUPT OP INT POORT B.0 AAN
SYMBOL INTF = INTCON.1 ; FLAG BITJE VAN EXTERNAL INTERRUPT
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 INTEDG = OPTION_REG.6 ; INTERRUPT EDGE SELECT BIT (1 = RISING EDGE)
SYMBOL A = PORTB.0 ; EXTERNAL INTERRUPT
SYMBOL B = PORTA.4
GOTO Over_interrupt ' Jump over the interrupt subroutine
ISR:
TMR0 = 160
IF RED < TELLER THEN
LOW PORTA.0
ELSE HIGH PORTA.0
ENDIF
IF GREEN < TELLER THEN
LOW PORTA.1
ELSE HIGH PORTA.1
ENDIF
IF BLUE < TELLER THEN
LOW PORTA.2
ELSE HIGH PORTA.2
ENDIF
TELLER = TELLER + 1
IF INTF = 1 THEN
IF A = 0 THEN
IF B = 0 THEN
RED = RED + 1
;WHILE A = 0 : WEND
ELSE
RED = RED - 1
ENDIF
ENDIF
ENDIF
INTF = 0
T0IF = 0 ; INTERRUPT RESET
CONTEXT RESTORE ' Restore the registers and exit the interrupt
Over_interrupt:
' Initiate the interrupt
GIE = 0 ' Turn off global interrupts
PSA = 0 ' Assign the prescaler to external oscillator
PS0 = 0 ' Set the prescaler
PS1 = 0 ' to increment TMR0
PS2 = 0 ' every 32th 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
INTE = 1
INTEDG = 1
Inf:
TOGGLE PORTB.3
DELAYMS 1000
GOTO Inf
END
Bijna
ISR:
if T0IF = 1 then //als het timer0 was dan
TMR0 = 160
IF RED < TELLER THEN
LOW PORTA.0
ELSE HIGH PORTA.0
ENDIF
IF GREEN < TELLER THEN
LOW PORTA.1
ELSE HIGH PORTA.1
ENDIF
IF BLUE < TELLER THEN
LOW PORTA.2
ELSE HIGH PORTA.2
ENDIF
TELLER = TELLER + 1
ENDIF
IF INTF = 1 THEN //als heet portb0 was dan
IF A = 0 THEN
IF B = 0 THEN
RED = RED + 1
;WHILE A = 0 : WEND
ELSE
RED = RED - 1
ENDIF
ENDIF
ENDIF
INTF = 0
T0IF = 0 ; INTERRUPT
CONTEXT RESTORE Zoals je het nu hebt doe je altijd de timer interrupt afhandeling. Maar je wilt dat alleen doen als de timer een interrupt heeft gegenereerd.