PDA

View Full Version : I2C clock code with tiny problem



Amoque
- 25th October 2013, 16:30
I hope this day finds you well.

Armed with the information I gained in my last post (thank you again), I set about putting it to use in the following code. I think that it is a good beginner project - a clock that uses the popular DS series I2C chip and is very simple in hardware by displaying to the debug window rather than some complicated interface. Unlike many I have seen posted, the complete code for buttons is included and to the best of my ability it is commented and tested to function in every regard - except one: It doesn't work.

Enjoy your laugh at my chagrin, as I have! Then, wipe the tear from your eye and consider my problem, if you please.

The clock starts by displaying the special and status registers, writes to them and reads back the values without flaw.
It then initialized each day and date register with it's hex value ($00 is written to seconds, $01 to minutes, $02 to hours...). This also works well and displays as expected.

Clock display outputs as it should.

Each of the three buttons work as I intended: Press "1" to enter the adjustment routines, "2" to advance though the registers, and "3" to advance through valid values. "1" again writes the new register value to the clock chip and, in a few seconds without input, at any point, the routines abort appropriately.

Almost perfect, except the clock value never advances - stubbornly remaining precisely as set. I believe that in my fumbling attempts to "pull up" the heartbeat signal I may have damaged the clock chip. I haven't another and so expose my ineptitude in hopes of avoiding the delay of ordering another (or at least verifying such a delay is unavoidable) by asking for help - either by hardware test or simulation to determine I have not a code error. Is that possible? If so, thank you.




'************************************************* ***************
'* Name : 3 BTN CLOCK.BAS *
'* Author : [AMOQUE] *
'* Notice : Copyright (c) 2013 [PBP 2.6] *
'* : All Rights Reserved *
'* Date : 10/21/2013 *
'* Version : 1.0 *
'* Notes : 16F88, DS1337 or equivalent, *
'* : 3 BUTTONS - ACTIVE HIGH *
'************************************************* ***************

#CONFIG
__config _CONFIG1, _INTRC_IO & _WDT_OFF & _PWRTE_OFF & _MCLR_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_PROTECT_OFF & _DEBUG_OFF
__config _CONFIG2, _FCMEN_OFF & _IESO_OFF
#ENDCONFIG
DEFINE OSC 8

'-----DEBUG (SERIAL) SETUP----------------------------------------
DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 5
DEFINE DEBUG_BAUD 2400
DEFINE DEBUG_MODE 0

'-----CHIP REGISTER SET-UP----------------------------------------
TRISA = %00000000 ' Set PORTA output
TRISB = %00001101
OSCCON = %01110000
CCP1CON = %00001100
T2CON = %00000101
'ADCON0 = %11000000 ' Configure and turn on A/D Module
'ADCON1 = %10000000 ' Set PORTA analog and LEFT justify result
'ANSEL = %00000011

'-----PORT SET-UP-------------------------------------------------
SDA VAR PORTB.1
SCL VAR PORTB.4
BTN1 VAR PORTB.0
BTN2 VAR PORTB.2
BTN3 VAR PORTB.3

'-----CLOCK SET-UP------------------------------------------------
RTC_ADD CON %11010000
REG_TIM CON $00
REG_AL1 CON $07 ' Not implemented
REG_AL2 CON $0B ' Not implemented
REG_SPC con $0E
REG_STS CON $0F

'-----TIME/ CLOCK VARIABLES----------------------------------------
REG_MIN VAR BYTE[7] ' Minimum register values
REG_VAL VAR Byte[7] ' Seconds, minutes, hours, day of week, date, month, year
REG_MAX VAR BYTE[7] ' Maximum register values
ACT_REG VAR BYTE ' Active register (setting)

'-----GENERAL USE VARIABLES---------------------------------------
LP VAR BYTE ' For/ Next value
D0 VAR BYTE
D1 VAR BYTE
D2 VAR BYTE

'-----INITIALIZE CLOCK--------------------------------------------
'CHECK STATUS
debug "---STABALIZE---", 10
pause 250
D0 = $00 : D1 = $00
gosub SPCL_READ
D0 = $00 : D1 = $00 ' Assign 'special' registers
gosub SPCL_WRITE ' Write 'special' registers
gosub SPCL_READ ' Verify

