PDA

View Full Version : tmr2 interrupt problem



ADCON
- 27th December 2007, 19:05
Hello all,

I have a problem with a tmr2interrupt. I have programmed a several things but that was lways in loops and now 1 want to change my program.

I use a pic16f628 controller at 4MHz internal ascillator.
I want to use timer2 to generate an interrupt every 2milliseconds.
Only problem is that it never gets to the interruptroutine..
It is for a RTC controlled clock with muxed 7segment displays at two 74hc595 shiftregisters.

Here is the problem code

@ DEVICE pic16F628a, INTRC_OSC_NOCLKOUT
' System Clock Options
@ DEVICE pic16F628a, WDT_OFF
' Watchdog Timer
@ DEVICE pic16F628a, PWRT_ON
' Power-On Timer
@ DEVICE pic16F628a, BOD_ON
' Brown-Out Detect
@ DEVICE pic16F628a, MCLR_OFF
' Master Clear Options (Internal)
@ DEVICE pic16F628a, LVP_OFF
' Low-Voltage Programming
@ DEVICE pic16F628a, CPD_OFF
' Data Memory Code Protect
@ DEVICE pic16F628a, PROTECT_OFF
' Program Code Protection
@ DEVICE pic16F628a, MCLR_OFF
define OSC 4 'runs at 4MHz

INCLUDE "modedefs.bas" 'for shiftout

segments var byte
counter var byte

Symbol tmr2if=PIR1.1
Symbol tmr2ie=PIE1.1
Symbol gie =INTCON.7

'Turn on INTCON.7(GIE) and INTCON.5 (TMR0IE)
INTCON = %10100000
tmr2ie=1
gie=1

on interrupt GoTo isr
GoTo loop

;-----------------------------------------------------------
isr:
'Clear tmr2if
disable
segments = %01111011
counter=%00000000 'only for test. all segments are on.
if hr.6=1 then 'mode indication
segments.7=%1
endif
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1
'return
INTCON.6 =0
enable
INTCON.6 =0
resume

loop: 'main programloop
repeat
'sec=%00000111
until 0=1
END

The full code is about 10 a4 sides of paper..

I hope that anyone knows what I do wrong and can help me.

Thanks.
Martijn

mister_e
- 27th December 2007, 19:08
almost sure i'm right, you should enable peripheral interrupts as well. INTCON.6=1

mmm, Tmier2---shouldn't be something to do with PR2 as well?

i'll dig the datasheet.. been awhile i didn't use that pic now.

ADCON
- 27th December 2007, 19:22
Thnx for the fast answere.

Wel, i only make intcon.6 0 in the isr-loop.

Hope you can help me..

mister_e
- 27th December 2007, 19:38
TRY


@ __CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

CMCON=7
TRISA=0
TRISB=0
PORTA=0
PORTB=0

PIE1 = %00000010
'0------- Disable EE write complete interrupt
'-0------ Disable comparator interrupt
'--0----- Disable USART receive interrupt
'---0---- Disable USART transmit interrupt
'----x--- unimplemented
'-----0-- Disable CCP1 interrupt
'------1- Enable TMR2 to PR2 match interrupt
'-------0 Disable TMR1 overflow interrupt

T2CON = %00000010
'X------- Unimplemented
'-0000--- postscale 1:1
'-----0-- Timer2 off
'------10 prescaler 1:16


GIE VAR INTCON.7
PEIE VAR INTCON.6
TMR2IF VAR PIR1.1
TMR2ON VAR T2CON.2
RELOAD CON 131

ON INTERRUPT GOTO ISR
TMR2 = RELOAD
PR2 = 0
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR:
TOGGLE PORTB.0
TMR2ON = 0
TMR2 = RELOAD
TMR2ON = 1
TMR2IF = 0 ' Clear interrupt flag
resume
enable

LOOP:
'TOGGLE PORTB.1
GOTO LOOP




or another variant of



@ __CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

CMCON=7
TRISA=0
TRISB=0
PORTA=0
PORTB=0

PIE1 = %00000010
'0------- Disable EE write complete interrupt
'-0------ Disable comparator interrupt
'--0----- Disable USART receive interrupt
'---0---- Disable USART transmit interrupt
'----x--- unimplemented
'-----0-- Disable CCP1 interrupt
'------1- Enable TMR2 to PR2 match interrupt
'-------0 Disable TMR1 overflow interrupt

T2CON = %00000010
'X------- Unimplemented
'-0000--- postscale 1:1
'-----0-- Timer2 off
'------10 prescaler 1:16


GIE VAR INTCON.7
PEIE VAR INTCON.6
TMR2IF VAR PIR1.1
TMR2ON VAR T2CON.2

ON INTERRUPT GOTO ISR
PR2 = 124 ' load period register for 2mSec
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR:
TOGGLE PORTB.0
TMR2IF = 0 ' Clear interrupt flag
resume
enable

LOOP:
'TOGGLE PORTB.1
GOTO LOOP

The second one is probably the best method to deal with Timer2. have a look to section 6.0 of your datasheet.

ADCON
- 28th December 2007, 13:35
Thanks, it works now!
First i tried to inplement your code in mine but that didnd work.
So I fit my program in yours and the first test works.
Here's my code fore enyone with the same problem.
Now I'm have to set all my other code in it. Hope it don't make problems with the changed config now.



