PDA

View Full Version : Using Sleep



elec_mech
- 16th August 2008, 23:36
Ladies & Gents,

I'm attempting to put a 18F2525 to sleep and wake up whenever a keypad button is pressed. When pressed, I tell an LED IC to light up one of 12 LEDs to indicate the button pressed, then go back to sleep. I've used sleep successfully in the past in assembly, but due dominantly to laziness, I'm trying to avoid relearning assembly for this task. I've read several posts on this form, but most of what I've seen either says use an interrupt, which I'm trying to do, without an interrupt routine or shows something with @sleep, @nop and then code immediately following as if sleep is a pause statement.

I'm sure, as usual, I'm doing something silly, but I can't figure it out. I've got the WDT turned off at the beginning and if I turn it on and lessen the WDT postscaler value, the code seems to continuously blink the the LED (for ... next statement in Main routine). If I keep the WDT turned on and increase the postscaler value, as in the code below, the same thing happens every minute or so. I've included a for ... next routine with a slower blink rate when the interrupt routine gets called, but the interrupt routine never appears to get called. If anyone has some advice or a code example on just putting a PIC to sleep and waking up with an interrupt (from a button press) or a link to a post here I've missed, I'd be grateful. Any advice would be appreciated. Thanks in advance!

The code:

INCLUDE "modedefs.bas"
'INCLUDE "pic18f2525.h"
PORTA = $00
PORTB = $00
PORTC = $00
asm

__CONFIG _CONFIG1H, _OSC_INTIO7_1H & _FCMEN_OFF_1H & _IESO_OFF_1H ; Use internal oscillator,
; output clock on RA6, turn off failsafe monitor, disable switch over mode
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOREN_OFF_2L ; Enable Power-up timer, disable brown out
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_32768_2H ; Turn off Watchdog timer, set WDT postscale
; to 1:32,678
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _XINST_OFF_4L ; Turn off stack under/overflow, turn off
; extended instruction set
bcf WDTCON, SWDTEN ; Disable the watchdog timer
bsf OSCCON, IRCF2 ; Set the internal oscillator to 8MHz
bsf OSCCON, IRCF1 ; Set the internal oscillator to 8MHz
bsf OSCCON, IRCF0 ; Set the internal oscillator to 8MHz
MOVLW 0x0F ; Set w = 00001111
MOVWF ADCON1 ; Make all analog pins digital I/Os
MOVLW 0x07 ; Set w = 00000111
MOVWF CMCON ; Make all comparator pins digital I/Os
endasm ' End assembly code
define OSC 8
TRISA = %11110000
TRISB = %11101111
TRISC = %11000000
PORTA = $00
PORTB = $00
PORTC = $00


SPI_CLK VAR PORTC.4 ' Clock for SPI communication
SPI_SDO VAR PORTC.5 ' Serial Data Out for SPI communication
LED_ENABLE VAR PORTB.4 ' OE-DM2, LED enable for STP16DP05's

keypress var byte
i VAR WORD ' Used for for...next loops
first_byte var byte
second_byte var byte
third_byte var byte
temp_byte var byte
first_digit var byte
column var byte
column_value var word
row var byte
row_value var word
temp var byte
number var word
remainder var byte
value var word
keypad_number var byte
check_port var bit

first_byte = $00
second_byte = $00
third_byte = $80 ' Bright Display
'third_byte = $00 ' Dim Display

' Interrupt Setup
Intcon.1 = 0 ' Clear the INT0IF Interrupt Flag bit
' (Last Column Button Press)
Intcon3.0 = 0 ' Clear the INT1IF Interrupt Flag bit
' (Middle Column Button Press)
Intcon3.1 = 0 ' Clear the INT2IF Interrupt Flag bit
' (First Column Button Press)
Intcon2.6 = 1 ' Enable last column button press interrupt on rising edge
Intcon2.5 = 1 ' Enable middle column button press interrupt on rising edge
Intcon2.4 = 1 ' Enable first column button press interrupt on rising edge
On Interrupt goto Halt ' Once an active interrupt port is enabled, go to the Halt routine
Intcon = %10000000 ' Activate global interrupt
Intcon.4 = 1 ' Activate First Column Button Press interrupt
Intcon3.3 = 1 ' Activate Middle Column Button Press interrupt
Intcon3.4 = 1 ' Activate First Column Button Press interrupt

''************************************************ ************************************************** **

SHIFTOUT SPI_SDO, SPI_CLK, 1, [$0000\16] ' Turn off all LED columns
HIGH PORTA.1 ' ENABLE the 1st STP16DP05 to except data
LOW PORTA.1 ' DISABLE the 1st STP16DP05 to except further data

pause 1000

high porta.2

SHIFTOUT SPI_SDO, SPI_CLK, 1, [$FFFF\16] ' Turn on proper LED column
HIGH PORTA.1 ' ENABLE the 1st STP16DP05 to except data
LOW PORTA.1 ' DISABLE the 1st STP16DP05 to except further data