'SET INITIAL TIME
FOR lp = 0 TO 6 ' For each register
REG_VAL[LP] = LP ' Set value to address
NEXT LP ' Loop
'----------------------' Alarm set-up
GOSUB CLK_WRITE ' Write initial values and start clock

'LOAD REGISTER MIN/ MAX VALUES
REG_MIN[0] = 00: REG_MIN[1] = 00: REG_MIN[2] = 00: REG_MIN[3] = 1: REG_MIN[4] = 01: REG_MIN[5] = 01: REG_MIN[6] = 00
REG_MAX[0] = 59: REG_MAX[1] = 59: REG_MAX[2] = 23: REG_MAX[3] = 6: REG_MAX[4] = 31: REG_MAX[5] = 12: REG_MAX[6] = 99


'+++++MAIN LOOP++++++++++++++++++++++++++++++++++++++++++++++ +++++
MAIN:
if BTN1 then goto CLK_SET ' Button 1 = Enter set mode
GOSUB CLK_READ: ' Read clock
PAUSE 500 ' Pause
GOTO MAIN ' Loop til the end of time (lol)



'-----SUB-ROUTINES------------------------------------------------
'READ TIME, CONVERT TO DECIMAL VALUES, DISPLAY
CLK_READ:
I2CRead SDA, SCL, RTC_ADD, REG_TIM, [REG_VAL[0], REG_VAL[1], REG_VAL[2], REG_VAL[3], REG_VAL[4], REG_VAL[5], REG_VAL[6]]
FOR LP = 0 TO 6 ' For each register
D0 = (REG_VAL[LP] >> 4) * 10 ' Decode 10's digit
D1 = REG_VAL[LP] & %0001111 ' Blank 10's, get 1's
REG_VAL[LP] = D0 + D1 ' Write Decimal value to register
NEXT LP ' Next register
DEBUG "TIME:[", dec1 REG_VAL[3], "] ", dec2 REG_VAL[5], "/", dec2 REG_VAL[4], "/", dec2 REG_VAL[6], " ", dec2 REG_VAL[2], ":", dec2 REG_VAL[1], ":",

dec2 REG_VAL[0], 10
Return

'CONVERT TO BCD VALUES, WRITE TO CLOCK REGISTERS
CLK_WRITE:
FOR LP = 0 TO 6 ' For each register
D0 = REG_VAL[LP] / 10 ' Get decimal 10's digit
D1 = REG_VAL[LP] // 10 ' Get decimal 1's
REG_VAL[LP] = (D0 << 4) + d1 ' Shift BCD 10's in, add 1's
NEXT LP ' Next register
I2CWrite SDA, SCL, RTC_ADD, REG_TIM, [REG_VAL[0], REG_VAL[1], REG_VAL[2], REG_VAL[3], REG_VAL[4], REG_VAL[5], REG_VAL[6]]
GOSUB CLK_READ ' Update display
Return

'SPECIAL REGISTERS--------------------------------------------------------------
SPCL_WRITE:
I2CWrite SDA, SCL, RTC_ADD, REG_SPC, [D0, D1]
Return

SPCL_READ:
I2CRead SDA, SCL, RTC_ADD, REG_SPC, [D0, D1]
debug "SPCL: [", bin8 D0, "] STATUS: [", BIN8 D1, "]", 10, 10
pause 1000
Return

'BEGIN SET ROUTINE--------------------------------------------------------------
CLK_SET:
debug "SET TIME", 10 ' Announce in debug window
For LP = 0 to 100 ' Start timer loop
IF BTN2 Then Goto SELECT_REG ' Button 2 = select register
Pause 100 ' Advance time
NEXT LP ' Loop
GOTO MAIN ' Time expired, drop out

