How do I set the year in the RTC module

General discussion on mikroBasic.
Author
Message
Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

How do I set the year in the RTC module

#1 Post by Ken » 13 Aug 2006 23:19

Hi,
Can someone please explain how to set the year in the RTC module. In the data sheet it states, memory location 05 (year/date), year (0 to 3 binary, read as 0 if the mask flag is set). What does this mean? In the mB example, memory location 05 is hex 24 which is binary 00100100 so according to the data sheet bits 7 and 6 (year) = 0, bits 5 and 4 (ten days) = dec 2, bits 3 - 0 (unit days BCD) = dec 4, all this gives us a date of the 24th. How do I change the year to 2006?

P.S. I assume that the date format displayed on the LCD is day/month/year if I'm wrong then I am totally confused.

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#2 Post by xor » 14 Aug 2006 00:42

Ken,

I don't use the PCF8583 but after looking at the datasheet I think I understand how to do this. Address locations 05 and 06 in the IC have double duty. Each of these addresses can be one of two things depending on how you set/reset Bit3 of the Control Register.

For instance, if you make Bit3 = 1 in the Control Register, address 05 is the DATE value and address 06 is the MONTH value. If Control Register Bit3 = 0, then address 05 is the YEAR value and address 06 is the WEEKDAY value. It's a shortcut method of addressing registers used by this IC.

Also note that each byte is made up of 2 BCD values. That means that the Lower Nybble (4-bits) of a byte is a value from 0 to 9 for the decimal 1's position, and the Upper Nybble is a value of 0 to 9 for decimal 10's position. So a value of HEX 24 ($24) is really equivalent to decimal 24.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#3 Post by Ken » 14 Aug 2006 01:40

Hi Xor,
Thanks for taking the time to look over the data sheet. That didn't work. This is what I tried:

Code: Select all

main:
   I2C_Init(10000)      ' initialize full master mode
   I2C_Start            ' issue start signal
   I2C_Wr($A0)         ' address PCF8583
   I2C_Wr(0)            ' start from word at address 0 (configuration word)
   I2C_Wr($80)          '0 write $80 to config. (pause counter...)
   I2C_Wr($0)           '1 write 0 to cents word
   I2C_Wr($0)           '2 write 0 to seconds word
   I2C_Wr($27)           '3 write $30 to minutes word
   I2C_Wr($11)          '4 write $11 to hours word
   I2C_Wr($24)          '5 write $24 to year/date word
   I2C_Wr($11)          '6 write $08 to weekday/month
   I2C_Stop             ' issue stop signal

   I2C_Start
   I2C_Wr(0)            ' start from word at address 0 (configuration word)
   I2C_Wr($88)          '0 write $88 to config. set bit 3
   I2C_Wr(5)            ' start from word at address 5 (year/date word)
   I2C_Wr($86)
   I2C_Stop             ' issue stop signal
   
   I2C_Start            ' issue start signal
   I2C_Wr($A0)          ' address PCF8530
   I2C_Wr(0)            ' start from word at address 0
   I2C_Wr(0)            ' write 0 to config word (enable counting)
   I2C_Stop             ' issue stop signal
end.

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#4 Post by Ken » 14 Aug 2006 01:48

Got it! :lol:

Code: Select all

main:
   I2C_Init(10000)      ' initialize full master mode
   I2C_Start            ' issue start signal
   I2C_Wr($A0)         ' address PCF8583
   I2C_Wr(0)            ' start from word at address 0 (configuration word)
   I2C_Wr($80)          '0 write $80 to config. (pause counter...)
   I2C_Wr($0)           '1 write 0 to cents word
   I2C_Wr($0)           '2 write 0 to seconds word
   I2C_Wr($27)           '3 write $30 to minutes word
   I2C_Wr($11)          '4 write $11 to hours word
   I2C_Wr($80+$13)  ' 5 write $80=2006, +$13 to year/date word
   I2C_Wr($08)          '6 write $08 to weekday/month
   I2C_Stop             ' issue stop signal

   I2C_Start            ' issue start signal
   I2C_Wr($A0)          ' address PCF8530
   I2C_Wr(0)            ' start from word at address 0
   I2C_Wr(0)            ' write 0 to config word (enable counting)
   I2C_Stop             ' issue stop signal
end.
Found this in another post, I2C_Wr($80+$13), sorry I forget who's post it was.

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#5 Post by xor » 14 Aug 2006 02:13