@ device pic16F628a, INTRC_OSC_NOCLKOUT
@ device pic16F628a, MCLR_ON
@ device pic16F628a, LVP_OFF
@ device pic16F628a, WDT_OFF
@ device pic16F628a, PWRT_ON
@ device pic16F628a, BOD_ON
INCLUDE "modedefs.bas" 'for shiftout

CMCON=7
TRISA=0
TRISB=0
PORTA=0
PORTB=0

PIE1 = %00000010
'0------- Disable EE write complete interrupt
'-0------ Disable comparator interrupt
'--0----- Disable USART receive interrupt
'---0---- Disable USART transmit interrupt
'----x--- unimplemented
'-----0-- Disable CCP1 interrupt
'------1- Enable TMR2 to PR2 match interrupt
'-------0 Disable TMR1 overflow interrupt

T2CON = %00000010
'X------- Unimplemented
'-0000--- postscale 1:1
'-----0-- Timer2 off
'------10 prescaler 1:16

segments var byte
counter var byte
GIE VAR INTCON.7
PEIE VAR INTCON.6
TMR2IF VAR PIR1.1
TMR2ON VAR T2CON.2

ON INTERRUPT GOTO ISR
PR2 = 124 ' load period register for 2mSec
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR:
'first half of the displays
segments=%01011011 '5
counter=%01010101 'on displays
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1 'for latch 74hc595

'remaining displays
segments = %00110000 '1
counter=%10101010
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1 'for latch 74hc595
'------- ^^my try

TOGGLE PORTB.0
TMR2IF = 0 ' Clear interrupt flag
resume
enable

LOOP:
'TOGGLE PORTB.1
GOTO LOOP
end

ADCON
- 28th December 2007, 16:11
Dear,

I still have a problem.

I have merged all the code and the beginning works fine now.
It go's to the loop: makes a I2C read.
Go's to another loop for I2C write(only if needed).

Then it have to wait for the the interupt.
At the interrupt is starts to shiftout the data for the display.
Until here it works fine.

The problem is: it keeps doing that and NEVER goes back to the loop..

This didn't I know becose in the testprogram there was noting to do in the loop..

I can post the code when someone needs it but it's the same as above, only with some onther code inside it.

Dos anyone know what I do wrong?

mister_e
- 28th December 2007, 21:22
ISRs should be keep as short as possible, i feel that what you do inside may need much time than 2mSec?

If so... :eek: you may stop the timer, do your stuff, re-start the timer and clear the interrupt flag.. but yeah you loose all of this needed 2mSec accuracy... even using Darrel's favorite ON INTERRUPT :D

Try to reduce your 2mSec to let's say 5-10 mSec
But that's a feeling. Post your whole code here with the I2C stuff.

ADCON
- 28th December 2007, 22:28
My isr is long, but at 4MHz and no delay instructions it has not to be the problem.
Well, I tried to set the presale to 1:16. 1:4 had to make a interrupt every 2mSec.
after that I tried to turn off the timer and after that, turn it back on. All had no effect.
So, I came back here.

This is all my code:
first config, var's and isr
then main loop
after that the complete menu
Much of the code was for a rtc-clock using a lcd. Thats why some of the loops are empty now.




@ device pic16F628a, INTRC_OSC_NOCLKOUT
@ device pic16F628a, MCLR_ON
@ device pic16F628a, LVP_OFF
@ device pic16F628a, WDT_OFF
@ device pic16F628a, PWRT_ON
@ device pic16F628a, BOD_OFF'ON
INCLUDE "modedefs.bas" 'for shiftout
pause 50

' Defines
' ----------------
'I2C pins
DS_SCL VAR PORTA.0 ' I2C clock pin
DS_SDA VAR PORTA.1 ' I2C data pin
'RTC CON %11010000 ' RTC device address (byte addressing) not needed

'Setting the RTC so we can get out 1Hz tick output
'-------------------------------------------------
' -------------- RTC definitions -----------------
SecReg CON $00 ' seconds address (00 - 59)
' MSB of SecReg must be set to a 0 to enable RTC
MinReg CON $01 ' minutes address (00 - 59)
HourReg CON $02 ' hours address (01 - 12) or (00 - 23)
DayReg CON $03 ' day address (1 - 7)
DateReg CON $04 ' date address (01 - 28/29, 30, 31)
MonthReg CON $05 ' month address (01 - 12)
YearReg CON $06 ' year address (00 - 99)
ContReg CON $07 ' control register
RTCflag CON 0 ' RTC flag (location 0 of internal EEPROM)
cntrl CON %00010000 ' sets the SQW/OUT to 1Hz pulse, logic level low

' The variable below holds the values entered:
'menu var's
_sec VAR BYTE ' $00 set seconds
_min VAR BYTE ' $56 set minutes
_hr VAR BYTE ' $23 set hour
_day VAR BYTE ' $06 set day
_date VAR BYTE ' $28 set date
_mon VAR BYTE ' $02 set month
_yr VAR BYTE ' $03 set year

'rtc var's
sec VAR BYTE ' seconds
MINs VAR BYTE ' minutes
hr VAR BYTE ' hours
day VAR BYTE ' day
date VAR BYTE ' date
mon VAR BYTE ' month
yr VAR BYTE ' year

'button input
'-------------------
SetButton var PORTa.7 ' Press to Set/memorise Button
DecButton var PORTa.3 ' Press to Decrement Button
IncButton var PORTa.2 ' Press to Increment Button

