PDA

View Full Version : DS1307 and a LED array, need ideas



peu
- 26th December 2009, 14:59
Hi, I want to do two things at once, and I don't know how :)

Let me explain, I want to update a led matrix (12x12) this needs to be done real fast so the eye, due to persistance of vision , thinks all the leds are on at the same time, but also I want to poll a DS1307 RTC to keep time.

So, how do I do both things at the same time? I mean if I pause between reads the led display does not show, and if I read the clock in the led matrix refresh loop I choke the DS1307 with too many requests.

Speed is no problem because Im going to use a 18F4550 or one of its relatives (depending on the amount of data I will need to store)

I think the solution is around interrupts, but I never programmed with interrupts, so Im kinda lost here... Im not asking for code (it wont hurt to read some thou) just some pointers so I can figure it out what to do with some datasheet reading.

thanks

mackrackit
- 27th December 2009, 02:05
How long does it take for the display loop?
How are you driving the display? Direct or shifting out through a driver chip?

When you say real fast... keep in mind that for most folks the blink goes away at around 30 Hz. Should leave plenty of time someplace.

How often do you want to read the RTC?

jellis00
- 27th December 2009, 02:19
... Im not asking for code (it wont hurt to read some thou) ....


You're on the right track to consider an interrupt. Search this forum for how to use Darrel Taylor's Base Interrupt System...you need to download his DT_INTS-18.bas and ReEnterPBP-18.bas files and make them INCLUDEs in your code. Am currently working on an application that uses this approach for an 18F4550, but with a DS1337 real-time-clock rather than the DS1307. DS1307 is almost identical to DS1337 except for 2 pins and the register addressing...suggest you get the data sheets for both and compare and you should be able to quickly see how to modify this example code to make it work with DS1307.

Here is the setup from the example code. If you are interested in all the code I can email it to you...too long for this posting. Ask questions and I will try to help you. This forum has been very good to me so I welcome the opportunity to do some payback.



' [ Program Description ]
' This Program is for a PIC18F4550 & was tested in an EasyPic6 board. *
' Purpose: *
' 1) Monitors 1/min interrupt from external Real Time Clock *

' [ Device Declaration

; if you un-comment these, you must comment the ones in the .inc file--
ASM ; 18F2550/4550, 8mhz crystal
__CONFIG _CONFIG1L, _PLLDIV_2_1L & _CPUDIV_OSC4_PLL6_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H ; PortB resets as digital
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

Include "Modedefs.Bas"
INCLUDE "DT_INTS-18.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP high priority interrupts
INCLUDE "ALLDIGITAL.pbp" ' Sets all registers for digital ops.

DEFINE OSC 16

' Initialize Hardware
' =============
'Set registers
TRISA = 0 ' PORTA all outputs
TRISB =%00001100 ' RB2 & RB3 set as RTC Alarm1 & Alarm2 inputs
TRISC = 0
TRISD = 0
TRISE = 0

' Variables & Aliases for Pins other than RTC use
' ==================================
b0 VAR Byte ' LSB of range measurement when right justified
b1 VAR Byte ' MSB of range measurement when right justified

'SETUP FOR USING DS1337 Real Time Clock
' Setup Hardware for uart
' ==================
DEFINE HSER_BAUD 115200
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_CLROERR 1

' * NOTES for use with EasyPic6 development board:
'For interface to DS1337 RTC:
' - To provide battery backup place a Shottky diode between + battery
' terminal and Vcc (pin-8) of the DS1337.
' - I2C communication lines should be connected to 4.7K pull-up resistors.
' - INTA & INTB lines should be connected to pull-up resistsors.
' - Turn off LEDs connected to I2C communication lines.

' Aliased Variables for CLock
' ====================
Alarm1 VAR PORTB.2 ' Alarm1 input from DS1337 INTA (pin-3)
Alarm2 VAR PORTB.3 ' Alarm2 input from DS1337 INTB (pin-7)
SCL VAR PORTB.1 ' I2C clock pin
SDA VAR PORTB.0 ' I2C data pin
RTCdevice CON %11010000 ' RTC device write address(byte addressing)
' A list of possible clock contrl settings, one which must be
' setup in the SetTimeAndDate subroutine.
'contrl CON %00000101 ' Starts oscillator, enables INTA interrupt
' from A1F, INTA/SQW off.
'contrl CON %00000110 ' Starts oscillator, enables INTB interrupt
' from A2F. WORKS OK!

' RTC Address 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)
HrReg 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)
MonReg CON $05 ' month address (01 - 12)
YearReg CON $06 ' year address (00 - 99)

' Alarm 1 Address definitions
' ====================
Alm1sec CON $07 ' Alarm 1 seconds address (00 - 59)
Alm1min CON $08 ' Alarm 1 minutes address (00 - 59)
Alm1hr CON $09 ' Alarm 1 hours address (01 - 12) or (00 - 23)
Alm1Day CON $0A ' Alarm 1 day address (1 - 7)

