PDA

View Full Version : Pin won't stay high during Repeat...Until loop??



jellis00
- 16th August 2009, 23:55
My code is below for reference during this problem description. It has an alias called ext_pwr that is used to set PortC.3 high at the start of the Interrupt Service Routine (ISR) and is intended to stay high for the entire duration of the ISR, and then be set low when the ISR resumes the Main loop (ext_pwr = 0 is first statement in the Main Loop). The ext_pwr alias (PortC.3) is intended to be used to turn on or off a reed relay that is a control for external power delivery.
Must be something I don't understand about the Repeat..Until loop, because the ext_pwr pin is being set low during the loop when not intended. I don't understand why, since no changes are made to PortC.3 or any of the PortC pins during the Repeat...Until loop. Could any of the register settings being made at the start of the Repeat...Until loop cause the PortC.3 pin to go low? Appears to me that the ext_pwr pin should stay high for the entire loop and only go low when the ISR is over and returns to the Main loop, but it doesn't. Can anyone tell me why this is happening???
BTW, this code will run on a PICkit2 LPDB and the four LED's on the LPDB will light according to the PortC pin assignments in this code....purposely done so I can more easily trouble shoot the code before programming my custom board.

jellis00
- 16th August 2009, 23:57
' -----[ Device Declaration ]----------------------------------------------
@ __config _INTRC_OSC_NOCLKOUT & _BOR_OFF & _FCMEN_OFF & _WDT_OFF & _MCLRE_OFF & _CP_OFF

' -----------------[ Declare Variables & Aliases ]
ADINPUT VAR WORD ' Stores VP6 value as sampled by the A/D
b0 VAr vdd.byte1 ' LSB of VDD when right justified
b1 var VDD.Byte0 ' MSB of VDD when right justified
dummy VAR Byte ' For read of on-interrupt port & clear mismatch condition
ext_pwr VAR PORTC.3 ' Set RC3 to control RL2 as RL1 power control source
flush VAR PORTA.3 ' Set RA3 as input for sensing flush switch closure Int
i VAR Byte ' Index used in Gallon counter loop
LED_Grn VAR PORTC.0 ' Set RC0 (Green LED) for valve open..water flowing
LED_Red VAR PORTC.1 ' Set RC1 (Red LED) for solenoid cmnd or low battery
meter VAR PORTA.2 ' Set RA2 as input for HS1 meter pulse Interrupt
sol_valve VAR PORTC.2 ' Set RC2 as valve solenoid open/close command
Vdd VAR WORD ' Stores Vdd value as converted from ADINPUT
Vthr CON 32 ' Set threshold (3.2v) to trigger low voltage warning

' -----[ Declare Constants ]
k CON 10 ' Calibration factor for flow meter...# pulses per gal

' -----[ Initialization ]
Init:
' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000 ' PORTA/B pullups enabled, Interrupt on falling
' edge of RA2/INT, TMR0 clock source is RA2,
' increment on high-to-low transitions, prescaler to
' TMR0, TMR0 Rate 1:2
TMR0 = 256 - k ' preload TMR0 to overflow after k counts
' Initialization of inputs/outputs
flush = 1 ' Initialize RA3 (flush) at High value for flush interrupt
meter = 1 ' Initialize RA2 (meter) at High for METER pulse inputs
' RA2 = TMR0 clock input for simulated meter pulse inputs
ext_pwr = 0 ' Intialize RC3 at low value to turn off external power
sol_valve = 0 ' Initialize RC2 (sol_valve) at Low value
TRISA.2 = 1 ' Set RA2 as input port for clock to TMR0
TRISA.3 = 1 ' Set RA3 as input port for sensing Flush switch closure

' Interrupts Settings
TMR0_Enable VAR INTCON.5 ' Alias for On_Off switch of TMR0 counter
FLUSH_INT_FLAG VAR INTCON.0 ' Alias RA3(FLUSH) On-change-interrupt flag bit
TMR0_INT_FLAG VAR INTCON.2 ' Alias Timer0 overflow flag bit

' Set INT Handler
ON INTERRUPT GOTO Int_handler

'-----[ Main Code Starts Here ]
MAIN:
' Perform following steps to save power during Sleep mode
ext_pwr = 0 ' Turn off external power after interrupt is over
OPTION_REG.7 = 1 ' Disable PortA/PortB pull-ups
OSCCON = %0100011 ' Switch to 1 MHz internal oscillator
VRCON = %00100000 ' Set Voltage Reference for minimum power consumption
' Disable CVref
ANSEL= %11110011 ' Set PortA to Analog I/O to save power during Sleep but
' leave Bits 2 & 3 as digital for RA2 pulse count
' TMR0 overflow interrupt & RA3 On-Change intterupt.
ANSELH= %11111111 ' Analog module enabled to save power during Sleep
CM1CON0.7 = 0 ' Turn off comparators during Sleep
CM2CON0.7 = 0
PCON.4 = 0 ' Turn off BOR during Sleep
WDTCON = %00010110 ' Turn WDT off to SLEEP indefinitely
TRISA = %00001101 ' Set RA0, RA2 & RA3 as inputs
TRISB = %11111111 ' Set all PORTB pins to inputs during Sleep
TRISC = %11111111 ' Set all PORTC pins to input during Sleep
PortA = %11111111 ' Write Port A all High to clear mismatch and save
' power during SLEEP
PortB = %11111111 ' Set all Port B and C pins High to save power
PortC = %11111111 ' in Sleep mode
' Interrupt Settings
INTCON = %10001000 ' Enable interrupts: GIE & RABIE but TMR0 disabled
IOCA = %00001000 ' before SLEEP. Enable RA3 as RABIE on-change-INT
@ sleep
@ NOP ' @ NOP statement here makes no difference
' Microcontroller is in Sleep State waiting for external FLUSH Interrupt
' Valve should be closed at this point and no water flowing
GOTO Main ' Loop to Main to wait for next Flush interrupt on RA3 change

