I went through all the configuration bits and they seem to be OK.
When I "modified" the original code, the only thing that I changed from the configuration bits was the "BORV_27" which I replaced it by the "BORV_25" (the PIC16F1937.INC of my MPLAB compiler does not include the "BORV_27"). I will attach the asm code (which is practically the same as the original) just in case there is a mistake that I cannot detect myself:
;===========================================================================
; A 4-buttons capacitance touch sensor using the built-in capacitance module
; of the PIC, and the Tmr0 as a timebase.
;===========================================================================
list F=inhx8m, P=16F1937, R=hex, N=0
#include P16F1937.inc; PIC definitions
__config _CONFIG1,_FCMEN_OFF & _IESO_ON & _CLKOUTEN_ON & _BOREN_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_OFF & _WDTE_OFF & _FOSC_INTOSC
__config _CONFIG2,_LVP_ON & _BORV_25 & _STVREN_OFF & _PLLEN_OFF & _VCAPEN_OFF & _WRT_OFF
Errorlevel -302, -224
; Definitions -------------------------------------------------------------
#define Out_4_Pin PORTD,1
#define Out_3_Pin PORTD,0
#define Out_2_Pin PORTC,3
#define Out_1_Pin PORTC,2
; RAM preserved -----------------------------------------------------------
cblock 0x20
PassArg1
CountH,CountL
CapCh1_H,CapCh1_L
CapCh2_H,CapCh2_L
CapCh3_H,CapCh3_L
CapCh4_H,CapCh4_L
endc
; Conastants --------------------------------------------------------------
PressThreshold_H equ b'00000000' ; This is the Press Threshold Constant pair (PressThreshold_H:PressThreshold_L).
PressThreshold_L equ b'00010110' ; Increasing this 16-bit value, decreased button sensitivity and opposite
ReleaseThreshold_L equ b'00000101' ; This is the Release threhold value. Increasing this 8-bit value increases the hysteresis
; for button release. It must be less than PressThreshold_L, otherwise the button will never be released
; Program Memory ----------------------------------------------------------
org 0
goto Init
; Interrupt Service Routine -----------------------------------------------
org 4 ; ISR beginning
; btfss intcon,TMR0IF ; Check if int called from TMR0 overflow
; retfie ; If not (most unlikely) then return. Enable these lines
; only if you modify the program to handle more interrupts.
btfsc T1GCON,T1GVAL ; Check the state of the toggle FF of Tmr1 Gate
goto ButtonCheckEnds ; If is SET, means that it was LOW when TMR0 overflowed
; So TMR1 did not count. So return
bcf T1CON,TMR1ON ; Stop Timer1 - Not really nessecary
movf TMR1L,w ; Save its contents
movwf CountL ;
movf TMR1H,w ;
movwf CountH ;
movf CPSCON1,w ; Check CPSCON1 which holds
btfsc STATUS,Z ; the right channel curently active
goto Cap_Check_Ch_1 ; Then, go to the appropriate routine
movwf PassArg1 ;
decf PassArg1,f ;
btfsc STATUS,Z ;
goto Cap_Check_Ch_2 ;
decf PassArg1,f ;
btfsc STATUS,Z ;
goto Cap_Check_Ch_3 ;
Cap_Check_Ch_4 ; Check routine for channel 4 (all 4 are identical)
clrf CPSCON1 ; Prepare capacitance module to check channel 0 next time
movf CapCh4_H,w ; Check the value of CapCh4_H and CapCh4_L
addwf CapCh4_L,w ; If both are 0x00, this means that this channel is
btfsc STATUS,Z ; tested for the first time. So go to the Initializing routine
goto IsFirstTime_4 ; of this channel to acquire initial values
movf CountH,w ; Otherwise, check if the current count for this channel
movwf PassArg1 ; is less than the Press Threshold Value calculated
movf CapCh4_L,w ; in the initializing routine
subwf CountL,w ;
btfss STATUS,C ;
decf PassArg1,f ;
movf CapCh4_H,w ;
subwf PassArg1,f ;
btfss STATUS,C ;
goto $+2 ;
goto $+3 ;
bsf Out_4_Pin ; If it is, then enable appropriate output!
goto ButtonCheckEnds
movf CapCh4_L,w ; If not, then it could be released. Check again, but this
addlw ReleaseThreshold_L ; time ADD the Release Threshold, to achieve hysteresis
subwf CountL,w ;
btfss STATUS,C ;
decf CountH,f ;
movf CapCh4_H,w ;
subwf CountH,w ;
btfsc STATUS,C ; If the count is above the Press Threshold PLUS the
bcf Out_4_Pin ; Release Threshold, then the4 button is released!
goto ButtonCheckEnds
; All routines for button check are identical with the above
; No need for additional comments
Cap_Check_Ch_3 ; Check routine forchannel 3
incf CPSCON1,f ; Prepare capacitance module to check channel 3 next time
movf CapCh3_H,w
addwf CapCh3_L,w
btfsc STATUS,Z
goto IsFirstTime_3
movf CountH,w
movwf PassArg1
movf CapCh3_L,w
subwf CountL,w
btfss STATUS,C
decf PassArg1,f
movf CapCh3_H,w
subwf PassArg1,f
btfss STATUS,C
goto $+2
goto $+3
bsf Out_3_Pin
goto ButtonCheckEnds
movf CapCh3_L,w
addlw ReleaseThreshold_L
subwf CountL,w
btfss STATUS,C
decf CountH,f
movf CapCh3_H,w
subwf CountH,w
btfsc STATUS,C
bcf Out_3_Pin
goto ButtonCheckEnds
Cap_Check_Ch_2 ; Check routine forchannel 2
incf CPSCON1,f ; Prepare capacitance module to check channel 2 next time
movf CapCh2_H,w
addwf CapCh2_L,w
btfsc STATUS,Z
goto IsFirstTime_2
movf CountH,w
movwf PassArg1
movf CapCh2_L,w
subwf CountL,w
btfss STATUS,C
decf PassArg1,f
movf CapCh2_H,w
subwf PassArg1,f
btfss STATUS,C
goto $+2
goto $+3
bsf Out_2_Pin
goto ButtonCheckEnds
movf CapCh2_L,w
addlw ReleaseThreshold_L
subwf CountL,w
btfss STATUS,C
decf CountH,f
movf CapCh2_H,w
subwf CountH,w
btfsc STATUS,C
bcf Out_2_Pin
goto ButtonCheckEnds
Cap_Check_Ch_1 ; Check routine forchannel 1
incf CPSCON1,f ; Prepare capacitance module to check channel 1 next time
movf CapCh1_H,w
addwf CapCh1_L,w
btfsc STATUS,Z
goto IsFirstTime_1
movf CountH,w
movwf PassArg1
movf CapCh1_L,w
subwf CountL,w
btfss STATUS,C
decf PassArg1,f
movf CapCh1_H,w
subwf PassArg1,w
btfss STATUS,C
goto $+2
goto $+3
bsf Out_1_Pin
goto ButtonCheckEnds
movf CapCh1_L,w
addlw ReleaseThreshold_L
subwf CountL,w
btfss STATUS,C
decf CountH,f
movf CapCh1_H,w
subwf CountH,w
btfsc STATUS,C
bcf Out_1_Pin
ButtonCheckEnds
movlw 0xff ; Here is an interesting trick: The flip flop of the Tmr1 gate is now
movwf TMR0 ; low, which means that even if TMR0 overflows, TMR1 will not count. So,
btfss T1GCON,T1GVAL ; i make TMR0 0xFF and let it run to quickly overflow. This way, the flip flop
goto $-1 ; will be HIGH again, ready to check the next channel. This trick only saves
; time. It is not very important, it will work without it, but hey, there must
; be something to distinguish us from Arduino developers, right?
clrf TMR1L ; Reset Timer1 module
clrf TMR1H ;
clrf TMR0 ; Reset Timer0 module AND prescaller
bsf T1CON,TMR1ON ; Start Timer1
bcf INTCON,TMR0IF ; Clear Tmr0IF flag (to re-enable TMR0 interrupt)
retfie ; RETurn From Interrupt
IsFirstTime_1
;Initializing Channel 1
movlw PressThreshold_L ; In this sub, the Press Threshold for each button
subwf CountL,w ; is calculated. This Press Threshold is calculated
movwf CapCh1_L ; by the Tmr1 count, minus a constant named
movf CountH,w ; PressThreshold_H:PressThreshold_L.
btfss STATUS,C ;
decf CountH,w ;
movwf CapCh1_H ;
movlw PressThreshold_H ;
subwf CapCh1_H,f ;
goto ButtonCheckEnds ;
; All routines for button check are identical with the above
; No need for additional comments
IsFirstTime_2
;Initializing Channel 2
movlw PressThreshold_L
subwf CountL,w
movwf CapCh2_L
movf CountH,w
btfss STATUS,C
decf CountH,w
movwf CapCh2_H
movlw PressThreshold_H
subwf CapCh2_H,f
goto ButtonCheckEnds
IsFirstTime_3
;Initializing Channel 3
movlw PressThreshold_L
subwf CountL,w
movwf CapCh3_L
movf CountH,w
btfss STATUS,C
decf CountH,w
movwf CapCh3_H
movlw PressThreshold_H
subwf CapCh3_H,f
goto ButtonCheckEnds
IsFirstTime_4
;Initializing Channel 4
movlw PressThreshold_L
subwf CountL,w
movwf CapCh4_L
movf CountH,w
btfss STATUS,C
decf CountH,w
movwf CapCh4_H
movlw PressThreshold_H
subwf CapCh4_H,f
goto ButtonCheckEnds
; -------------------------------------------------------------------------
; Microcontroller initialization
Init
;Set Clock
movlb 0x01
movlw b'01111000'
movwf OSCCON
movlb 0x00
;No ANSEL
movlb 0x03
clrf ANSELA
clrf ANSELB
clrf ANSELD
clrf ANSELE
movlb 0x00
; Main Program ------------------------------------------------------------
Start
clrf PORTA ; Clear all ports
clrf PORTB ;
clrf PORTC ;
clrf PORTD ;
; TRIS setup
movlb 0x01 ; Go to bank 1
movlw b'11111111' ;
movwf TRISA ; Set the port pin types of the RA
movlw b'11111111' ;
movwf TRISB ; Set the port pin types of the RB
movlw b'11110011' ;
movwf TRISC ; Set the port pin types of the RC
movlw b'11111100' ;
movwf TRISD ; Set the port pin types of the RD
movlb 0x00 ; Go to bank 0
clrf CapCh1_H ; Clear all RAM positions for Press Threshold
clrf CapCh1_L ; values. This way, the ISR will see that
clrf CapCh2_H ; these values are 0x00, and it will
clrf CapCh2_L ; run an initializing routine for each one
clrf CapCh3_H ; during which, the PressThreshold value
clrf CapCh3_L ; for each individual button will be
clrf CapCh4_H ; calculated on start-up
clrf CapCh4_L ;
clrf INTCON ; Disable all interrupts
bsf INTCON,TMR0IE ; Enable only the TMR0 overflow interrupt
movlw b'10001100' ; Setup capacitance module.
movwf CPSCON0 ;
movlw b'00000000' ; Channel 0 (CPS0) is first to check.
movwf CPSCON1 ; I call it channel 1. Icount from base 1, not 0.
movlw b'11000101' ; I use the capacitance module with TMR0 as timer.
OPTION ; So i have to set-it up through the Option Register
; The prescaler is also connected to TMR0.
; Bit 5: TMR0 Source is internal instruction clock (Fosc/4)
; Bit 3: Prescaller assigned to TMR0 module
; Bits <2:0>: Prescaller rate is 1:64
movlw b'11000100' ; Setup TMR1 module Control register
movwf T1CON ; Bits <7:6>: Timer 1 source is Capacitive Sensing Oscillator
; Bits <5:4>: Prescaller is 1:1
; Bit 3: LP oscillatos is deactivated
; Bit 2: No synchronization
; Bit 0: Timer 1 is stopped
movlw b'11100001' ; Setup Timer 1 Gate module
movwf T1GCON ; Bit 7: Gate controls the counting function of TMR1
; Bit 6: Gate polarity is Active HIGH
; Bit 5: Gate input is through Toggle FF
; Bits <4:3>: No single pulse mode
; Bits <1:0>: Gate source is Timer0 overflow
clrf TMR1L ; Clear TMR1 High and Low registers
clrf TMR1H ;
clrf TMR0 ; Clear TMR0 register AND prescaller
bsf T1CON,TMR1ON ; Start TMR1
bsf INTCON,GIE ; Enable global interrupts
MainLoop ; This is an infinate loop, only interrupted whenever
goto MainLoop ; a TMR0 overflow occures. When does, the program flow
; goes to the ISR routine (org 0x04) which checks the
; state of one button, and prepares the capacitance module
; to check the state of the next button, the next time that
; TMR0 overflows
end ; end of program