'other var's
'------------------
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
CounterC var byte ' General purpose Variable
CounterD var byte ' General purpose Variable
ButtonRepeat con 200 ' Timeperiod (in mS for Edit Buttons auto-repeat
' should you want to hold them down...
RTCCtrl var byte ' Control
TimeOut var word ' Variable for SetUp Menu Time-Out
SetTime var byte ' 12/24 Hour Clock
RTCWDay var byte ' Weekday
timeformat var word ' place for displaying am/pm
counter var byte
counter2 var byte
counter3 var word ' delaycounter
counter4 var word ' counter at redisplayloop
segments var byte
myBCD var byte
toDEC var byte

'I/O pins
'port conditions
'---------------
CMCON=7
TRISA=0
TRISB=0
PORTA=0
PORTB=0

'timer and interruptconditions
'----------------
PIE1 = %00000010
'0------- Disable EE write complete interrupt
'-0------ Disable comparator interrupt
'--0----- Disable USART receive interrupt
'---0---- Disable USART transmit interrupt
'----x--- unimplemented
'-----0-- Disable CCP1 interrupt
'------1- Enable TMR2 to PR2 match interrupt
'-------0 Disable TMR1 overflow interrupt

T2CON = %00000010
'X------- Unimplemented
'-0000--- postscale 1:1
'-----0-- Timer2 off
'------10 prescaler 1:16

GIE VAR INTCON.7
PEIE VAR INTCON.6
TMR2IF VAR PIR1.1
TMR2ON VAR T2CON.2
RELOAD CON 131

ON INTERRUPT GOTO ISR
TMR2 = RELOAD
PR2 = 0 ' load period register for 2mSec
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR: 'interruptroutine
TMR2ON=0
'later to use to reduce the isr text. then only shiftout the var's
if counter3=>200 then 'number of shiftouts
counter3=0
else
counter3=counter3+1
endif

'hours
'the one that is 0 wil blink
'for segments the opposite
counter = %01111111 '1 segment
toDEC = hr
if hr.6=1 then '12 uurs mode
todec = todec <<3
todec = todec >>7
else '24 uurs mode
todec = todec <<2
todec = todec >>6
endif
gosub findsegments
if hr.6 = 1 then 'add in the am/pm indication
if hr.5 = 1 then
segments.7 = %1
endif
endif
gosub segmentsshiftout

counter = %10111111 '2 segment
toDEC = hr
toDEC = toDEC << 4 'shiftout unusable data
todec = todec >> 4 'shiftback usable data
gosub findsegments
if portA.6 = 1 then segments.7 = %1 'add the blinkin dot
gosub segmentsshiftout

'minits
counter = %11011111 '3 segment
toDEC = MINs
todec = todec >> 4 'shiftback usable
gosub findsegments
gosub segmentsshiftout

counter = %11101111 '4 segment
toDEC = MINs
todec = todec << 4 'shiftout unusable data
todec = todec >> 4
gosub findsegments
gosub segmentsshiftout

'seconds
counter = %11110111 '5 segment
toDEC = sec
todec = todec >> 4 'shiftback usable
gosub findsegments
gosub segmentsshiftout

counter = %11111011 '6 segment
toDEC = sec
todec = todec << 4 'shiftout unusable data
todec = todec >> 4
gosub findsegments

if hr.6=1 then 'mode indication
segments.7=%1
endif
gosub segmentsshiftout

counter = %11111111 'to take care that no segment is blinking harder
todec = %00000000'todec >> 4
gosub segmentsshiftout

segmentsshiftout:
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1
return
findsegments:
if todec=%00000000 then '0
segments = %01111110
endif
if todec=%00000001 then '1
segments = %00110000
endif
if todec=%00000010 then '2
segments = %01101101
endif
if todec=%00000011 then '3
segments = %01111001
endif
if todec=%00000100 then '4
segments = %00110011
endif
if todec=%00000101 then '5
segments = %01011011
endif
if todec=%00000110 then '6
segments = %01011111
endif
if todec=%00000111 then '7
segments = %01110000
endif
if todec=%00001000 then '8
segments = %01111111
endif
if todec=%00001001 then '9
segments = %01111011
endif
return
TMR2 = RELOAD
TMR2ON = 1
TMR2if=0 ' Clear interrupt flag

resume
enable


LOOP:
I2CRead DS_SDA,DS_SCL,$D0,$00, [sec,MINs,hr,day,date,mon,yr] ' Read Ds1307
If sec.7=1 then goto coldstart
If setbutton = 0 then 'if setbutton is pressed
_hr=hr
_min=MINs
_sec=sec
gosub SetButtonRelease
Gosub SetTimeAndDate 'after release
endif
counter3=0
repeat 'show the segments for 5 times.
pauseus 10
until counter3 > 5
GoTo Loop
end

Segmentswrite2:'write settimevar's to timevar's in bcd
CounterA=_hr
If SetTime=1 then
If CounterA>12 then CounterA=CounterA-12
If CounterA=0 then CounterA=12
endif
Gosub ConvertBCD
hr=CounterB
' Save the Hours Value
If SetTime=1 then
hr.6=1
' Save the 12 Hour Mode Flag
If _hr=>12 then hr.5=1
' Save the 'PM' Flag
endif
'
' Save Minutes
' ------------
CounterA=_min
Gosub ConvertBCD
MINs=CounterB
'
' Save Seconds
' ------------
CounterA=_sec
Gosub ConvertBCD
sec=CounterB
'gosub segmentswrite
return