I'm still trying to figure out how $80 is equivalent to 2006 in Address 05. The datasheet is not much help here either. Somehow setting the year seems to still be a different read/write based on setting/resetting the mask bit (Bit3) :?
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#6 Post by Ken » 14 Aug 2006 02:31

Somehow $80=6, it works for now. The 200 that precedes it is handled by the read program. If you figure it out I'd like to know what you find.
Ken

retep
Posts: 115
Joined: 15 Apr 2006 19:00
Location: Windhoek Namibia

#7 Post by retep » 14 Aug 2006 17:20

so is it. the pcf8583 can not handl the year fully.

you have to store the real year in one of the free eeprom and to correct if the yeare calendar is changed.

so there is only a counter 0 - 4 and you have to set them so thad the switch yeare was to yeare a go. remember every olympia year is a switch year.

the real count of 2006, 2007, 2008 and more have the software to do.

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#8 Post by Ken » 15 Aug 2006 01:10

I'm not sure, I just said that the 200 portion of the 2006 is handled by the mB sample read program.

California
Posts: 361
Joined: 14 Dec 2005 20:56
Location: Slovenia

#9 Post by California » 15 Aug 2006 07:09

Look this code and help yourself.

Code: Select all

program ura2_usart
                                       ' 18F458-HS mikroBasic2.2


symbol OWP = PORTA
symbol PIN = 5
dim  cnt, cnt1 as byte
dim txtmin as char[16]
dim K1 as integer
dim D0,D1,D2,D3,D4 as byte
dim Sec as byte
dim Min as byte
dim Hr  as byte
dim Day as byte
dim Mn  as byte
dim Year as byte
dim txt,txt1 as char[16]
dim minuta, ura, ura10, dan, mesec, leto as byte

sub procedure Set_Clk
   Soft_I2C_Start                 ' issue start signal
   Soft_I2C_Write($A0)            ' address PCF8583
   delay_ms(20)
   Soft_I2C_Write(0)              ' start from word at address 0 (configuration word)
   delay_ms(20)
   Soft_I2C_Write($80)            '0 write $80 to config. (pause counter...)
   delay_ms(20)
   Soft_I2C_Write(0)              '1 write 0 to cents word
   delay_ms(20)
   Soft_I2C_Write(0)              '2 write 0 to seconds word
   delay_ms(20)
   Soft_I2C_Write(minuta)         '3 write $56 to minutes word
   delay_ms(20)

   Soft_I2C_Write(ura10+ura)      ' 4 $80 is 12hr mode A.M., write $10 to hours word    '$20+$03   'ura10
   delay_ms(20)                   ' $C0 is 12hr mode P.M.,
   Soft_I2C_Write($80+dan)       ' 5 write $80=2006, +$17 to year/date word
   delay_ms(20)
   Soft_I2C_Write(mesec)          ' 6 write $02 to weekday/month
   delay_ms(20)
   Soft_I2C_Stop                  ' issue stop signal

   Soft_I2C_Start                 ' issue start signal
   Soft_I2C_Write($A0)            ' address PCF8530
   delay_ms(20)
   Soft_I2C_Write(0)              ' start from word at address 0
   delay_ms(20)
   Soft_I2C_Write(0)              ' write 0 to config word (enable counting)
   delay_ms(20)
   Soft_I2C_Stop                  ' issue stop signal
end sub

