ACA ESTÁ EL PROGRAMA HECHO POR MELANIE NEWMAN (1a PARTE)
' Project MN1307
' ==============
' Embedded Software Version 1.00
' Target Processor PIC16F628-04/SP
' Target PCB - BB-01
' Created 12/06/02
' Last Updated 12/06/02
' Written by Melanie Newman
'
' DS1307 RTC Program
' Includes Setting the Date and Time
' 3 Buttons Control Setting...
' 12/24 hour Clock Mode
' Year
' Month
' Day of Month (also accounting for Leap Years)
' Hour
' Minute
' Second
'
' Written for 2 line 16 Character LCD
'
' This program is designed to "hold your hand" and prevent you
' from setting any invalid data combinations into the DS1307
'
' It's a crude program, but demonstrates how to set the clock
' with control buttons
'
' You will be automatically returned to the Time & Date display if
' you are in the Setup and don't touch any Buttons for 20 seconds
'
'
' Device Programming Options
' --------------------------
@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT
' System Clock Options
@ DEVICE pic16F628, WDT_ON
' Watchdog Timer
@ DEVICE pic16F628, PWRT_ON
' Power-On Timer
@ DEVICE pic16F628, BOD_ON
' Brown-Out Detect
@ DEVICE pic16F628, MCLR_OFF
' Master Clear Options (Internal)
@ DEVICE pic16F628, LVP_OFF
' Low-Voltage Programming
@ DEVICE pic16F628, CPD_OFF
' Data Memory Code Protect
@ DEVICE pic16F628, PROTECT_OFF
' Program Code Protection
'
' Hardware Assignments
' --------------------
'
' System LCD
' ----------
' No Resistors required on any line
' RA0-RA3 Data bits DB0-DB3
' RA6 RS-bit
' RA7 E-Bit
'
Define LCD_DREG PORTA ' Port for LCD Data
Define LCD_DBIT 0 ' Use lower 4 bits of Port
Define LCD_RSREG PORTA ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 6 ' Port Pin for RS bit
Define LCD_EREG PORTA ' Port for Enable (E) bit
Define LCD_EBIT 7 ' Port Pin for E bit
Define LCB_BITS 4 ' Using 4-bit bus
Define LCD_LINES 2 ' Using 2 line Display
Define LCD_COMMANDUS 2000
' Command Delay (uS)
Define LCD_DATAUS 50 ' Data Delay (uS)
'
' DS1307 Connections
' ------------------
' 10K Resistors required from PORTB.1 and PORTB.2 to Vdd
' PORTB.0 relies on weak pull-up's (for future use)
'
SQWpin var PORTB.0
' You don't actually need to wire this pin... but...
' If you're observant, you'll notice I've wired the DS1307's
' SQW to RB0. Rather than 'poll' and display the time/date
' as in this example code, you can have an interrupt
' on RB0 each second to do this. In fact if you look at
' my code for setting the DS1307 you'll see I've already
' programmed it for a 1 second 'Tick' for exactly this
' purpose...
SCLpin var PORTB.1
SDApin var PORTB.2
'
' Setting Buttons
' ---------------
' Buttons are connected between PORTB.4, 5 & 6 down to Vss
' No Resistors required - we're using weak pull-up's
'
DecButton var PORTB.4 ' Press to Decrement Button
SetButton var PORTB.5 ' Press to Set/memorise Button
IncButton var PORTB.6 ' Press to Increment Button
'
' Unused Ports
' ------------
' RA4
' RA5
' RB3
' RB7
'
' EEPROM Locations
' ----------------
Data @0,74,97,110,70,101,98,77,97,114,65,112,114
' Jan Feb Mar Apr
Data 77,97,121,74,117,110,74,117,108,65,117,103
' May Jun Jul Aug
Data 83,101,112,79,99,116,78,111,118,68,101,99
' Sep Oct Nov Dec
Data 84,117,101,87,101,100,84,104,117,70,114,105
' Tue Wed Thu Fri
Data 83,97,116,83,117,110,77,111,110
' Sat Sun Mon
'
' RAM Assignments and Variables
' -----------------------------
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
CounterC var byte ' General purpose Variable
CounterD var byte ' General purpose Variable
RTCSec var byte ' Seconds
RTCMin var byte ' Minutes
RTCHour var byte ' Hours
RTCWDay var byte ' Weekday
RTCDay var byte ' Day
RTCMonth var byte ' Months
RTCYear var byte ' Year
RTCCtrl var byte ' Control
SetTime var byte ' 12/24 Hour Clock
SetSec var byte ' Seconds
SetMin var byte ' Minutes
SetHour var byte ' Hours
SetDay var byte ' Day
SetMonth var byte ' Months
SetYear var byte ' Year
TimeOut var word ' Variable for SetUp Menu Time-Out
'
' Program Constants
' -----------------
ButtonRepeat con 200 ' Timeperiod (in mS for Edit Buttons auto-repeat
' should you want to hold them down...
'
' Start Program
' =============
goto JumpStart
'
' Subroutine Nest Area
' ====================
'
' 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
'
' Subroutine Displays Month at current Cursor Position
' ----------------------------------------------------
' CounterB holds Month (1-12) this value is destroyed by the routine
' additionally uses CounterA and CounterD variables
DisplayMonth:
CounterB=CounterB*3-3 ' Convert BCD Month to EEPROM Start Address
DisplaySequence:
For CounterA=CounterB to CounterB+2
' Read and Display Month
Read CounterA,CounterD
LCDOut CounterD
Next CounterA
Return
'
' Subroutine works out Number of Days in the Month
' ------------------------------------------------
' SetYear - entry variable containing year (0-99)
' SetMonth - entry Variable Containing Month (1-12)
' CounterA - exits with number of days
FindDays:
LookUp SetMonth-1,[31,28,31,30,31,30,31,31,30,31,30,31],CounterA
' Above line gives the 'usual' days of the Month
' Section below adjusts for Leap-Year
If SetMonth=2 then
If (SetYear&$03)=0 then CounterA=29
endif
Return
'
' Subroutine waits until user reseases Set Button
' -----------------------------------------------
SetButtonRelease:
LCDOut $FE,1
While SetButton=0:Wend
Pause 250 ' Small pause to kill any Key-Bounce
Return
'
' End of Subroutine Nest Area
' ---------------------------
'
' Actual Start of Real Program
' ============================
JumpStart:
'
' Set Hardware Directions
' -----------------------
CMCON=%00000111 ' Disable Comparators
TRISA=%00000000 ' PORTA all set to Output
TRISB=%11111111 ' PORTB all set to Input
OPTION_REG.7=0 ' Enable Weak Pull-Ups
'
' Reset Hardware
' --------------
Pause 200 ' Timeout for LCD to settle
'
' Time & Date Display Loop
' ========================
ReDisplay:
LCDOut $FE,1 ' Clear LCD
ReDisplayLoop:
'
' Read RTC
' --------
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCYear,RTCCtrl]
'
' Decide if Setup Required/Wanted
' -------------------------------
If RTCSec.7=1 then goto SetUpPreset
' Hands-Up who noticed the fact that when the DS1307
' powers-up initially from cold, and all it's
' registers are potentially "unpredictable", that
' Seconds bit 7 is always high?
' We can use this feature to automatically jump to
' our 'Setup' routine on initial power-up if the user
' forgets to keep 'Setup' depressed and so prevent
' any 'undesriable' Time & Date displays...
If SetButton=0 then
' If Set Button is pressed, User will be taken to
' the Setup Menu. If the Set Button is pressed at
' Power-Up, then the User will be taken to the Setup
' Menu directly without any intermediate display
Gosub SetButtonRelease
goto Setup
endif
'
' Display RTC
' -----------
' Displayed on 2-line 16 character LCD in the form...
' 10:15:00 AM
' Wed 12 Jun 2002
' Note - AM/PM indicator only shows in 12 hour mode.
' Additionally there is Hours leading Zero Surpression in 12-Hour Mode
' after-all, you don't display 07pm do you?
'
'
' Display Time on Line 1
' ----------------------
LCDOut $FE,$80
If RTCHour.6=1 then
' Work-Out 12 or 24 hour Display for Hours
CounterA=(RTCHour>>4)&$01
else
CounterA=(RTCHour>>4)&$03
endif
CounterA=CounterA*10+(RTCHour&$0F)
If RTCHour.6=1 then
' Display Hours appropriately for 12 or 24 hour Mode
LCDOut #CounterA
else
LCDOut #CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTCMin>>4)&$0F,#RTCMin&$0F,":"
LCDOut #(RTCSec>>4)&$0F,#RTCSec&$0F," "
IF RTCHour.6=1 then
If RTCHour.5=1 then
LCDOut "PM"
else
LCDOut "AM"
endif
endif
'
' Display Day of Week on Line 2
' -----------------------------
' Let's face it... the DS1307 doesn't calculate the Day of Week,
' all it does is increment a number at each mignight from
' 1 thru 7 and roll back to start from 1 all over again.
' It's really up to you to work out the DOW and program it in.
' This is a tough nut for integer math to do... see the
' 'Calculate Day of Week' routine in the setup section.
LCDOut " ",$FE,$C0
CounterB=RTCWDay*3+33 ' Convert BCD WeekDay to EEPROM Start Address
Gosub DisplaySequence ' Display 3 character sequence from EEPROM
'
' Display Date on Line 2
' ----------------------
LCDOut " ",#(RTCDay>>4)&$0F,#RTCDay&$0F," "
CounterB=((RTCMonth>>4)&$0F)*10+(RTCMonth&$0F)
Gosub DisplayMonth
LCDOut " 20",#(RTCYear>>4)&$0F,#RTCYear&$0F,$FE,$80
'
Pause 250 ' Repeat about 4 times/sec
Goto ReDisplayLoop
'
' Clock and Calandar Settings
' ===========================
'
' Initial Default Settings
' ------------------------
' Default setting preset to the moment this program first born
'
SetupPreset:
RTCSec=$00 ' Seconds preset to 00
RTCMin=$15 ' Minutes preset to 15
RTCHour=$13 ' Hours preset to 13'00
RTCWDay=$01 ' Weekday preset to 01
RTCDay=$12 ' Day preset 12
RTCMonth=$06 ' Months preset to June
RTCYear=$02 ' Year preset to 2002
RTCCtrl=$10 ' Control preset to output 1 second 'Tick' on SQWpin
'
' Convert the Current BCD Data to Something easier to Edit
' --------------------------------------------------------
Setup:
SetTime=RTCHour.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
SetHour=(RTCHour>>4)&$01
' if 12-hour mode
else
SetHour=(RTCHour>>4)&$03
' if 24 hour mode
endif
SetHour=SetHour*10+(RTCHour&$0F)
If SetTime=1 then
If RTCHour.5=1 then
If SetHour<12 then SetHour=SetHour+12
' Add-in the AM/PM indicator
else
If SetHour=12 then SetHour=0
endif
endif
SetMin=((RTCMin>>4)&$0F)*10+(RTCMin&$0F)
SetSec=((RTCSec>>4)&$0F)*10+(RTCSec&$0F)
SetYear=((RTCYear>>4)&$0F)*10+(RTCYear&$0F)
SetMonth=((RTCMonth>>4)&$0F)*10+(RTCMonth&$0F)
SetDay=((RTCDay>>4)&$0F)*10+(RTCDay&$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:
LCDOut $FE,1,"Set "
'
' First Display the Menu Prompts
' ------------------------------
' This is a crude way of doing the entry Menu's but it was
' pretty fast and quite mindless to program this lunch-hour
'
If CounterC=0 then
LCDOut "Mode"
endif
If CounterC=1 then
LCDOut "Hours"
endif
If CounterC=2 then
LCDOut "Minutes"
endif
If CounterC=3 then
LCDOut "Seconds"
endif
If CounterC=4 then
LCDOut "Year : 20"
endif
If CounterC=5 then
LCDOut "Month"
endif
If CounterC=6 then
LCDOut "Day"
endif
If CounterC<>4 then LCDOut " :"
'
' Now Display the Data
' --------------- ----- SIGUE >>
masterjorgito: (para que analicemos entre todos)
NOTA 1: pone alguno registros (lcd) en PORTA 6 y 7 ???
NOTA 2: que es el modificador OPTION_REG.7=0 ?
Comentario: para que funcione modifiqué los registros de puertos hasta que dí con EL MODIFICADOR (OPTION_REG.7=0) y decidí
configurar en los puertos B6 y B7 los registros de SCL y SDA del i2c.
En principio hice parpadear el led del pin SQW del DS 1307 y aparece en pantalla la configuración del reloj pero se disparaban los valores (día,fecha,año...) al azar. Improvisando con resistores a masa y a Vcc superé el problema pero creo que debería resolverlo de otra manera.
El reloj lo hice con un display de 4 lineas y modifiqué los valores de la EEprom para que la configuración en pantalla aparezca en castellano. Ahora estoy buscando la forma para que muestre la palabra completa, y no solamente las tres primeras letras.
GRACIAS Y HASTA LUEGO.