'------{ Begin Interrupt Handler }
DISABLE ' Disable interrupts during interrupt handler
Int_handler:
'Initialize registers upon Interrupt wakeup from Sleep
OPTION_REG.7 = 0 ' Enable PortA/PortB Pullups
WDTCON = %0001000 ' Turn WDT on for ops
' A/D & Comparators disabled
ANSEL=0 ' Set PortA to digital I/O for use with RA2 and RA3
ANSELH=0 ' Analog module disabled
CM1CON0=0 ' Disable comparators
CM2CON0=0

' Port Settings
'TRISA = %00001000 ' Per JoeS to save power
TRISA = %11111111 ' Set all PORTA pins to inputs...RA0, RA2 & RA3 are used
TRISB = %00000000 ' Set all PORTB pins to outputs
'TRISC = %00000000
TRISC = %11110000 ' Set lower 4 pins of PortC as outputs for LEDs
PORTA = %00000000 ' PortA pins all set to Low
PORTC = %00000000 ' LEDs off, PULSOUT RC3 provides a high-going pulse
HIGH ext_pwr ' Turn on power to RL1 and to external power during
' the Interrupt Service Routine

DEFINE WRITE_INT 1
IF FLUSH_INT_FLAG = 1 Then ' Interrupt was from RA3 on change
REPEAT
' Wait until the external Flush interrupt is at high level...limits
' interrupt to switch closure only and not also for switch opening
Until flush = 1
PULSOUT sol_valve,2000*10 ' Generate 100 msec RC2 pulse to RL1 to
' open valve
'Write 7, flush ' Write FLUSH value..remove comment for test only
' Put code here to start a timer to run for 50 secs as a fail safe
' to prevent overflow of toilet tank in case of sensor failure.
'PULSOUT relay_off,2000 ' Generate 20 msec
' pulse to RL2 to turn off power to RL1
Endif
TMR0_Enable = 1 ' Enable the TMR0 pulse counter for overflow interrupt
' Valve is open and water is flowing

REPEAT ' Execute this loop while waiting for flow to reach 1.6 gallons.
' Set registers for using A/D converter
' Set ADCON registers for A/D converter
ADCON0 = %10110101
' ADCON0.7 = ADFM = 1 ' 10-bit result is right justified
' ADCON0.6 = VCFG = 0 ' Set VREF+ to Vdd
' CHS<3:0> = 1101 ' Select 0.6V Ref channel
ADCON1 = %00110000 ' Select FRC as A/D conversion clock source
' Set FOSC=1MHz to stay inside recommended TAD range when not in SLEEP mode
OSCCON = %01000001
' Set ANSEL register to make RA1 analog input
ANSEL= %11110011 ' Set PortA to Analog I/O to save power during Sleep but
' leave Bits 2 & 3 as digital for RA2 and RA3 interrupts
ANSELH= %11111111 ' Analog module enabled to save power during Sleep
DEFine ADC_BITS 10
' Flash Green flow light while water flowing until pulse counter overflows.
LED_Grn = 1
Pause 125
LED_Grn = 0
Pause 500
' If Battery is low..flash low battery monitor light while water flowing
VRCON.4 = 1 ' Turn 0.6V reference ON
PAUSEUS 100 ' Allow VP6 to settle
ADCIN 13,ADINPUT ' Get VP6 analog reading (10-bit)
VRCON.4 = 0 ' Turn 0.6V reference OFF
WRITE 11,ADINPUT
'A/D scale for 0.6 volts is 0.6 * 1024 Full Scale = 6138
VDD = 6138/ADINPUT ' convert input reading to Vdd voltage
' Vdd now holds the measured Vdd voltage * 10 (i.e., 3.4V = 34)
' The formula is the same for any Vdd voltage. Assume normal
' Vdd = +3.95vdc direct from fully charged battery pack input.
WRITE 13,b0 ' Remove comments on Write statements for test only
WRITE 14,b1
Write 17,Vthr
IF Vdd <= Vthr THEN ' If Vdd less than or equal to 3.2v flash the
LED_Red =1 ' Blink RED LED for warning to replace batteries.
PAUSE 125
LED_Red = 0
Pause 500
EndIF
Until TMR0_INT_FLAG = 1 ' Loop ends w/ flow meter pulse counter overflows
PULSOUT sol_valve,2000*10' Generate 100 msec pulse to RC2 & Blink LED_Red
LED_Red = 1 ' Blink RED LED one time to indicate close command
PAUSE 125
LED_Red = 0
Pause 500
'WRITE 19, TMR0_INT_FLAG ' Write TMR0 value..remove comment for test only
dummy = flush ' Clear mismatch condition
FLUSH_INT_FLAG = 0 ' Clear interrupt flag & enable RA3 on interrupt
TMR0_INT_FLAG = 0 ' Clear overflow flag
TMR0 = 256 - k ' Reload TMR0 to overflow after k counts
RESUME ' Resume Main Program
ENABLE
'-------{ End of Interrupt Handler }
END