'paste here the other half of the code

ADCON
- 28th December 2007, 22:29
the text wat to long to set in one message





'paste here the above code

SetTimeAndDate:
'=============
Setup:
SetTime=hr.6 ' Determines 12/24 Hour mode
If SetTime=1 then
' Regardless of 12/24 options, SetHour always
' contains the hours in 24 hour clock format
' otherwise there's twice the amount of work
' to keep track in the edit routines
_hr=(hr>>4)&$01
' if 12-hour mode
else
_hr=(hr>>4)&$03
' if 24 hour mode
endif
_hr=_hr*10+(hr&$0F)
If SetTime=1 then
If hr.5=1 then
If _hr<12 then _hr=hr+12
' Add-in the AM/PM indicator
else
If _hr=12 then _hr=0
endif
endif
_Min=((Mins>>4)&$0F)*10+(Mins&$0F)
_Sec=((Sec>>4)&$0F)*10+(sec&$0F)
_yr=((yr>>4)&$0F)*10+(yr&$0F)
_mon=((mon>>4)&$0F)*10+(mon&$0F)
_day=((day>>4)&$0F)*10+(day&$0F)
'
' Setup Menu Loop
' ---------------
CounterC=0 ' Set to Start of Setup (seven steps from 0 to 6)
TimeOut=0 ' Zero the Time-Out counter
SetupLoop:
'
' Now Display the Data
' --------------------
SetupDisplayLoop:
'
' 12/24 Hour Option
' -----------------
'
' The Data-Entry Bit
' ------------------
SetupEntryLoop: 'datainput.
'
' Decrement(down) Button Pressed
' ------------------------
If DecButton=0 then
'
' 12/24 Clock Selection
' ---------------------
If CounterC=0 then
If SetTime=0 then
SetTime=1
else
SetTime=0
endif
endif
'
' Decrement Hours
' ---------------
If CounterC=1 then
If _hr=0 then
_hr=23
else
_hr=_hr-1
endif
endif
'
' Decrement Minutes
' -----------------
If CounterC=2 then
If _Min=0 then
_Min=59
else
_Min=_Min-1
endif
endif
'
' Decrement Seconds
' -----------------
' Kinda overkill to include setting seconds,
' but if you got codespace to burn...
If CounterC=3 then
If _Sec=0 then
_Sec=59
else
_Sec=_Sec-1
endif
endif
gosub Pauseloop
TimeOut=0
Goto SetUpDisplayLoop
endif
'
' Increment(up) Button Pressed
' ------------------------
' This is just like Decrement but opposite...
If IncButton=0 then
'
' 12/24 Clock Selection
' ---------------------
If CounterC=0 then
If SetTime=1 then
SetTime=0
else
SetTime=1
endif
endif
'
' Increment Hours
' ---------------
If CounterC=1 then
If _hr=>23 then
_hr=0
else
_hr=_hr+1
endif
endif
'
' Increment Minutes
' -----------------
If CounterC=2 then
If _min=>59 then
_Min=0
else
_Min=_Min+1
endif
endif
'
' Increment Seconds
' -----------------
' Kinda overkill to include setting seconds,
' but if you got codespace to burn...
If CounterC=3 then
If _Sec=>59 then
_Sec=0
else
_Sec=_Sec+1
endif
endif

gosub Pauseloop
TimeOut=0
Goto SetupDisplayLoop
endif
'
' Set Button Pressed
' ------------------
If setbutton =0 then
CounterC=CounterC+1 ' Increment Menu Item
TimeOut=0
endif
If CounterC>3 then 'old menu counterC>6#########################
' Save Data if all edit items exhaused
'
' Save 12/24 Hours to BCD DS1307's Format
' ---------------------------------------
CounterA=_hr
If SetTime=1 then
If CounterA>12 then CounterA=CounterA-12
If CounterA=0 then CounterA=12
endif
Gosub ConvertBCD
hr=CounterB
' Save the Hours Value
If SetTime=1 then
hr.6=1
' Save the 12 Hour Mode Flag
If _hr=>12 then hr.5=1
' Save the 'PM' Flag
endif
'
' Save Minutes
' ------------
CounterA=_min
Gosub ConvertBCD
MINs=CounterB
'
' Save Seconds
' ------------
CounterA=_sec
Gosub ConvertBCD
sec=CounterB

'
' Do the Business
' ---------------
rtcwrite:
I2CWrite DS_SDA, DS_SCL,$D0,$00,[sec,MINs,hr,RTCWDay,day,mon,yr,RTCCtrl]
Gosub SetButtonRelease
Goto ReDisplay
endif
Gosub SetButtonRelease
Goto SetupLoop ' Loop for Next Menu Item
'
' Menu TimeOut Counter
' --------------------
gosub Segmentswrite2
TimeOut=TimeOut+1 'not jet working good
If TimeOut>20000 then goto ReDisplay
' User paused too long
' Return User to Time & Date Display
' This will however bounce the User to the original
' Setup Menu start point if the DS1307 has not
' been initialised
Goto SetupEntryLoop ' Loop for Button Press

Pauseloop: 'some timedelay
counter3=0
repeat
pauseus 10
until counter3 > 50
return

