Shop OBEX P1 Docs P2 Docs Learn Events
DS1307,help on explanation of the code — Parallax Forums

DS1307,help on explanation of the code

CruxCrux Posts: 74
edited 2007-08-30 15:43 in BASIC Stamp
I experimented with the I2C,Im still a newbie about this particular area and I messed with the code from this article in this link

www.parallax.com/dl/docs/books/sw/Web-SW-v2.1.pdf

I was able to manage already to write some default values to the DS1307 but the problem is I cant display it in my own code. I think If I understood this part here I could find the solution to my code,

refer to the link I placed above and turn to page 198,you can see this variables below

==========================================================

secs VAR Byte ' DS1307 time registers
mins VAR Byte
hrs VAR Byte
day VAR Byte ' weekday
date VAR Byte ' day in month, 1 - 31
month VAR Byte
year VAR Byte
control VAR Byte

===========================================================

I want to know how was it possible,that this block:

===========================================================

Get_Clock:
GOSUB I2C_Start ' send Start
i2cWork = slvAddr & %11111110 ' send slave ID (write)
GOSUB I2C_TX_Byte
IF (i2cAck = Nak) THEN Get_Clock ' wait until not busy
i2cWork = 0 ' point at secs register
GOSUB I2C_TX_Byte
GOSUB I2C_Start
i2cWork = slvAddr | %00000001 ' send slave ID (read)
GOSUB I2C_TX_Byte
FOR idx = 0 TO 6 ' read secs to year
GOSUB I2C_RX_Byte
secs(idx) = i2cWork
NEXT
GOSUB I2C_RX_Byte_Nak ' read control
control = i2cWork
GOSUB I2C_Stop
RETURN

===========================================================

was able to assign values to the variables I mentioned above?

I am pretty sure it is the secs(idx) in the FOR LOOP that is assigning values to it.

I want to know in detail how was it able to access the ram and was able to assigned to the variables.


THANKS