' Alarm 2 Address definitions
' ====================
Alm2min CON $0B ' Alarm 2 minutes address (00 - 59)
Alm2hr CON $0C ' Alarm 2 hours address (01 - 12) or (00 - 23)
Alm2Day CON $0D ' Alarm 2 day address (1 - 7)

' Alias of Clock register addresses
' ========================
ContReg CON $0E ' CONTROL register address
StatusReg CON $0F ' STATUS register address

' Clock Variables
' ===========
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

' ALARM1 VARIABLES
' ==============
A1sec VAR BYTE ' seconds
A1MINs VAR BYTE ' minutes
A1hr VAR BYTE ' hours
A1day VAR BYTE ' day

' ALARM2 VARIABLES
' ==============
A2MINs VAR BYTE ' minutes
A2hr VAR BYTE ' hours
A2day VAR BYTE ' day

GoSub SetTimeAndDate ' Setup current time & alarm settings

'SETUP FOR INTERRUPTS
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
;INT_Handler USB_Handler
INT_Handler INT2_INT, _Alarm, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE INT2_INT ; enable external (INT) interrupts

INTCON.7 = 1 ' Set Global Interrupt Enable bit
INTCON2 = %00000000 ' Set INT2 for falling edge (Bit4-low)
' on RTC's interrupt.
INTCON3 = %10010000 ' Set INT2 high priority (Bit7-high), enable INT2
' (Bit4-high)
RTC_INT_FLG VAR INTCON3.1 'Alias for RB2 INTA interrupt flag from RTC

'[ Begin Main Program Loop ]

Main:
GoTo Main ' Endless Loop waiting for interrupt
End ' Safety measure to insure program stops if reaches here

'[ Begin Interrupt Handler
Alarm:
'Put your interrupt service routine code here
' Process the RTC alarm
' Read the current time and ALARM settings from the DS1337
I2CRead SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
Pause 1000

' Clear the Alarm flags to be ready for next intterupt
' Clear STATUS register
I2CWrite SDA, SCL, RTCdevice, StatusReg,[$00]
Pause 1000
WRITE 255, sec
PAUSE 20
RTC_INT_FLG = 0 ' Clear PIC interrupt flag for next Alarm
PAUSE 1000
' Resume Main Program
@ INT_RETURN
End ' Safety measure to insure program stops if reaches here
'{ End of Interrupt Handler }

' [ START LIST OF SUBROUTINES

SetTimeAndDate: ' Subroutine to set current time, date and alarms
'==============
' Initialize clock variables to 0
yr=0:date =0:mon =0:day=0:hr=0:MINs=0:sec=0
A1sec=0:A1MINs=0:A1hr=0:A1Day=0
A2MINs=0:A2hr=0:A2day=0
' The BCD constants below set the RTC to: 11:00:00 on 12-20-2009
hr=$11
MINs=$00
sec=$00
day=$07
mon=$12
date=$20
yr=$09
' Per MAXIM TechSupport, proper sequencing requires setting INTCN = 1,
' & A2IE=A1IE=0 before setting alarms.
I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000100]
Pause 20
'Define ALARM1 FOR 11:01:00 & to alarm when secs match (1/min).
' This requires A1M1=0 and A1M2=A1M3=A1M4=1
' (A1xxx + $80 or A1xxx + 128d sets bit 7 as A1Mx = 1)
A1hr = %10010001 '$11 + $80 = %10010001, for A1M3 = 1
'Bit6 must be 0 for 24 hour clock
A1MINs = %10000001 '$501 + $80 = %10000001, for A1M2 = 1
A1sec = $00 '$00 = %00000000, for A1M1 = 0
A1day = %10000111 '$07 + $80 = $10000111, for A1M4 = 1
'DY/_DT Bit6 = 0 for using Day of month alarm
' Per MAXIM TechSupport, reset control register for desired Alarm
' after setting alarms.
I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
PAUSE 20
'Set the main Time
I2CWrite SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
Pause 20
'Set the Alarm1 Time
I2CWrite SDA, SCL, RTCdevice, Alm1sec,[A1sec,A1MINs,A1hr,A1day]
PAUSE 20
' Clear STATUS and set CONTROL registers
I2CWrite SDA, SCL, RTCdevice, StatusReg,[$00] ' Clear STATUS register
PAUSE 20
I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
' Starts the oscillator,
' enables INTA interrupt from A1F.
' WORKS as intended!!
Pause 20
Return
' If the user program ends by getting to the last statement of the
' program at an END instruction, the MCU will SLEEP and await a wakeup.
END

peu
- 27th December 2009, 14:06
a 12x12 led matrix sequenced row by row needs to be turned on at least 70 times per second, so the loop needs to run 70 times 12 per second, that translates to 1.2ms per row, if I read the DS1307 at this speed Im sure I'll choke it.

jellis, thanks for the offer, my email is pablou at gmail

I'll recheck Darrel interrupts, no matter what I do I always peek at his work... :)


thanks guys!