'just a routine to make sure you didn't push the button by faulth
'------------------------------------
SetButtonRelease: 'delay for button
counter3=0
while setbutton=0
pauseus 10
Wend
if counter3=>29 then
repeat
pauseus 10
until counter3 > 70
else
goto loop
endif
Return

FindDays: 'deleted
Return
DisplayMonth:'deleted

DisplaySequence: 'deleted
Return

'
' Subroutine Converts back to BCD
' -------------------------------
' CounterA is the entry variable
' CounterB holds the converted BCD result on exit
ConvertBCD:
CounterB=CounterA DIG 1
CounterB=CounterB<<4
CounterB=CounterB+CounterA DIG 0
Return

Redisplay: 'deleted
return

Am_or_Pm: 'deleted
return

coldstart: 'only started when rtc starts from cold
'--xx--
_yr=0:_date =0:_mon =0:_day=0:_hr=0:_min=0:_sec=0

' The constants below set the RTC to: 16:30:00 on 13-07-2003
_yr=$03
_mon=$07
_date=$13
_hr=$16
_sec=$00
_min=$30
I2CWrite DS_SDA, DS_SCL, $D0,$00,[_sec,_min,_hr,_day,_date,_mon,_yr,cntrl]
Return

mister_e
- 28th December 2007, 22:47
:eek: i see you use some GOSUBs & Return in your ISR... not a good idea to me...

Observe the way your program will flow, assuming there's no problem with the use of Gosub and Return (erm), your program will execute all lines.. and finally jump to...


counter = %11111111 'to take care that no segment is blinking harder
todec = %00000000'todec >> 4
gosub segmentsshiftout

segmentsshiftout:
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1
return

it's kinda dangerous here... once it have execute once the segmentsshiftout sub, it will execute it once again and meet a RETURN without a GOSUB... where the program branch now??? i guess at the begining of your ISR... or.. mmm... resume to your main loop, but as you NEVER EVER clear the interrupt flag, it will automatically jump back to your ISR.

try to add a GOTO after your last GOSUB segmentsshiftout, which will send it at the end of your ISR...

counter = %11111111 'to take care that no segment is blinking harder
todec = %00000000'todec >> 4
gosub segmentsshiftout

GOTO RESUME_ISR ' <-- Add this

segmentsshiftout:
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1
return
'
'
'
'
'
RESUME_ISR: ' <-- And this
TMR2 = RELOAD
TMR2ON = 1
TMR2if=0 ' Clear interrupt flag

resume
enable

ADCON
- 29th December 2007, 13:39
thanks,