Comments

  • ZootZoot Posts: 2,227
    edited 2007-08-27 21:47
    You're basically on the right track. When you assign a variable in Pbasic, there are "implied" arrays associated with that variable -- basically any memory following the variable can be accessed AS IF it were an array, with the actual defined variable determining the size of the cell.

    For example:

    someData VAR Byte

    would let me access someData(0) -- the same as someData
    someData(1) -- the next byte after someData
    someData(2) -- etc

    So in the DS1307 examples:

    secs VAR Byte 'same as secs(0)
    mins VAR Byte 'same as secs(1)
    hrs VAR Byte 'same as secs(2)
    day VAR Byte ' same as secs(3)
    date VAR Byte ' same as secs(4)
    month VAR Byte ' same as secs(5)
    year VAR Byte 'same as secs(6)
    control VAR Byte 'same as secs(7) -- so always be careful w/implied arrays -- it's easy to overwrite data that should be for something else

    Since you can use expressions, vars, etc. for the index of an array, the I2C routines use this "trick" with implied arrays to read bytes into

    secs(0)..secs(6) using
    FOR idx = 0 TO 6

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • CruxCrux Posts: 74
    edited 2007-08-28 09:28
    Thanks, I got it smoothly running already but I still got another problem.. I cant initialize the 12 hour mode in the DS1307,anybody knows how to initialize?I browsed the datasheet and I followed the register address which is 02H and wrote a value of $46 which would mean I will reset the hour value into 6 AM,pls help
  • ZootZoot Posts: 2,227
    edited 2007-08-28 15:56
    Hmmm. That sounds right -- if you write to $46 to register $02, you should get 6AM in 12 hour mode.

    BIT6 = 1 = 12 hour mode
    BIT5 = 0 = AM
    BIT4 = 0 = tens hours
    BIT3..BIT0 = unit hours

    Yeah, that's right.

    Can you post your full code? Maybe the register is not being written properly. Is the clock keeping correct time even if it's in 24 hour mode? Remember that BIT7 of register 0 must be set to 0 at least once to "enable" the oscillator (e.g. start the clock running).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • CruxCrux Posts: 74
    edited 2007-08-29 15:01
    I tried variations of settings in the code I provided,I changed $46 to this one below because it was still in the 24 Hour mode

    Default_HOUR CON $52


    I think without initializing BIT7 to 0 of register 0 will not make the clock run,am I right?I already made this initialization I just cant figure out why I still get 24 hour mode in hour.
  • ZootZoot Posts: 2,227
    edited 2007-08-29 17:01
    OK, at first glance I don't think these defaults in your initialization sub are good. Here are revised defaults with explanations:

    Default_SECONDS CON $00   'Set seconds to 0 and enable oscillator (BIT7 = 0) -- remember unlike a Stamp, a peripheral chip like this will not necessairly default to 0 on powerup
    ' also you had $50 here which would be ( 5 * 10 ) + ( 0 * 01 ) = 0 seconds
    ' UNLESS you set time to about 10 seconds before 0 on purpose?
    Default_MINUTES CON $00   'set minutes to 0
    ' you had $59 which would be ( 5 * 10 ) + ( 9 * 01 ) = 59 minutes. On purpose?
    Default_2412AMPM    CON %01000000  '12 hour, AM -- set  mode/am/pm as bits -- easier to read
    Default_HOUR CON Default_2412AMPM + $06  ' mode/am/pm bits + ( 0 * 10 )  ( 6 * 01 ) hours
    ' you had $52 which would be %01000000 + $12 which would be 12 hour, AM but 1 in the tens, 2 in the ones
    ' remember this is BCD -- the lower NIBBLE of the secs/hours/mins is the digit -- the lower nibble will always be
    ' 0 through 9; the higher nibble will be the "upper" digit -- in 12 hour mode it will be 0 thru 1, in 24 hour mode, 0 thru 2
    ' the trap with hours, secs, is you need to mask off (disregard) the highest bits which are used for modes/enables
    Default_DAY     CON $01   'set day to sunday
    Default_DATE    CON $01   'set date to 1
    Default_MONTH   CON $01   'set month to january
    Default_YEAR    CON $07   'set year to 2007
    Default_CONTROL CON $00   'set contol to disable
    
    



    Next, and here I didn't quite have the time yet to look at the BS2 I2C routines, as I pretty much just use BSPs if I need I2C, but this doesn't seem quite right, so I made some changes:

    
      GOSUB I2C_START
      I2C_Raw_data = DS1307_Address       'assign device address
      Device_Access = Write_device        'assign access control -- you're writing
      GOSUB I2C_WRITE
      I2C_Raw_data = 0                    'you had 2 here, which not be secs register
      GOSUB I2C_WRITE_DATA          'point to this register
       I2C_Raw_data = 2                   'just an example, but set seconds to 02 and leave oscillator on
      GOSUB I2C_WRITE_DATA          'send data to this register
      GOSUB I2C_STOP
    
    



    I took out the rest of the set "hours" code before the I2C_STOP above, because I *think* that the setup of the subroutine Initialize_Clock_Defaults led you to skip some steps above. With *most* I2C devices, the register you are reading or writing from is "auto-incremented" if you don't stop. So the Initialize_Clock_Defaults routine takes advantage of this fact by writing a "write" bit to the device followed by the register number for SECONDS. The seconds register is conveniently numbered 0. Then the routine PRESUMES that after reads the byte from register 0, the next byte it asks for will come from register 1, and so on.

    If you want to "skip around" to different registers, you have to specifiy each register in turn. It looks like this as an outline:

    - start I2C, wait for control of I2C bus
    - send device address with write bit = 1
    - send the register address byte you want to read from
    - read the byte of data
    - (optionally) keep reading bytes IN ORDER
    - stop I2C

    Lastly, and here I offer my apologies again, because I didn't have the time to look over the I2C routines in detail till this evening. Is that your code? I looked at the code from page 179 in the StampWorks PDF, and your I2C routines are substantially different. I don't think you're handling the ACK NACK properly.

    You might try using the code as is from the tuturials, swapping in the address of your DS1307 and cutting/pasting the start/write/send/stop code with your registers, e.g.:

    Setup:
    slvAddr =  DS1307_Address ' setup slave ID to be your DS1307
    addrLen = 1 ' 1 byte register  addresses
    
    Main:
    wrdAddr = 0 ' write to register 0 (seconds and oscillator)
    i2cData = $00 ' enable osc, 00 seconds
    GOSUB Write_Byte
    wrdAddr = 1 ' write to register 1 (minutes)
    i2cData = $00 ' 0 minutes
    GOSUB Write_Byte
    wrdAddr = 2 ' write to register 2 (hours)
    i2cData = %010010000 ' 12 hour, AM, ( 1 * 10 ) + ( 0 * 01 ) = 10 hours
    GOSUB Write_Byte
    
    ' now read the time
    wrdAddr = 2 'start with hours, we'll  go right to debug screen
    GOSUB Read_Byte ' returns i2cData
    DEBUG "hours: ", DEC i2cData.BIT4, DEC2 i2cData.LOWNIB  'bit4 is 10s, lownib is 1s
    IF ( i2cData.BIT5 = 0 ) THEN
       DEBUG "AM"
    ELSE
       DEBUG "PM"
    ENDIF
    DEBUG CR
    
    wrdAddr = 1 ' minutes
    GOSUB Read_Byte
    DEBUG "mins:  ", HEX2 i2cData, CR 'high nib 10s, lownib 1s
    
    wrdAddr = 0 ' secs
    GOSUB Read_Byte
    i2cData = i2cData & %01111111 'technically, mask of the osc bit, but if it's 1 your time is no good anyway [img]http://forums.parallax.com/images/smilies/smile.gif[/img]
    DEBUG "secs:  ",  HEX2 i2cData, CR 'high nib 10s, lownib 1s
    
    
    



    It's not as efficient as reading/writing all the bytes in one shot, and you're wasting byte on the word address, but it shows the steps really clearly and might help you understand what's going on when you read from I2C registers.

    Does this help?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • CruxCrux Posts: 74
    edited 2007-08-30 03:02
    I will still try this out and I'll just reply as soon as i get questions. Thanks
  • CruxCrux Posts: 74
    edited 2007-08-30 03:10
    Do you know any link that cud give a concise tutorials about BCD,Im still confused about this stuff.
  • ZootZoot Posts: 2,227
    edited 2007-08-30 05:33
    Don't let the term BCD throw you. All it means is:

    HIGHNIB = 10s
    LOWNIB = 1s

    So HEX $10 does not equal the decimal number 10
    To get the DECIMAL number you'd need to do:
    HIGHNIB * 10 + LOWNIB

    HEX $11 = "11" but decimal number would be:
    HIGHNIB * 10 + LOWNIB = 10 + 1 = 11

    Remember that a nib can count to 16 -- so the number
    13
    if converted to hex would not be $13 but would be
    $0D

    If you want a concise tutorial, I'm not sure... check the Stamp manual, or maybe the explanation at Wikipedia: en.wikipedia.org/wiki/Binary-coded_decimal

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • CruxCrux Posts: 74
    edited 2007-08-30 15:43
    I think I already corrected my problem. What I did was dividing the nibbles in displaying the hour.Thanks
Sign In or Register to comment.