PDA

View Full Version : Timer1, Interrupts and SLEEP (on 18F45K22) - can't get it to work at all!



jimbostlawrence
- 6th November 2011, 00:07
Hi,
I'm trying to get a circuit I have to save on battery power by sleeping for most of the time. Having read through as much as my head would take of interrupts, timers, sleep modes etc I'm starting to cloud over. I did have timer0 running earlier, creating an interrupt and pulsing a blue LED. I'm now trying to get timer1 to do the same thing, although just getting it to say 'interrupt' on the serial port within the interrupt routine. However, I can't get it to enable. I've even looked at TMR1L/H and they are not incrementing at all!
Going nuts here!!! Can anyone PLEASE take a look at my code (have removed the majority of crap to simplify it for anyone who has the time/inclination...
My eventual aim is to incorporate this code into my already working code for writing I2C sensor data to SD card to allow data capture over several days/weeks from a single battery - note the commented out PMD variables where I was attempting to disable as many peripherals as possible.
Any clues/hints greatly appreciated.

Best regards all, and happy guy fawkes!
Jimbo


define OSC 16
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Auto clear over-run errors
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
blue_LED var portb.5
trisa = %00000000
trisd = %00000000
trisc = %00000000
trisb = %00001000
adcon0.0 = 0
ANSELA = 0
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0
ADCON1 = 15
tmp1 var byte
tmp2 var byte
p1 var byte
p2 var byte
p3 var byte
seconds var byte
pausetime var byte
OSCCON = OSCCON | %11110000 ' set internal clock to 16 MHz incase of switchover
On Interrupt Goto myint
'PMD0 = %11111110
'PMD1 = %11111111
'PMD2 = %11111111
pause 4000
IPR1.0 = 1
INTCON = %11000000 ' global int enable,
T1CON.7 = 1 ' timer 1 clock source is oscillator (external xtal) YES
T1CON.6 = 0 ' """""""""""""""""""""""""""""""""""""""""""""""""" YES
T1CON.5 = 0 ' prescale value set to 1:1 YES
T1CON.4 = 0 ' """"""""""""""""""""""""" YES
TMR1H = $ff
TMR1L = 0
T1CON.2 = 1 ' do not synchronise external clock input with system clock YES
T1CON.1 = 0 ' 8 bit timer?
T1CON.0 = 1 ' enable timer 1
T1CON.3 = 1 ' secondary (external) oscillator enable bit YES
TMR1H = 0 ' Clear time counts before Timer1 re-start
TMR1L = 0 ' Clear time counts before Timer1 re-start
PIR1.0 = 0 ' Clear over-flow flag before enable
PIE3.0 = 1
PIE1.0 = 1 ' timer 1 enable interrupt
lp3:
high blue_LED
p2 = TMR1L
hserout[$d,$a,#p2]
pause 50
low blue_LED
pause 50
goto lp3
Disable
myint:
high blue_LED
pause 50
low blue_led
hserout[$d,$a,"Interrupt!"]
PIR1.0 = 0
Resume
Enable

HenrikOlsson
- 6th November 2011, 09:42
Hi,
You have the two highest bits of T1CON set to 10 and T1CON.3 set to 1 which, if I read the datasheet correctly, sets TMR1 up to be clocked from an external crystal (32768Hz) connected between the SOSCI and SOSCO pins. Do you have a crystal connected here?

If you want TMR1 to be "driven" by the main oscillator (the internal 16MHz oscillator in your case) you should set the two high bits to either 00 (Fosc) or 01 (Fosc/4). This mode however won't work if you want TMR1 to wake the PIC up from sleep since the main osciallator (now "driving" TMR1) is shut down when you enter sleep mode.

/Henrik.

jimbostlawrence
- 6th November 2011, 17:57
Hi Henrik,

Many thanks for your help. I was going round in circles last night. I was confused by the fact that the timer could be clocked when the oscillator was shut down, but as you say, there it was in black and white - secondary oscillator!!! I was glancing past the SOSCI/O part, just seeing the OSCI/O thinking it was the main oscillator. Anyway, I've fitted a 32.768 KHz xtal to the secondary pins and will continue with things. Last night I did manage to get the chip to go to idle, but I guess that's no mean feat! Going to sleep, sent it to sleep and that was that :) lol.

Cheers again, you have been a great deal of help on what most people would consider a simple issue.

Jimbo

jimbostlawrence
- 6th November 2011, 19:33
Hi Henrik,

Just to thank you again. Installed the 32.768KHz xtal with a 12pF cap on each leg to earth and it now all runs. Also, I now have a clearer head and all the settings now make sense in my head. Current drops from around 2mA for my test circuit to about 100uA, which I believe is roughly the norm. This should DRAMATICALLY increase the lifetime of the battery!

The code I now have is below for the benefit of others.

Best regards

Jimbo


define OSC 16
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Auto clear over-run errors
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
blue_LED var portb.5 'prototype =a3, sleep test cct b5
trisa = %00000000
trisd = %00000000
trisc = %00000000
trisb = %00001000
adcon0.0 = 0
ANSELA = 0
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0
ADCON1 = 15
tmp1 var byte
tmp2 var byte
p1 var byte
p2 var byte
p3 var byte
seconds var byte
pausetime var byte
i2cSDA VAR PORTD.1
i2cSCL VAR PORTD.0
pause 50
i2cwrite i2cSDA,i2cSCL, $d0, $3e, [64] ' switch off the gyroscope (save 6.5 mA)
pauseus 5
'I2CWRITE i2cSDA,i2cSCL, $a6, $2c, [%1000] 'accelerometer
pauseus 5
OSCCON = OSCCON | %11110000 ' set internal clock to 16 MHz incase of switchover
On Interrupt Goto myint
PMD0 = %10111110 ' leave UART1 and Timer1 enabled
PMD1 = %10111111 ' leave MSSP1 (SPI) enables
PMD2 = %11111111 ' disable all these peripherals
IPR1.0 = 1
INTCON = %11000000 ' global int enable
OSCCON.7 = 0 ' CPU goes to IDLE when SLEEP command given
T1CON.3 = 1 ' secondary (external) oscillator enable bit
T1CON.7 = 1 ' timer 1 clock source is oscillator (external xtal)
T1CON.6 = 0 ' """"""""""""""""""""""""""""""""""""""""""""""""""
T1CON.5 = 0 ' prescale value set to 1:1
T1CON.4 = 0 ' """""""""""""""""""""""""
T1CON.2 = 1 ' do not synchronise external clock input with system clock
T1CON.1 = 0 ' 2x 8 bit timer value output
TMR1H = $fc ' Clear timer1 count
TMR1L = 0 ' Clear timer1 count
PIR1.0 = 0 ' Clear over-flow flag before enable
PIE1.0 = 1 ' timer 1 enable interrupt
T1CON.0 = 1 ' enable timer 1

lp:

' do something in this loop
sleep 10 ' and then go to sleep

goto lp
stop
Disable
myint:
hserout[$d,$a,"Interrupt!"]
high blue_led
pause 1
low blue_led
TMR1H = $fc
TMR1L = $0

PIR1.0 = 0 ' reset interrupt request flag
Resume
Enable