here s my progress for now:
First I added the lines you gave me. unfortunatly it didn't work.
I put somethings at a more logical place(tmr2if=0 at the top of isr)
Then I replaced all the gosubs by the real text. it cost me for aboud 500 words more but luckily there was enough space at the 628 (i haven't a 648 at stock).
Then I began thinking aboud the stackadresses. But that was not the option because there was not a gosub at the loop so the only things at the stack had to be the adress for the return after the interrupt and max 1 gosub adress from inside the ISR.

When I looked at the helpfile I got an idea. It is also possible to place a label after the resume command. I added loop after the resume command and it works for now.

>>The only problem now is that after the 'resume loop' command I have just 2msec to change my settings:P That is not possible but maby you get now an adea for what I'm doing wrong.

So, I tried that at the prevous version of the program. This works the same, so with the gosubs inside the ISR.

Here is my code for now: under the loop didn't I change anything so that is not posted.



@ device pic16F628a, INTRC_OSC_NOCLKOUT
@ device pic16F628a, MCLR_ON
@ device pic16F628a, LVP_OFF
@ device pic16F628a, WDT_OFF
@ device pic16F628a, PWRT_ON
@ device pic16F628a, BOD_OFF'ON
INCLUDE "modedefs.bas" 'for shiftout
pause 50

' Defines
' ----------------
'I2C pins
DS_SCL VAR PORTA.0 ' I2C clock pin
DS_SDA VAR PORTA.1 ' I2C data pin
'RTC CON %11010000 ' RTC device address (byte addressing) not needed

'Setting the RTC so we can get out 1Hz tick output
'-------------------------------------------------
' -------------- RTC definitions -----------------
SecReg CON $00 ' seconds address (00 - 59)
' MSB of SecReg must be set to a 0 to enable RTC
MinReg CON $01 ' minutes address (00 - 59)
HourReg CON $02 ' hours address (01 - 12) or (00 - 23)
DayReg CON $03 ' day address (1 - 7)
DateReg CON $04 ' date address (01 - 28/29, 30, 31)
MonthReg CON $05 ' month address (01 - 12)
YearReg CON $06 ' year address (00 - 99)
ContReg CON $07 ' control register
RTCflag CON 0 ' RTC flag (location 0 of internal EEPROM)
cntrl CON %00010000 ' sets the SQW/OUT to 1Hz pulse, logic level low

' The variable below holds the values entered:
'menu var's
_sec VAR BYTE ' $00 set seconds
_min VAR BYTE ' $56 set minutes
_hr VAR BYTE ' $23 set hour
_day VAR BYTE ' $06 set day
_date VAR BYTE ' $28 set date
_mon VAR BYTE ' $02 set month
_yr VAR BYTE ' $03 set year

'rtc var's
sec VAR BYTE ' seconds
MINs VAR BYTE ' minutes
hr VAR BYTE ' hours
day VAR BYTE ' day
date VAR BYTE ' date
mon VAR BYTE ' month
yr VAR BYTE ' year

'button input
'-------------------
SetButton var PORTa.7 ' Press to Set/memorise Button
DecButton var PORTa.3 ' Press to Decrement Button
IncButton var PORTa.2 ' Press to Increment Button

'other var's
'------------------
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
CounterC var byte ' General purpose Variable
CounterD var byte ' General purpose Variable
ButtonRepeat con 200 ' Timeperiod (in mS for Edit Buttons auto-repeat
' should you want to hold them down...
RTCCtrl var byte ' Control
TimeOut var word ' Variable for SetUp Menu Time-Out
SetTime var byte ' 12/24 Hour Clock
RTCWDay var byte ' Weekday
timeformat var word ' place for displaying am/pm
counter var byte
counter2 var byte
counter3 var word ' delaycounter
counter4 var word ' counter at redisplayloop
segments var byte
myBCD var byte
toDEC var byte

'I/O pins
'port conditions
'---------------
CMCON=7
TRISA=0
TRISB=0
PORTA=0
PORTB=0

'timer and interruptconditions
'----------------
PIE1 = %00000010
'0------- Disable EE write complete interrupt
'-0------ Disable comparator interrupt
'--0----- Disable USART receive interrupt
'---0---- Disable USART transmit interrupt
'----x--- unimplemented
'-----0-- Disable CCP1 interrupt
'------1- Enable TMR2 to PR2 match interrupt
'-------0 Disable TMR1 overflow interrupt

T2CON = %00000010
'X------- Unimplemented
'-0000--- postscale 1:1
'-----0-- Timer2 off
'------10 prescaler 1:16

GIE VAR INTCON.7
PEIE VAR INTCON.6
TMR2IF VAR PIR1.1
TMR2ON VAR T2CON.2
RELOAD CON 131

ON INTERRUPT GOTO ISR
TMR2 = RELOAD
PR2 = 0 ' load period register for 2mSec
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR: 'interruptroutine
TMR2if=0 ' Clear interrupt flag
TMR2ON=0
'counter3 to reduce later the isr text. then only shiftout the var's
if counter3=>200 then 'number of shiftouts
counter3=0
else
counter3=counter3+1
endif

'hours
'the one that is 0 wil blink
'for segments the opposite
counter = %01111111 '1 segment
toDEC = hr
if hr.6=1 then '12 uurs mode
todec = todec <<3
todec = todec >>7
else '24 uurs mode
todec = todec <<2
todec = todec >>6
endif
gosub findsegments
if hr.6 = 1 then 'add in the am/pm indication
if hr.5 = 1 then
segments.7 = %1
endif
endif
gosub segmentsshiftout

counter = %10111111 '2 segment
toDEC = hr
toDEC = toDEC << 4 'shiftout unusable data
todec = todec >> 4 'shiftback usable data
gosub findsegments
if portA.6 = 1 then segments.7 = %1 'add the blinkin dot
gosub segmentsshiftout

'minits
counter = %11011111 '3 segment
toDEC = MINs
todec = todec >> 4 'shiftback usable
gosub findsegments
gosub segmentsshiftout

counter = %11101111 '4 segment
toDEC = MINs
todec = todec << 4 'shiftout unusable data
todec = todec >> 4
gosub findsegments
gosub segmentsshiftout

'seconds
counter = %11110111 '5 segment
toDEC = sec
todec = todec >> 4 'shiftback usable
gosub findsegments
gosub segmentsshiftout

counter = %11111011 '6 segment
toDEC = sec
todec = todec << 4 'shiftout unusable data
todec = todec >> 4
gosub findsegments

if hr.6=1 then 'mode indication
segments.7=%1
endif
gosub segmentsshiftout

counter = %11111111 'to take care that no segment is blinking harder
todec = %00000000'todec >> 4
gosub segmentsshiftout
GOTO RESUME_ISR ' <-- Add this

segmentsshiftout:
SHIFTOUT PORTB.0, PORTB.1, LSBFIRST,[counter\8,segments\8] 'data, clock
pulsout PORTA.4,1
return

findsegments:
if todec=%00000000 then '0
segments = %01111110
endif
if todec=%00000001 then '1
segments = %00110000
endif
if todec=%00000010 then '2
segments = %01101101
endif
if todec=%00000011 then '3
segments = %01111001
endif
if todec=%00000100 then '4
segments = %00110011
endif
if todec=%00000101 then '5
segments = %01011011
endif
if todec=%00000110 then '6
segments = %01011111
endif
if todec=%00000111 then '7
segments = %01110000
endif
if todec=%00001000 then '8
segments = %01111111
endif
if todec=%00001001 then '9
segments = %01111011
endif
return
RESUME_ISR: ' <-- And this
TMR2ON=1
TMR2 = RELOAD
resume loop
enable

LOOP:
I2CRead DS_SDA,DS_SCL,$D0,$00, [sec,MINs,hr,day,date,mon,yr] ' Read Ds1307
If sec.7=1 then goto coldstart
If setbutton = 0 then 'if setbutton is pressed
_hr=hr
_min=MINs
_sec=sec
gosub SetButtonRelease
Gosub SetTimeAndDate 'after release
endif
counter3=0
repeat 'show the segments for 5 times.
pauseus 10
until counter3 > 5
GoTo Loop
end

mister_e
- 29th December 2007, 21:09
Well, believe it or not, and if MPLAB StopWatch don't lie, your ISR need 4.6 mSec to execute... and usually you want to reload the timer before re-starting it.

Do you have any schematic of your thing and a brief description of what you want to do?

ADCON
- 30th December 2007, 10:57
Thanks, I didn't know how long the ISR really was.
Now we know this, there are a couple of possible solutions..
make the timer longer to 6 or 8 mSec, restart and reload the timer after the ISR or make the ISR less long.

I tried to restart the timer after the ISR(above post) but that didn't work.. Suprisingly did it work somehow when the end of the ISR was 'resume loop'. Then was the program able to make a I2C-read from the RTC and update the var's.

So, the first possible solution is to make longer the timer to let's say 8mSec and afther that reduce the length of the ISR and posible to set the timer back to 2mS.

The ISR is doing a lot of work every time and that is not necessary do execute every time. The lookup for segments is not deeded everytime but can be executed in the program somewhere else and 1 in the 10 times of shiftout is also very acurate(I'm not placing it in a nucear powerplant... ;) ) So the only thing left for the ISR to do is shiftout the segmentsdata.

I had problems with var's I did change at the mainloop. He didn't update them by the shiftout.

So, when I place this T2CON = %00000010 is the presale to 1:16 and is the timer about 8mSec, right? Then it have to work anyway?

about the schematic: a ds1307 is connected to A0 & A1. the two 74HC595 are placed at B0 & B1. The pushbuttons for the menu are at port A2, A3 & A7. All including external pullups. For the 7segmentsdisplays are resistors added. The 7segmentsdisplays are Common Cathode and connected with a BC557C to the GND. The PIC16f628 is working at it's internal oscillator. And a smal capacitor of 0,1uF added from V+ to GND near the IC's. So, it's all very basic and there isn't more to tell about the schematic.

Can you also measure how long it takes for a I2C-read and write? Because, when I delete it from the mainloop the ISR can use other var's from the loop...

mister_e
- 30th December 2007, 18:48
To measure how long a single code line or chunk of code need toexecute, you have several method
1: Scope method
you Set/Clear an I/O before and after a code chunk, then you measure it with a scope

2: MPLAB StopWatch
You set a breakpoint at the end of the code chunk you want to measure, You set the PC at the start of the code chunk, then you click on Run at PC (refer to MPLAB help file)

3: use a PIC timer
Same concept as StopWatch but you need to send the results to a LCD or via serial communication. The following link explain it better

instruction execution time
http://www.picbasic.co.uk/forum/showthread.php?t=365

i'll try to figure out what the heck happen here... would be nice if i had those shift register :eek:

ADCON
- 30th December 2007, 20:02
thanks, I use microcodestudio but this is a reason to look for MPlab.
Microcodestudio sadly don't have a timerfunction. A time ago did I look for MPlab but it looked a lot harder to work with to me.

The shiftregisters works simple. It is data+clock and when all data is loaded a puls so the latches reset to the new value.
Maby you do have Proteus VSM? I mean that they have also this registers(haven't a lisence myself). The datasheet is here: http://www.alldatasheet.com/datasheet-pdf/pdf/23121/STMICROELECTRONICS/74HC595.html

The RTC I used is a DS1307 from Maxim-ic.com but that works fine..

mister_e
- 30th December 2007, 20:22
Proteus :eek: VSM :eek: any sim :eek: E+457810214

sorry not for me.

Yeah i know those shift register and i know what a shift register is, what i meant is that it would be great if i had them in stock to build the circuit and test it in a real environment.

I'm not a Sim fan... i know a few people using it for all their design and they seems to be more than happy with it.

ADCON
- 30th December 2007, 21:02
Yes, sim programs are expensive. I had a free beta-testversion once, it had still to much bugs to work with, after that came the pay-version.. I also like to life-test :) also my bankaccount.. it only takes sometimes some more time. But the good side is that when it workt it really works and with sim-programs is that always a question..

Well, Possibli can you tell me the length of a I2Cread/write procedure because I think that it is also to long. When I start the timer after the ISR it will only read the RTC, it never finishes the coldstart.

I did try to set the prescale to 1:16 but it hadn't any good progress. How do I become a timerinterrupt every 8mSec? of 16msec? Maby I can thy that so it works..

mister_e
- 30th December 2007, 21:23
Well the prescaler was already 1:16 at the first post.. hence why you didn't had any better results ;)
Now what you need to do is to use the POSTscaller. if you set the postscaller to 1:2 you'll have a 2mSec*Prescaller int. 8mSec, postscaller 1:4 and so on


T2CON = %00011010
'X------- Unimplemented
'-0011--- postscale 1:4
'-----0-- Timer2 off
'------10 prescaler 1:16

seems to work with the second suggestion


// Snip
ON INTERRUPT GOTO ISR
PR2 = 124 ' load period register for 2mSec
PEIE = 1 ' Enable peripheral interupt
GIE = 1 ' enable Global interrupt
TMR2ON = 1 ' TMR2 ON
GOTO LOOP

disable
ISR:
TOGGLE PORTB.0
TMR2IF = 0 ' Clear interrupt flag
resume
enable
// end snip

ADCON
- 30th December 2007, 21:51
thanks, i just found it myself.

4000000/4/256/16/2=122
osc/4/8bit/precaler/postprescaler=period
1/122=0,008S

4000000/4/256/16/4=61
1/61=0,016S

now try at the code..

mister_e
- 30th December 2007, 21:56
or... easier way... PICMultiCalc, Timer Helper.
http://www.mister-e.org/pages/utilitiespag.html

255-Value listed in the list, and you're in business

Raise your hand those using it.. at least for timer!!!

OK Darrel ;) http://photos.photosig.com/photos/02/94/1739402-thumb.jpg

ADCON
- 30th December 2007, 22:52
Well, I can use the timer now.
I even added a postscale of 1:16 and a prescale of 1:16 so it's interrupt-frequency was about 15Hz. The segments were blinkin visibly. Even then, when I changed 'resume loop' to 'resume' I had no changing data to my display. Only the var's he already had.

So, somehow there is something wrong with the resume command. And I really don't know what it is...

mister_e
- 30th December 2007, 23:12
Nah there's no issue with RESUME... i'm trying to analyze the whole program here. yeah i TRY.

Try something... comment out the whole none-ISR code, assign a value to the var used in your ISR, and see if there's any problem. You main loop could be anything like a LED blink. Careful with your delays... you're using ON INTERRUPT...

EDIT:
http://www.mister-e.org/Pics/woohoo found 2 X 74HC595 on a really old board here, need to test them first...

mister_e
- 31st December 2007, 00:07
EDIT2: Thought i saw that before... http://www.mister-e.org/Pics/pan

One thing i discover in your code...


LOOP:
I2CRead DS_SDA,DS_SCL,$D0,$00, [sec,MINs,hr,day,date,mon,yr] ' Read Ds1307
If sec.7=1 then goto coldstart
If setbutton = 0 then 'if setbutton is pressed
_hr=hr
_min=MINs
_sec=sec
gosub SetButtonRelease
Gosub SetTimeAndDate 'after release
endif
counter3=0
repeat 'show the segments for 5 times.
pauseus 10
until counter3 > 5
GoTo Loop

You don't increment Counter3 variable.. so it will never jump to Loop... hence maybe why it works when you're using RESUME LOOP...

Same thing in PauseLoop


Pauseloop: 'some timedelay
counter3=0
repeat
pauseus 10
until counter3 > 50
return

and


'------------------------------------
SetButtonRelease: 'delay for button
counter3=0
while setbutton=0
pauseus 10
Wend
if counter3=>29 then
repeat
pauseus 10
until counter3 > 70
else
goto loop
endif
Return

I'll wait before building it http://www.mister-e.org/Pics/error00

ADCON
- 31st December 2007, 10:07
hi, the counter3 has not to be the problem. It is incremended everytime it go's to the ISR. If you look at the top of the ISR you see:


if counter3=>200 then 'number of shiftouts
counter3=0
else
counter3=counter3+1
endif


So it stays in stat loop until the ISR is called for 'counter3' time's.
So it's a kind of delayloop.

Is there an other wat to go to the ISR at the timerinterrupt then ON INTERRUPT?

I go to try comment the code to a minimize is left and use 'return' at th end of the ISR.

To make clear that there are no mistakes: I tried to make the program work in loops and every time the timerinterrupt sets it's flag jumps it to the ISR to shiftout the displayvalues, afther that it go's back to twere it was en finish the loop so it can start again waiting for a buttonpress.

I'm sorry, I thing it will be tomorrow that this is finished. It's buzy over here...:(

ADCON
- 1st January 2008, 14:16
i changed my code now.
the var counter works fine.



LOOP:


Sec=12
Mins=34
hr=56

if counter3=>100 then
blink=1
else
blink=0
endif
goto loop
end

This is with only the return-command.

I'm going to change the loop now. I try to set more gosubs in it, maby it works..

It looks like there is a problem between the I2C and interrupt. Do's I2C also use timer2 for it's clocksignal or something?
edit:
I found a mistake:
@ loop:
goto coldstart

@ coldstart
return

:(

not all the problems are solved now, but at least return at the end of the ISR dos have any effect!

edit2:
after changing the tris settings to
TRISA=%11111111
TRISB=%11111111
I can make some input with the buttons. The problem now is that it's menu is not working right.
It looks like it just runs the routine for once and not wait for any other input.(possible a mistake when I did change it from only loops to interrrupt I might have did something wrong..). I have to look at that for now..

mister_e
- 1st January 2008, 19:07
None of I2C function use the internal timer, but they need time to execute. I should be able to build the board today.

Out of curiosity... did you also tried to test it with ISIS?

ADCON
- 1st January 2008, 22:48
I have no licence of ISIS. If I had I would be happy :)
Well, I have now the clock working(it means running the way it has to do) and it looks like the settings of the menu is now a software-thing what I have to debug and modificate. My old version did work but to make it timerinterrupt I had to change the code. So, I think I have make some mistakes at that part of the job. It looks like it runs the menu for one time and don't wait for inputs.
For this part thanks for all your help!

It is a option to use also a interrupt for the inputbuttons...

ADCON
- 2nd January 2008, 18:49
Well, its working :D finally!

The only thing is that the display dos not change when a button is pushed-in. so, when you hold your hand on a button so it will count crom 1,2,3,4 and release it by five, you see the 1 untill you release the button.
I have to finish that part..