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)

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.

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.

Bedankt bassie. Ga het meteen proberen en uitwerken.