
Mycket intressant lösning då man kan köra åtta knappar parallellt med bara tre minnesregister.
http://www.dattalo.com/technical/softwa ... rtcnt.html
// Stefan
Kod: Markera allt
knapp_test
;Knapp-koll
bcf knapp_pos, 0 ;Nolla knappens avlästa läge.
btfsc PORTA, 4 ;Knappen är intryckt? Om inte: Hoppa över nästa rad.
bsf knapp_pos, 0 ;Knappen avläst som intryckt en gång..
;Spara current
movf knapp_pos, 0 ;knapp_pos till W.
movwf knapp_current ;W till knapp_current.
;Resultat
movf knapp_previous, 0 ;knapp_previous till W.
andwf knapp_current, 0 ;knapp_current AND W (knapp_previous). Resultatet till W.
movwf knapp_resultat ;W (resultatet) till knapp_resultat.
;Spara nästa previous
movf knapp_current, 0 ;knapp_current till W.
movwf knapp_previous ;W (current) till knapp_previous.
;Knapp_toggle
btfsc knapp_current, 0 ;Är knapp_current = 1 ? Om inte: Hoppa över nästa rad.
comf knapp_onoff, 1 ;Toggla knapp_onoff.
;LED_visning
btfsc knapp_onoff, 0 ;Är knapp_onoff = 1 ? Om inte: Hoppa över nästa rad.
movlw h'00' ;Tänd lysdioderna. (Inverterat, därav 00.)
btfss knapp_onoff, 0 ;Är knapp_onoff = 0 ? Om inte: Hoppa över nästa rad.
movlw h'ff' ;Släck lysdioderna. (Inverterat.)
movwf PORTC ;Lysdioderna..
return
Kod: Markera allt
;****************************************************
list p=PIC16F688
include "p16f688.inc"
;****************************************************
;
; PIC16F688. Intern oscillator på 8MHz.
;
;
; Lysdioder 1 - 6 : RC0 - RC5.
; Knapp (JP1) : RA4. (pin 3).
;
;
;****************************************************
__CONFIG _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF
errorlevel -302
;****************************************************
; Definiera diverse namn...
; #define KNAPP PORTA, 4
;****************************************************
;knapp_vars UDATA_SHR
;variabel RES 1
; det blir mer här senare..
;****************************************************
Boot CODE h'0000'
goto start
;****************************************************
Int_vect CODE h'0004'
goto isr_rutin
;****************************************************
; MACRO
; kommer senare...
;****************************************************
Main CODE
Start
;Generell setup
banksel OPTION_REG
bsf OPTION_REG, NOT_RAPU ;PORT A pull-ups disabled
bsf OPTION_REG, INTEDG ;Interrupt on rising edge of RA2/INT --
bcf OPTION_REG, T0CS ;TMR0 internal clock --
bcf OPTION_REG, PSA ;Prescaler är tilldelad Timer0-modulen --
bsf OPTION_REG, PS2 ;Prescaler 1:128
bsf OPTION_REG, PS1 ;Prescaler 1:128
bcf OPTION_REG, PS0 ;Prescaler 1:128
banksel WDTCON
bcf WDTCON, SWDTEN ;WDT turned off
; Interrupt
banksel INTCON
bsf INTCON, GIE ;Global interrupt enable bit <--
bsf INTCON, PEIE ;Enable unmasked peripheral interrupts <--
bsf INTCON, T0IE ;Enable the Timer0 interrupt <--
bcf INTCON, INTE ;Disable the RA2/INT external interrupt
bcf INTCON, RAIE ;Disable the PORTA change interrupt <--
bcf INTCON, T0IF ;Timer0 did not overflow <--
bcf INTCON, INTF ;RA2/INT external interrupt did not occur
bcf INTCON, RAIF ;None of the PORTA-pins have changed state <--
banksel IOCA
movlw b'00000000' ;Inga interrupt on change på PORTA. <--
movwf IOCA
banksel PIE1
bcf PIE1, EEIE ;Disable the EE write complete interrupt
bcf PIE1, ADIE ;Disable the ADC-interrupt <-- DISABLED NU
bcf PIE1, RCIE ;Disable the EUSART receive interrupt
bcf PIE1, C2IE ;Disable the comparator C2 interrupt
bcf PIE1, C1IE ;Disable the comparator C1 interrupt
bcf PIE1, OSFIE ;Disable the oscillator fail interrupt
bcf PIE1, TXIE ;Disable the EUSART transmit interrupt
bcf PIE1, TMR1IE ;Disable the Timer1 overflow interrupt <<<<
banksel PIR1
clrf PIR1 ;Cleara alla interrupt
bcf PIR1, ADIF ;AD interrupt clear <--
; Klocka
banksel OSCCON
bsf OSCCON, IRCF2 ;8MHz
bsf OSCCON, IRCF1 ;8MHz
bsf OSCCON, IRCF0 ;8MHz
bcf OSCCON, SCS ;Fosc = systemklockan
; I/O
banksel TRISA
; movlw b'00010100' ;Allt till utgångar, bortsett från knappen (R4) och poten (R2).
movlw b'00010000' ;Allt till utgångar, bortsett från knappen (R4).
movwf TRISA
banksel TRISC
clrf TRISC ;Alla till utgångar, för lysdioderna.
banksel PORTA
clrf PORTA ;Tomt
banksel PORTC
movlw h'FF' ;Tomt (OBS: Inverterat för lysdioderna). <<<<<<<<<
movwf PORTC
banksel WPUA
clrf WPUA ;Inga pull-ups
; Timers
banksel TMR0
movlw d'100' ;TMR0 start. <<<<<<<<<<<<<<<<
movwf TMR0
banksel T1CON
bcf T1CON, TMR1ON ;Timer1 avstängd
; Comparator
banksel CMCON0
bsf CMCON0, CM2 ;Comparators avstängda
bsf CMCON0, CM1 ;Comparators avstängda
bsf CMCON0, CM0 ;Comparators avstängda
banksel VRCON
bcf VRCON, VREN ;CVref powered down
; ADC
banksel ANSEL
; movlw b'00000100' ;AN2 (pin 11) analog. Resten digitala
movlw b'00000000' ;Digitala ingångar.
movwf ANSEL
banksel ADCON0
bsf ADCON0, ADFM ;Högerjusterad AD
bcf ADCON0, VCFG ;Vdd som referens
bcf ADCON0, CHS2 ;Channel: AN2 (pin 11)
bsf ADCON0, CHS1 ;Channel: AN2 (pin 11)
bcf ADCON0, CHS0 ;Channel: AN2 (pin 11)
bcf ADCON0, ADON ;ADC disabled <-- DISABLED!!
bcf ADCON0, GO_DONE ;AD-conversion NOT in progress <--
banksel ADCON1
bcf ADCON1, ADCS2 ;AD Conversion clock: Fosc/32 = 250kHz
bsf ADCON1, ADCS1 ;AD Conversion clock: Fosc/32 = 250kHz
bcf ADCON1, ADCS0 ;AD Conversion clock: Fosc/32 = 250kHz
; USART
banksel TXSTA
bcf TXSTA, TXEN ;EUSART transmit disabled
clrf RCSTA ;EUSART port disabled
bcf BAUDCTL,ABDEN ;Auto-baud detect disabled
;Rensa. (För att lättare se i MPLAB SIM.)
clrf rakna_knapp
clrf knapp_onoff
;****************************************************
;****************************************************
;****************************************************
;Main-loopen
loop
goto loop ;Om och om igen...
;****************************************************
;****************************************************
;****************************************************
; Sub-rutiner här under
;****************************************************
knapp_vars UDATA_SHR
knapp_pos RES 1
knapp_onoff RES 1 ;Knappen. (Togglas vid nedtryck.)
knapp_current RES 1
knapp_resultat RES 1
knapp_previous RES 1
sub_rutiner CODE
;****************************************************
knapp_test
;Knapp-koll
bcf knapp_pos, 0 ;Nolla knappens avlästa läge.
btfsc PORTA, 4 ;Knappen är intryckt? Om inte: Hoppa över nästa rad.
bsf knapp_pos, 0 ;Knappen avläst som intryckt en gång..
;Spara current
movf knapp_pos, 0 ;knapp_pos till W.
andlw b'00000001' ;TEST för att försäkra mig om att bara första biten används. <<
movwf knapp_current ;W till knapp_current.
;Resultat
movf knapp_previous, 0 ;knapp_previous till W.
andlw b'00000001' ;TEST för att försäkra mig om att bara första biten används. <<
andwf knapp_current, 0 ;knapp_current AND W (knapp_previous). Resultatet till W.
andlw b'00000001' ;TEST för att försäkra mig om att bara första biten används. <<
movwf knapp_resultat ;W (resultatet) till knapp_resultat.
;Spara nästa previous
movf knapp_current, 0 ;knapp_current till W.
andlw b'00000001' ;TEST för att försäkra mig om att bara första biten används. <<
movwf knapp_previous ;W (current) till knapp_previous.
;Knapp_toggle
btfss knapp_current, 0 ;Är knapp_pos = 1 ? Isåfall: Hoppa över nästa rad.
goto LED_visning
comf knapp_onoff, 0 ;Toggla knapp_onoff. TEST: Resultatet till W.
andlw b'00000001' ;TEST för att försäkra mig om att bara första biten används. <<
movwf knapp_onoff ;TEST tillbaka med resultatet till knapp_onoff.
LED_visning
btfsc knapp_onoff, 0 ;Är knapp_onoff = 1 ? Om inte: Hoppa över nästa rad.
movlw h'00' ;Tänd lysdioderna. (Inverterat, därav 00.)
btfss knapp_onoff, 0 ;Är knapp_onoff = 0 ? Om inte: Hoppa över nästa rad.
movlw h'ff' ;Släck lysdioderna. (Inverterat.)
movwf PORTC ;Lysdioderna..
return
;****************************************************
;****************************************************
; Interrupt
isr_vars UDATA_SHR
pot_lo RES 1
pot_hi RES 1
isr_rutin CODE
isr_rutin
;Timer0 Interrupt. (TMR0 start: 100. Frekvens: 100.16 Hz. Period: 0.009984 sek.)
banksel INTCON
btfss INTCON, T0IF ;TMR0 interrupt? Isåfall: Hoppa över nästa rad.
goto timer0_slut ;Hoppa till slutet.
call knapp_test ;Hoppa till rutinen som läser av knappen.
bcf INTCON, T0IF ;Cleara TMR0 interrupt-flaggan.
bsf INTCON, T0IE ;Redo för nytt interrupt.
movlw d'100' ;TMR0 start. <<<<<<<<<<<<<
movwf TMR0
timer0_slut
retfie
;****************************************************
end
Kod: Markera allt
+V ----[SW]--+--+---- [µC]
| |
[R][C]
| |
+--+
GND