sub procedure Set_Time
    Lcd_Cmd(Lcd_Clear)
    lcd_out(1,1,"Set Time Date")
    D1 = TestBit(PORTD,1)
        if D1 = 1
         then inc(cnt1)
           if cnt1 = 7 then cnt1 = 0 end if
        end if
    if cnt1 = 0 then lcd_out(2,1,"Time menu") end if

    if cnt1 = 1
      then lcd_out(2,1,"minute")  ByteToStr(Min,txt) LCD_Out(2,9,txt)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > $59 then K1 = $1 end if
           if K1 = 10 then K1 = 16 end if
           if K1 = 26 then K1 = 32 end if
           if K1 = 42 then K1 = 48 end if
           if K1 = 58 then K1 = 64 end if
           if K1 = 74 then K1 = 80 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < $1 then K1 = $59 end if
           if K1 = 15 then K1 = 9 end if
           if K1 = 31 then K1 = 25 end if
           if K1 = 47 then K1 = 41 end if
           if K1 = 63 then K1 = 57 end if
           if K1 = 79 then K1 = 73 end if
        end if
      minuta=K1     Set_Clk
    end if

    if cnt1 = 2
     then lcd_out(2,1,"ura10")  ByteToStr(Hr,txt) LCD_Out(2,9,txt)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > $23 then K1 = $1 end if
           if K1 = 10 then K1 = 16 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < $1 then K1 = $23 end if
           if K1 = 15 then K1 = 9 end if
        end if
      ura10=K1     Set_Clk
    end if

    if cnt1 = 3
      then lcd_out(2,1,"ura")  ByteToStr(Hr,txt) LCD_Out(2,9,txt)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > $23 then K1 = $1 end if
           if K1 = 10 then K1 = 16 end if
           if K1 = 26 then K1 = 32 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < $1 then K1 = $23 end if
           if K1 = 15 then K1 = 9 end if
           if K1 = 31 then K1 = 25 end if
        end if
      ura=K1     Set_Clk
    end if

    if cnt1 = 4
      then lcd_out(2,1,"dan")  ByteToStr(day,txt) LCD_Out(2,9,txt)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > $31 then K1 = $1 end if
           if K1 = 10 then K1 = 16 end if
           if K1 = 26 then K1 = 32 end if
           if K1 = 42 then K1 = 48 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < $1 then K1 = $31 end if
           if K1 = 15 then K1 = 9 end if
           if K1 = 31 then K1 = 25 end if
           if K1 = 47 then K1 = 41 end if
        end if
      dan=K1     Set_Clk
    end if

    if cnt1 = 5
      then lcd_out(2,1,"mesec")  ByteToStr(Mn,txt) LCD_Out(2,9,txt)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > $12 then K1 = $1 end if
           if K1 = 10 then K1 = 16 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < $1 then K1 = $12 end if
           if K1 = 15 then K1 = 9 end if
        end if
      mesec=K1     Set_Clk
    end if

    if cnt1 = 6
      then lcd_out(2,1,"leto")  ByteToStr(leto,txt1) LCD_Out(2,9,txt1)
        D3 = TestBit(PORTD,3)
        if D3 = 1
         then Inc(K1)
           if K1 > 9 then K1 = 0 end if
        end if
        D4 = TestBit(PORTD,4)
        if D4 = 1
         then Dec(K1)
           if K1 < 0 then K1 = 9 end if
        end if
      leto=K1     Set_Clk
    end if

end sub

sub procedure Zero_fill(dim byref value as char[10])  ' fill text representation
  if length(value) = 1 then                           '      with leading zero
    value[2] = value[1]
    value[1] = 48
    value[0] = 2
  end if
end sub

sub procedure Read_time(dim byref Sec as byte,
                        dim byref Min as byte,
                        dim byref Hr  as byte,
                        dim byref Day as byte,
                        dim byref Mn  as byte)

   soft_i2c_start
   delay_us(20)
   soft_i2c_write($A0)
   delay_us(20)
   soft_i2c_write(2)
   delay_us(20)
   soft_i2c_start
   delay_us(20)
   soft_i2c_write($A1)
   delay_us(20)
   sec=soft_i2c_read(1)
   min = soft_i2c_read(1)
   hr = soft_i2c_read(1)
   day =soft_i2c_read(1)
   mn = soft_i2c_read(0)
   soft_I2C_Stop
end sub

sub procedure Transform_time(dim byref Sec  as byte,
                             dim byref Min  as byte,
                             dim byref Hr   as byte,
                             dim byref Day  as byte,
                             dim byref Mn   as byte,
                             dim byref Year as byte)
  sec  =  ((sec and $F0) >> 4)*10 + (sec and $0F)        ' formats date and time
  min  =  ((min and $F0) >> 4)*10 + (min and $0F)
  hr   =  ((hr and $F0) >> 4)*10 + (hr and $0F)
  year =  ((day and $C0)) >> 6
  day  =  ((day and $30) >> 4)*10 + (day and $0F)
  mn   =  ((mn and $10) >> 4)*10 + (mn and $0F)
end sub

sub procedure Display_time_txt
   Lcd_Cmd(Lcd_Clear)
   txt = "Datum"
   LCD_Out(1,1,txt)
   txt = "Ura"
   LCD_Out(2,1,txt)
   txt = "200"
   LCD_Out(1,13,txt)


end sub

sub procedure Display_time_txt1
    Lcd_Chr(1,9,".")
    Lcd_Chr(1,12,".")
    Lcd_Chr(2,9,":")
    Lcd_Chr(2,12,":")
end sub