jellis00
- 28th December 2009, 04:55
that translates to 1.2ms per row, if I read the DS1307 at this speed Im sure I'll choke it.


Yes, you are probably correct that in your case using interrupts from the DS1307 isn't the way to go. It takes a 10 millisec PAUSE after each I2CREAD statement to read the clock time from the DS1307, so it would be too slow for your requirement.

DT's Instant interrupts are still worth studying and using though in any of your applications as opposed to any of the PBPro interrupt approaches. I highly recommend them. Go here to download the files and to learn how to use them: http://darreltaylor.com/DT_INTS-18/home.html

Melanie
- 28th December 2009, 09:28
It takes a 10 millisec PAUSE after each I2CREAD statement to read the clock time from the DS1307, so it would be too slow for your requirement.

Not correct. Some I2C devices require a PAUSE after a WRITE statement, but READs are performed usually at max speed. The DS1307 certainly does NOT require any pauses for READing.

There are many ways of accomplishing this without going into interrupts. Here's two...

Software route: At the end of every row scan simply bump a BYTE Counter. When the Counter rotates through Zero (just over three times a second if you are scanning rows every 1.2ms), then do your I2CREAD of the DS1307. You'll be updating your time about three times a second.

Hardware Assisted Route: The DS1307 has a pin which can give you a pulse every Second. Several pins on PortB have the facility to set a FLAG in a Register when the state of the pin changes. Simply check the Flag at the end of a scan and do a DS1307 READ when the Flag pops up.

spcw1234
- 28th December 2009, 17:46
Hardware Assisted Route: The DS1307 has a pin which can give you a pulse every Second. Several pins on PortB have the facility to set a FLAG in a Register when the state of the pin changes. Simply check the Flag at the end of a scan and do a DS1307 READ when the Flag pops up.

I like this! :) I have not used the DS1307 yet, and usually I would increment a counter like your other suggestion, but I will keep this in mind in the future. Thanks, Melanie.

Melanie
- 28th December 2009, 21:06
Actually, just between you, me and the rest of the forum, I hate the DS1307. It's overpriced for what it is (even when bought in large quantities), and has worse timekeeping than your average 99 cent Chinese Digital Watch (even when you perfectly match the specified 12.5pF crystal with it).

To be honest, what I'm doing nowadays is designing-out the DS1307, chosing a micropower PIC, running it from two supplies (+5v for normal operation and +3v Battery back-up) and using a background Interrupt Routine that runs 24/7. The accuracy (for Data-Logging) is no worse than a DS1307 and you save yourself a dollars worth of chip, plus crystal, plus PCB real-estate!

peu
- 29th December 2009, 00:36
Thanks for your replies Melanie, one question, do you know how long it takes (in milliseconds) for the DS1307 to be read into a picbasic variable?


Not correct. Some I2C devices require a PAUSE after a WRITE statement, but READs are performed usually at max speed. The DS1307 certainly does NOT require any pauses for READing.

There are many ways of accomplishing this without going into interrupts. Here's two...

Software route: At the end of every row scan simply bump a BYTE Counter. When the Counter rotates through Zero (just over three times a second if you are scanning rows every 1.2ms), then do your I2CREAD of the DS1307. You'll be updating your time about three times a second.

Hardware Assisted Route: The DS1307 has a pin which can give you a pulse every Second. Several pins on PortB have the facility to set a FLAG in a Register when the state of the pin changes. Simply check the Flag at the end of a scan and do a DS1307 READ when the Flag pops up.

peu
- 29th December 2009, 02:52
Thanks for your replies Melanie, one question, do you know how long it takes (in milliseconds) for the DS1307 to be read into a picbasic variable?

how impolite on my part, I wanted to say thanks to ALL who replied :)

Melanie
- 29th December 2009, 07:53
Ohhh... that's not an easy question to answer without actually timing it on a scope... it will depend on the number of bytes you're reading at a time, etc etc.

But as a guesstimate, reading back say 8 bytes in one block (sequentially grab Registers 00-07), you might need as many as 150 bits at 100kHz... so I guess it could be as short as 1.5mS, and under 1mS if you're just grabbing the first three Resisters for the TIME only.

Ioannis
- 29th December 2009, 10:57
To be honest, what I'm doing nowadays is designing-out the DS1307, chosing a micropower PIC, running it from two supplies (+5v for normal operation and +3v Battery back-up) and using a background Interrupt Routine that runs 24/7. The accuracy (for Data-Logging) is no worse than a DS1307 and you save yourself a dollars worth of chip, plus crystal, plus PCB real-estate!

And if you trim the Xtal with a trimmer it is going to be even more accurate.

Also somewhere in this forum there was a thread for canceling out the clock error but cannot find it.

Ioannis

wellyboot
- 30th December 2009, 18:45
Are you scrolling the time on your display?

http://www.youtube.com/watch?v=nVRr-swB39I

This project i built a few months ago, uses a 8x7 led matrix & DS1307 RTC

It reads the DS1307 at the end of the scroll cycle when the display is blank.