FOR i = 1 to 2
LOW LED_ENABLE
PAUSE 250
HIGH LED_ENABLE
PAUSE 250
NEXT

low porta.2

SHIFTOUT SPI_SDO, SPI_CLK, 1, [$0000\16]
HIGH PORTA.1
LOW PORTA.1

pause 1000

MAIN:
LOW PORTB.3 ' Enable the transistor
for i = 1 to 3
high porta.2
pause 100
low porta.2
pause 100
next
@ SLEEP
GOTO MAIN

Button_Action:
LOW PORTC.0
LOW PORTC.1
LOW PORTC.2
LOW PORTC.3
SELECT CASE column_value
CASE 1
check_port = PORTB.2
CASE 2
check_port = PORTB.1
CASE 3
check_port = PORTB.1
CASE ELSE
GOTO Error
END SELECT
HIGH PORTC.0
IF check_port = 1 THEN
keypad_number = column_value
GOTO Got_Value
ENDIF
LOW PORTC.0
HIGH PORTC.1
IF check_port = 1 then
keypad_number = column_value + 3
GOTO Got_Value
ENDIF
LOW PORTC.1
HIGH PORTC.2
IF check_port = 1 then
keypad_number = column_value + 6
GOTO Got_Value
ENDIF
LOW PORTC.2
HIGH PORTC.3
IF check_port = 1 then
keypad_number = column_value + 9
ENDIF
LOW PORTC.3
column_value = 0
GOTO Error

Got_Value:
LOW PORTC.0
LOW PORTC.1
LOW PORTC.2
LOW PORTC.3
SELECT CASE keypad_number
CASE 1
Value = $0001
CASE 2
Value = $0002
CASE 3
Value = $0004
CASE 4
Value = $0008
CASE 5
Value = $0010
CASE 6
Value = $0020
CASE 7
Value = $0040
CASE 8
Value = $0080
CASE 9
Value = $1000
CASE 10
Value = $2000
CASE 11
Value = $4000
CASE 12
Value = $8000
CASE ELSE
GOTO Error
END SELECT

LOW LED_ENABLE
SHIFTOUT SPI_SDO, SPI_CLK, 1, [$Value\16]
HIGH PORTA.1
LOW PORTA.1

PAUSE 1000

HIGH LED_ENABLE
low porta.2

SHIFTOUT SPI_SDO, SPI_CLK, 1, [$0000\16]
HIGH PORTA.1
LOW PORTA.1

GOTO MAIN

Error:
FOR i = 1 to 3
HIGH PORTA.2
PAUSE 500
LOW PORTA.2
PAUSE 500
NEXT
GOTO Main
'************************************************* ************************************************** ***
Disable ' Disable all interrupts
Halt: ' Halt Routine
HIGH PORTB.3 ' Disable the transistor

HIGH PORTA.2
PAUSE 1000
LOW PORTA.2

column_value = 0 ' Set column value to zero
if Intcon.1 = 1 then ' If a button in the last column was pressed,
column_value = 3 ' Set column value to 3
endif ' End if statement
if Intcon3.0 = 1 then ' If a button in the middle column was pressed,
column_value = 2 ' Set column value to 2
endif ' End if statement
if Intcon3.1 = 1 then ' If a button in the first column was pressed,
column_value = 1 ' Set column value to 1
endif ' End if statement
Intcon.1 = 0 ' Clear the INT0IF Interrupt Flag bit
' (Last Column Button Press)
Intcon3.0 = 0 ' Clear the INT1IF Interrupt Flag bit
' (Middle Column Button Press)
Intcon3.1 = 0 ' Clear the INT2IF Interrupt Flag bit
' (First Column Button Press)
if column_value <> 0 then Resume Button_Action ' If column value is not equal to zero, go to Button Action routine
LOW PORTB.3
HIGH PORTA.2
PAUSE 500
LOW PORTA.2
PAUSE 500
Resume ' Return to sleep
Enable
'************************************************* ************************************************** ***


END

elec_mech
- 17th August 2008, 03:07
I apologize, I posted prematurely. I tried running this without the sleep statement, as I should have done sooner, and my interrupt routine isn't working. I still need help with the proper use of sleep, but I'm attempting to locate the interrupt problem first. I'll post the working interrupt version as soon as I figure this out. If you happen to see anything obvious, I'm all ears, well, eyes anyway. :) I think the problem is in my configurations, but we'll see. Thanks all.

Jerson
- 17th August 2008, 04:05
I haven't specifically used the 18F2525, so I cannot offer you specific advice. However, on the 16F628 and 16F917 that I have used, this is how I do it(from memory)

Enable PORTB interrupt on change. Global interrupts <B>need not</B> be enabled. Then when you want the processor to sleep, just do this


@ sleep
@ nop
@ nop

Any change on Portb pins RB4 to RB7(depends on specific bits being set) would trigger an interrupt flag being set. This event causes the PIC to wake up from sleep even though the global interrupt is disabled. Just in case you need you interrupts to be enabled at that time, you have to ensure that the ISR will read PORTB and reset the Change Flag.

That's all there is to it

Jerson