sub procedure Display_time(dim Sec  as byte,
                           dim Min  as byte,
                           dim Hr   as byte,
                           dim Day  as byte,
                           dim Mn   as byte,
                           dim Year as byte)
   cnt1=0

   ByteToStr(day,txt)
   Zero_fill(txt)
   LCD_Out(1,6,txt)
   ByteToStr(mn,txt)
   Zero_fill(txt)
   LCD_Out(1,9,txt)

   LCD_Chr(1,16,46+leto+year)

   ByteToStr(hr,txt)
   LCD_Out(2,6,txt)
   ByteToStr(min,txtmin)
   Zero_fill(txtmin)
   LCD_Out(2,9,txtmin)
   ByteToStr(sec,txt)
   Zero_fill(txt)
   LCD_Out(2,12,txt)

   D2 = TestBit(PORTD,2)
        if D2 = 1
         then Set_Clk
        end if
end sub

main:
    '
    adcon1 = 255                             ' configure RA5 pin as digital I/O
    CMCON  = 7                               ' comparators on portD off
    PORTB  = 0                               ' initialize PORTB
    PORTC  = 0                               ' initialize PORTC
    PORTD  = 255                             ' initialize PORTD
    PORTA  = 255                             ' initialize PORTA
    TRISB  = 0                               ' designate PORTB as output
    TRISC  = 0                               ' designate PORTC as output
    TRISD  = 255                             ' designate PORTD as input
    TRISA  = 255                             ' designate PORTA as input
    soft_i2c_config(PORTE,1,0)
    Lcd_Init(PORTB)
    lcd_cmd( LCD_CURSOR_OFF)
    
    Usart_Init(9600)                 ' Initialize USART module  2400

    minuta = $59
    ura    = $03
    ura10  = $20
    dan    = $17
    mesec  = $04
    leto   = 0


    cnt = 1
    cnt1= 0
    K1  = $30
    while true
        SetBit(PORTC,0)
        Delay_ms(200)
    Read_Time(Sec, Min, Hr, Day, Mn)              ' read time from RTC(PCF8583)
    Transform_Time(Sec, Min, Hr, Day, Mn, Year)

        D0 = TestBit(PORTD,0)
        if D0 = 1
         then inc(cnt)
           if cnt = 3 then cnt = 1 end if
        end if
        if cnt = 1 then Display_time_txt Display_Time(Sec, Min, Hr, Day, Mn, Year)
                        Display_time_txt1   end if
        if cnt = 2 then  Set_Time  end if

       ClearBit(PORTC,0)
       Delay_ms(100)
       Usart_Write(sec)   ' Send data via USART

    wend

end.

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#10 Post by xor » 15 Aug 2006 11:41

Can you explain how $80 = 2006? How would you write the year 2007?

Code: Select all

  Soft_I2C_Write($80+dan)       ' 5 write $80=2006, +$17 to year/date word
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#11 Post by Ken » 15 Aug 2006 13:16

Thanks for posting your code California and like Xor I would also like to know a little more on how the year byte is configured.
Ken

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#12 Post by xor » 15 Aug 2006 14:55

Found it! The year is 00 to 99 and is written at address 08, not 05 and 06. This is from an application note: http://www.standardics.philips.com/supp ... clocks.pdf
8. Initialization
Setting the clock is a straight forward procedure, setting first the mode and then the actual time: e.g Friday, July 16 1999, 2’45 pm
Image
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Ken
Posts: 166
Joined: 23 Dec 2005 20:56
Location: New York, USA

#13 Post by Ken » 15 Aug 2006 15:09

I see in the application note address 08 is "setting years to 99" but, in the data sheet 08 is the alarm control register. Even with that said how does a value of $80 = 2006?

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#14 Post by xor » 15 Aug 2006 17:13

You're right. There are some differences between the datasheet and the application notes. Hmmmm? If I were to take another guess, the year is not actually available except for user reference. It seems that it's 0 to 3 only, which may only be important to help identify a leap year. I think I'll stick to my DS1307.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

retep
Posts: 115
Joined: 15 Apr 2006 19:00
Location: Windhoek Namibia

#15 Post by retep » 15 Aug 2006 21:01

i not undersoud wy you gays not axept thad the PCF8583 not have a full yeare calendar.

the sample code from wath you speak i never cared about.

i wrote selve one witch is made in order of the datasheet. and it works.
i not have to look about mistakte by copy it in know each line because i wrote it selve.

Post Reply

Return to “mikroBasic General”