'SELECT REGISTER
SELECT_REG:
debug "SELECT REGISTER" , 10
ACT_REG = 0 : D2 = 0 ' Reset active register
For LP = 0 to 100 ' Start timer loop
IF BTN2 Then ' Button 2 press
ACT_REG = ACT_REG + 1 ' Advance active register
LP = 0 ' Restart time loop
IF ACT_REG > 6 THEN ACT_REG = 0 ' Keep register number in bounds
DEBUG "EDIT=", DEC1 ACT_REG, " MAX=" ' Announce register and max value to debug
debug DEC2 REG_MAX[ACT_REG], 10
Endif
If BTN3 Then ' Button 3 press
debug "SET REGISTER VALUE" , 10 ' Announce to debug
LP = 0 ' Restart time loop
Goto ADV_VALUE ' Goto advance register value routine
Endif ' End button 3 loop
Pause 100 ' Advance time
NEXT LP ' Loop
GOTO MAIN ' Time expired, drop out

'ADVANCE REGISTER VALUE
ADV_VALUE:
debug "ADVANCE REGISTER VALUE" , 10
for LP = 0 to 100 ' Announce to debug
IF Btn3 Then ' Button 3 press
LP = 0 ' Restart time loop
D2 = D2 + 1 ' Advance register value
IF D2 > REG_MAX[ACT_REG] THEN D2 = REG_MIN[ACT_REG] ' Keep register value in bounds
debug "REG=", DEC2 ACT_REG, " NEW VALUE=", DEC2 D2 , 10 ' Announce to debug
ENDIF ' End button 3 press
IF BTN1 Then ' Button 1 press
debug "WRITE VALUE TO CLOCK" , 10 ' Announce to debug
LP = 0 ' Restart timer
GOSUB CLK_READ ' Read fresh clock values
REG_VAL[ACT_REG] = D2 ' Insert new value
GOSUB CLK_WRITE ' Write to chip
GOTO SELECT_REG ' Goto 'select register'
EndIF ' End button 1 press
Pause 100 ' Advance timer
Next LP ' Loop
GOTO MAIN ' Time expired, drop out

END

Archangel
- 25th October 2013, 16:49
You have pullup resistors on I2C lines?

Amoque
- 25th October 2013, 17:17
Yes, I have verified the hardware again and again. In fact, early iterations worked quite well - the clock advancing for long periods as I worked through writing code, loading new many times. Then, as if choosing death over submission, it simply died.

Acetronics2
- 25th October 2013, 17:27
just if ... by greatest hazards ...



DS1337C ONLY
The DS1337C integrates a standard 32,768Hz crystal in the package. Typical accuracy at nominal VCC and +25°C is approximately +10ppm. Refer to Application Note 58 for information about crystal accuracy vs. temperature.


that checked ...




Bit 7: Enable Oscillator (EOSC). This active-low bit when set to logic 0 starts the oscillator. When this bit is set to logic 1, the oscillator is stopped. This bit is enabled (logic 0) when power is first applied


that states the device should run by itself @ power up ...

IF it's not accidentally overwritten ...

now ... did you notice the very low Xtal charge capacitance value ???

Alain

Amoque
- 25th October 2013, 17:36
With each post I, again, verify without prejudice. Chip is DS1337, "Special" registers report valid (functioning) values before being written, and verify valid values after first write (as described in RTFM). I did not notice low capacitor values, rather stuck a crystal in the appropriate holes without consideration for any value but frequency, yet it has worked without glitch for several days until after I thought I loaded "perfect" version of code.

I will see what I can do with that... though ordering crystals is as time consuming as ordering chips and, I still don't know if/ why it worked so well and stopped so suddenly.

Acetronics2
- 25th October 2013, 17:42
after years ( or not ! ) Xtals die without any announcements ...

I already experienced that ... ( with R/C Models : Ayayayay ... )

Alain

Amoque
- 25th October 2013, 17:48
I double checked both RTFM and crystal specs; they match, but as a precaution, I replaced it... and perfect! Time advances normally. Perhaps static? One again, I am stymied by the smallest thing, but different eyes (or minds) offer resolution. Thank you again, good to know my coding is correct.

All the best--

Amoque

Archangel
- 27th October 2013, 00:36
after years ( or not ! ) Xtals die without any announcements ...

I already experienced that ... ( with R/C Models : Ayayayay ... )

AlainGood information to know, thanks Alain.