I2C PIC16F690 and RTC DS3231 help

Discussion in 'Programmer's Corner' started by portreathbeach, May 1, 2014.

  1. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I want to be able to read and write to a DS3231 real time clock module using a PIC16F690. I have read about using the 'bit banging' method as when reading about the PICs I2C hardware control, it seems very long and complicated.

    Has anyone successfully read and written to a DS3231? In the datasheet for it, it says that if the power is removed from the microprocessor while a read or write is in progress, the 2 devices will be 'out of sync' as the DS3231 (as it is battery backed) could still be halfway through a data transfer the next time the microprocessor tries to talk to it.

    I program in assembly language so would appreciate any help and links directing me to any source for this.

    Thanks :)
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    Anything done in assembly is "long and complicated." That POIC has an SSP module to handle I2C for you for the most part, you still have to initiate each part of the transfer (start, address, data, stop) and know when to copy any data received.

    Being halfway thru a transfer is not an issue as the PIC will issue a start signal to reset any device out there.

    Wikipedia is as good a place as any to learn how this protocol works. You will have to dig up example code in assembly yourself, I have no links to that.
     
  3. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    Thanks for the reply, I was reading that the PIC16F690 does not support I2C master mode on it's SSP hardware, but the datasheet says that it does, so I guess the post I was reading on the internet is wrong.

    Anyway, the datasheet for the DS3231 says:

    "The I2C interface is accessible whenever either VCC or
    VBAT is at a valid level. If a microcontroller connected to
    the DS3231 resets because of a loss of VCC or other
    event, it is possible that the microcontroller and DS3231
    I2C communications could become unsynchronized,
    e.g., the microcontroller resets while reading data from
    the DS3231. When the microcontroller resets, the
    DS3231 I2C interface may be placed into a known state
    by toggling SCL until SDA is observed to be at a high
    level. At that point the microcontroller should pull SDA
    low while SCL is high, generating a START condition."

    Going by what this is saying, before I put the Start condition on the SDA and SCL lines, I need to toggle the SCL until it 'synchronises'?

    I am not a novice at programming and successfully wrote asm code a few years back to communicate with a Sony cam-corder via the LANC protocol, but I'm a little rusty.

    I have read pages and pages of Microchip datasheets showing how to implement the I2C module in various PIC microprocessors, but they is hundreds of lines of code to do what should be a fairly easy task.

    I did find this implementation of I2C, will this work for my needs?

    http://www.piclist.com/techref/microchip/i2c-dv.htm

    Anyone actually used a PIC in 'bit bang' mode to access a DS3231
     
    Last edited: May 1, 2014
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    Any assembly language program needs "hundreds of lines of code to do what should be a fairly easy task" which is why I am always constantly surprised to see people excited to be working in it.

    I've seen I2C latch like that but only when I was doing debugging of an I2C device. I used the same work around the data sheet suggests.

    Knowing that part did that I would pass and get something else with same or better function.

    As far as the code you found, if you try and try and read it over and over you should be able to adapt it for your needs. I2C has some subtle points where you have to frame the conversation in discrete chunks.
     
  5. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    You can generate a dummy start followed by a dummy stop. Then a start and the proper comms followed by the stop.

    The first (dummy) start/stop will force the I2C slave to reset or resync as needed before you do the proper comms.
     
  6. MaxHeadRoom

    Expert

    Jul 18, 2013
    10,553
    2,375
    If Assembly programming I would recommend graduating to the 18F series μp's.
    Not only for ease of programming a few more powerful instructions.
    There is minimal programming to do when implementing the I2c and there is also App notes such as AN989 etc for sample code etc.
    You don't need to resort to bit banging.
    For the 16f628
    http://www.winpicprog.co.uk/pic_tutorial6.htm
    Max.
     
    Last edited: May 2, 2014
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    The worst case slave lock-up I've seen in debug is the slave stuck transmitting a zero for an ACK, but any transmit of zero has the same effect: you cannot generate any bus commands.

    That's why you need to toggle SCK till SDA comes back.

    Note that only applies when the slave is stuck with the power on. I never had to use my work-around once I left debug mode because a later generation I2C interface resets with the power and ignores the battery back up. Vdd would reset anything stuck.

    That's another reason to avoid the DS3231. The PCF2129A has similar features, fewer bugs, and it's half the price.
     
    Last edited: May 2, 2014
  8. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    Thanks for the help. The app note AN989 looks interesting and there isn't much code to get my head around.

    It says it's for interfacing with a 24C EEPROM, I take it that the DS3231 (as it is I2C) can be read and written in the same way. I do have the datasheet for the DS3231 and it looks pretty straight forward as long as the comms work correctly in my PIC.

    I still want to use a low pin count chip, so would the PIC18F13K22 do the job? It looks as though it has a MSSP control module, so I should be able to port the code in the app note to it fairly easily shouldn't I?

    Sorry for all the questions, Thanks again :)
     
    Last edited: May 2, 2014
  9. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    ErnieM, I'm only using the DS3231 as it comes as a module at a stupidly cheap price from China (about £2). It comes with battery, battery holder, crystal etc. It wasn't until I bought a couple (which I'm still waiting for) that I realised there are many others to choose from.

    Just trying to get my head around it all before the modules arrive so I can get stuck in. I've got a couple of projects to use with them. A multiplexed Nixie tube clock and an LED HDD clock. Just want to make sure they keep the correct time. I did make a binary style clock a few years ago using the internal oscillator of a PIC16F690, but it would be several minutes a week out.
     
  10. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    As I read more into this, I think I may go down the road of 'bit banging' as it can be used on any PIC I wish to use, even the 8 pin PIC12F series I also use on a regular basis. I have found this site with some easy to read and understand code:

    http://davbucci.chez-alice.fr/index.php?argument=elettronica/pic_i2c/pic_i2c.inc&language=English

    By looking at the code, to read a particular register in the DS3231 it seems that all that I would need to do is:

    -Reading-
    1 - call the 'i2cstart' routine
    2 - put the DS3231 address into the COM register and call 'i2csend'
    3 - put the register I want to read into the COM register and call 'i2csend'
    4 - then call the 'i2crecieve' routine
    5 - then call either the 'i2csendack' or 'i2cnoack' routine
    6 - call the 'i2cstop' routine

    to write to an address in the DS3231:

    -Writing-
    1 - call the 'i2cstart' routine
    2 - put the DS3231 address into the COM register and call 'i2csend'
    3 - put the register I want to read into the COM register and call 'i2csend'
    4 - put the byte I want to write into the COM register and call 'i2csend'
    5 - call the 'i2cstop' routine

    The DS3231 says that it can be serially read and written, so I assume I can do actions 4 and 5 as many times as needed in 'Reading' and actions 4 as many times as needed in 'Writing'

    Can someone take a look and see if what I have written looks like it should work. I've gone over it a couple of times and I think it looks as though it should.

    Thanks
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    You seem to have the basics of writing to the DS, but reading is more "nuanced" as to read the device you first must write to it.

    So to read you start by sending the slave address, then the register address you will want to read, then sending a stop... then being the read by sending the slave write address followed by receiving the data starting at the register you just previously wrote. It confused me endlessly when I started I2C that a read starts with a write.

    BTW, I love cheap gadgets from China off Ebay. I buy em all the time just to have on hand.
     
  12. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    Oh I see now. I wondered from the datasheet why the address of the byte you wanted to read doesn't get sent when reading.

    So when reading from the device (address 1101000), are these the steps required?

    1 - Send a Start condition followed by the address with a 0 (R/W bit) at the end (11010000)
    2 - Check Ack bit
    3 - Send the address of the register to read (00H) (The seconds register)
    4 - Check Ack bit
    5 - Send the Stop condition
    (the device has been set to be read)

    6 - Send a Start condition followed by the address with a 1 (R/W bit) at the end 11010001
    7 - Check Ack bit
    8 - Now read a byte (should read 00H, the seconds register)
    9 - Send NotAck bit
    10 - Send Stop condition

    By reading the datasheet again, it looks like to read more than 3 bytes, I would Read a byte, send Ack bit, read another byte, send Ack bit, read another byte and then send NotAck bit to end the read, then a Stop condition. So if I put 00H in the initial step 3 (setting the DS3231 pointer) I can then read 3 registers (seconds, minutes and hours) then send the Stop condition.

    Does that sound right?

    Thanks again for your time, I think I'm nearly there.

    Just out of interest, here is the small RTC module I have bought from Hong Kong, how can they produce and sell these so cheap?

    http://www.ebay.co.uk/itm/DS3231-AT...al_Components_Supplies_ET&hash=item5d47118fd3
     
  13. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    Yes you got it now. :D

    How do they sell a $3 part mounted on a board with other devices for $1?

    I would suspect shenanigans, but I have no proof.
     
  14. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I know! The stuff you buy from Hong Kong is usually cheaper (with the shipping) than what you can buy a single component for in the UK. I needed a 5v TORX optical receiver for a DAC I built last year. I think they were about £7 in the UK. Or the same thing from China was £6 for 5 of them with free shipping!!!

    Anyway, back to my project.

    I'm building a Nixie tube clock, and also looking at an LED HDD clock too (I like clocks). I was originally going to set up the PIC to read the RTC and then use a 1 second timer inside the PIC to increment the time and then once every 24 hours, say 2am, read the RTC again in case the PIC has 'wondered'. I was going to do this so I wasn't constantly reading the RTC every second. Then I read on the datasheet that you can set the RTC to output a 1Hz square wave on the SQW pin. So I could use this to poll my clock.

    What's the normal way people use these devices?

    I will have 2 buttons on the back of the clock, increment minutes and increment hours. Each time a button is pressed the minutes, or hours are incremented and the time written to the RTC module.

    Just thought that writing to the DS3231 register that configures the SQW pin would be a good way of testing the comms while I'm playing around with I2C.
     
    Last edited: May 2, 2014
  15. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    If your entire application is a clock you spend most of your time (no pun intended) waiting for the next second. It's not a difficult app. So you can do it any way you wish.

    My preference would be to use the 1Hz pulse in the same way a mechanical clock used a pendulum: when it ticks increment the time, hold till the tock is over. You could keep the time local in memory or read it from the device each second. It is actually easier to read it back, you automatically get minute, hour, day, leap year updates.

    I've hinted several times without response so let me ask you directly: why use assembly? Higher level languages may be had for either free or damn cheap.

    Oh, and as far as clocks, everyone gets the bug and makes one. Here's mine:
    [​IMG]

    Since the PIC used has a built-in clock I would just read my battery backup clock once on power on.
     
  16. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I've just experimented with the interrupt on RA2 of the PIC16F690. I have got it to carry out the interrupt routine on every rising edge of RA2, so I will use the square wave output of the DS3231 as my timebase for the program.

    The reason for programming is assembly language is because that's what I've always done. I like the control you have with exact timing. You know exactly how long each instruction takes etc. It may be a bit old fashion, but that's what I'm used too. Things do take a bit more coding, but you end up with the same result in the end.

    I have also written programs in Objective C 2.0 for the iPhone and years ago made an in car entertainment system with touch screen in VB.net

    Yeah, I was thinking of reading the RTC module on startup and using my own registers in the PIC to store the time. Then the 1Hz square wave will give me the signal to increment the seconds.

    I am still was wondering about when the PIC is first powered and the ports are being setup (the TRIS registers), obviously the SLK and SDA lines on the I2C bus may change state and could accidentally start a transfer to the DS3231. And reading the datasheet, it doesn't 'time out' it will just sit there after it receives a Start signal indefinitely. I suppose I will have to do what it says in the datasheet and toggle the clock until I get a high on the SDA line and then pull the line low to create the start.

    Maybe I should write a START sub routine that checks the state of the SDA line. If it's low, I toggle the SLK until SDA is high, then pull it low. This way at least I know that the next load of bits I send will actually be communicating properly with the DS3231. Does that sound right?
     
    Last edited: May 3, 2014
  17. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    OK. I haven't recieved my DS3231 RTC module yet, but have started a little programming on the PIC16F690. Using the code by Davide Bucci, which I got from here:

    http://davbucci.chez-alice.fr/index.php?argument=elettronica/pic_i2c/pic_i2c.inc&language=English

    I think I have got something that should work.

    All the subs should work as they are the same as Davide's.

    After the program starts, I get it to read the contents of the seconds register and then I write a value to the seconds register in the DS3231.

    If anyone can have a scan through to see if it looks correct I would be most grateful :)

    Code ( (Unknown Language)):
    1. ;-----------------------------------------------------------------------------------------------;
    2. ;        I2C                                                                                     ;
    3. ;        ---                                                                                      ;
    4. ;                                                                                                ;
    5. ;    Author: Craig Smith                                                                            ;
    6. ;    Date:    May 2014                                                                            ;
    7. ;                                                                                               ;
    8. ;   [i2c routines by Davide Bucci (sourced from internet)]                                      ;
    9. ;                                                                                                ;
    10. ;    4MHz internal resonator used                                                                 ;
    11. ;                                                                                                ;
    12. ;   I2C protocol demo to interface with DS3231 RTC module                                       ;
    13. ;                                                                                               ;
    14. ;   RA0 -   Clock signal for RTC module                                                         ;
    15. ;   RA1 -   Data signal for RTC module                                                          ;
    16. ;                                                                                                ;
    17. ;                                                                                               ;
    18. ;   Writing a byte:                                                                             ;
    19. ;   1   - Call i2cStart                                                                         ;
    20. ;   2   - Put DS3231Add into DataReg, rotate left and set bit 0 to 0 (write)                    ;
    21. ;   3   - Call i2cSend                                                                          ;
    22. ;   4   - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    23. ;   5   - Put register to be written into DataReg                                               ;
    24. ;   6   - Call i2cSend                                                                          ;
    25. ;   7   - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    26. ;   8   - Put byte to write into DataReg                                                        ;
    27. ;   9   - Call i2cSend                                                                          ;
    28. ;   10  - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    29. ;   11  - Call i2cStop                                                                          ;
    30. ;   - To send more than 1 byte repeat steps 9 and 10 -                                          ;
    31. ;                                                                                               ;
    32. ;   Reading a byte: (First we write to the DS3231 to set the address of where to read from)     ;
    33. ;   1   - Call i2cStart                                                                         ;
    34. ;   2   - Put DS3231Add into DataReg, rotate left and set bit 0 to 0 (write)                    ;
    35. ;   3   - Call i2cSend                                                                          ;
    36. ;   4   - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    37. ;   5   - Put register to be read into DataReg                                                  ;
    38. ;   6   - Call i2cSend                                                                          ;
    39. ;   7   - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    40. ;   8   - Call i2cStop                                                                          ;
    41. ;   9   - Call i2cStart                                                                         ;
    42. ;   10  - Put DS3231Add into DataReg, rotate left and set bit 0 to 1 (read)                     ;
    43. ;   11  - Call i2cSend                                                                          ;
    44. ;   12  - If W reg is 00 transmition acknoleged, FF = not acknoweged                            ;
    45. ;   13  - Call i2cRead (DataReg now has the contents of the register read from the DS3231       ;
    46. ;   14  - Call i2cNoAck                                                                         ;
    47. ;   15  - Call i2cStop                                                                          ;
    48. ;   - To read more than 1 byte, do 13 then Call i2cAck, then 13, Call i2cAck... after the last  ;
    49. ;     read byte, Call i2cNoAck, then Call i2cStop                                               ;
    50. ;-----------------------------------------------------------------------------------------------;
    51.  
    52.  
    53.  
    54. #include <p16F690.inc>
    55.     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_ON & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
    56.  
    57.  
    58. ; Control lines of the I2C interface
    59.     SCL         equ .0
    60.     SDA         equ .1
    61.     I2CPort     equ PORTA
    62.     I2CTris     equ    TRISA
    63.     DS3231Add   equ b'01101000' ; the address of the DS3231 RTC module
    64.  
    65.  
    66.     udata 0x20
    67.     DataReg     res 1           ; Register to read/write in the DS3231
    68.     Count       res 1           ; counter
    69.     org 0
    70.     goto    Start               ; jump to Start
     
  18. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    Had to split the code as it was too long for one post.....

    Code ( (Unknown Language)):
    1. ;-----------------------------------------------------------------------------------------------;
    2. ; Subroutines are here at the top                                                                ;
    3. ;-----------------------------------------------------------------------------------------------;
    4.  
    5. ;-----------------------------------------------------------------------------------------------;
    6. ; Short Delay                                                                                   ;
    7. ;-----------------------------------------------------------------------------------------------;
    8. ShortDelay:
    9.     nop
    10.     nop
    11.     nop
    12.     nop
    13.     nop
    14.     return
    15.  
    16. ;-----------------------------------------------------------------------------------------------;
    17. ; i2cStart gets everything ready to start sending data to the DS3231                            ;
    18. ;-----------------------------------------------------------------------------------------------;
    19. i2cStart:
    20.     banksel I2CTris
    21.     bcf     I2CTris, SDA        ; SDA as output
    22.     bcf     I2CTris, SCL        ; SCL as output
    23.     banksel I2CPort
    24.  
    25.     bsf     I2CPort, SDA        ; The start condition on the I2C bus
    26.     bsf     I2CPort, SCL        ; An high to low transition when SCL is high
    27.     call    ShortDelay
    28.     bcf     I2CPort, SDA
    29.     call    ShortDelay
    30.     bcf     I2CPort, SCL
    31.     call    ShortDelay          ; Leave SDA and SCL low
    32.     return
    33.  
    34.  
    35. ;-----------------------------------------------------------------------------------------------;
    36. ; i2cStop sets the stop condition on the 2 interface lines                                      ;
    37. ;-----------------------------------------------------------------------------------------------;
    38. i2cStop:
    39.     banksel I2CTris
    40.     bcf     I2CTris, SDA        ; SDA as output
    41.     Banksel I2CPort
    42.     bcf     I2CPort, SCL
    43.     bcf     I2CPort, SDA        ; The stop condition on the bus I2C
    44.     call    ShortDelay
    45.     bsf     I2CPort, SCL        ; A low to high transition when SCL is high
    46.     call    ShortDelay
    47.     bsf     I2CPort, SDA
    48.     call    ShortDelay          ; SCL and SDA lines are left high
    49.     return
    50.  
    51. ;-----------------------------------------------------------------------------------------------;
    52. ; i2cSend send a byte over the i2c lines                                                        ;
    53. ;-----------------------------------------------------------------------------------------------;
    54. i2cSend:
    55.     movwf   DataReg             ; return 0x00 if ACK
    56.     movlw   0x08
    57.     movwf   Count
    58.     banksel I2CTris
    59.     bcf     I2CTris, SDA        ; SDA as output
    60.     Banksel I2CPort
    61.  
    62. i2cSendLoop:
    63.     bcf     I2CPort, SCL        ; Clock low: change of SDA allowed
    64.     rlf     DataReg,f
    65.     bcf     I2CPort, SDA
    66.     btfsc   STATUS, C           ; Test the carry bit
    67.     bsf     I2CPort, SDA
    68.     call    ShortDelay
    69.     bsf     I2CPort, SCL        ; Clock high
    70.     call    ShortDelay
    71.     decfsz  Count,f
    72.     goto    i2cSendLoop
    73.  
    74. i2cWaitAck:
    75.     bcf     I2CPort, SCL        ; Clock low
    76.     bsf     I2CPort, SDA
    77.     banksel I2CTris
    78.     bsf     I2CTris, SDA        ; SDA as input
    79.     banksel I2CPort
    80.     call    ShortDelay
    81.     bsf     I2CPort, SCL        ; Clock high
    82.     call    ShortDelay
    83.     movlw   0x00                ; Ox00 in w means ack
    84.     btfsc   I2CPort, SDA        ; SDA low means ack
    85.     movlw   0xFF                ; 0xFF in w means no ack
    86.     Banksel I2CTris
    87.     bcf     I2CTris, SDA        ; SDA as output
    88.     banksel I2CPort             ; Clock is left low
    89.     bcf     I2CPort, SCL
    90.     call    ShortDelay
    91.     return
    92.  
    93. ;-----------------------------------------------------------------------------------------------;
    94. ; i2cRead reads a byte over the i2c lines                                                       ;
    95. ;-----------------------------------------------------------------------------------------------;
    96. i2cRead:
    97.     clrf    DataReg             ; Read a byte over the I2C interface
    98.     movlw   0x08
    99.     movwf   Count
    100.     banksel I2CTris
    101.     bsf     I2CTris, SDA        ; SDA as input
    102.     banksel I2CPort
    103.  
    104. i2cReadLoop:
    105.     bcf     I2CPort, SCL        ; Clock low: change of SDA allowed
    106.     call    ShortDelay
    107.     bsf     I2CPort, SCL        ; Clock high
    108.     call    ShortDelay
    109.     bcf     STATUS, C           ; Clear the carry
    110.     rlf     DataReg,f
    111.     btfsc   I2CPort, SDA        ; Test the bit being received
    112.     bsf     DataReg,0           ; Stock the bit read in DataReg and rotate
    113.     decfsz  Count,f
    114.     goto    i2cReadLoop
    115.     movf    DataReg,w
    116.     bcf     I2CPort, SCL        ; Clock is left low
    117.     call    ShortDelay
    118.     return
    119.  
    120. ;-----------------------------------------------------------------------------------------------;
    121. ; i2cSendAck sends an acknowledge bit                                                           ;
    122. ;-----------------------------------------------------------------------------------------------;
    123. i2cSendAck:
    124.     banksel I2CTris
    125.     bcf     I2CTris, SDA        ; SDA as output
    126.     banksel I2CPort
    127.     bcf     I2CPort, SCL        ; Clock low: change of SDA allowed
    128.     call    ShortDelay
    129.     bcf     I2CPort, SDA        ; SDA low means ack
    130.     call    ShortDelay
    131.     bsf     I2CPort, SCL        ; Clock high
    132.     call    ShortDelay
    133.     bcf     I2CPort, SCL        ; Clock is left low
    134.     return
    135.  
    136. ;-----------------------------------------------------------------------------------------------;
    137. ; i2cNoAck sends a No acknowledge bit                                                           ;
    138. ;-----------------------------------------------------------------------------------------------;
    139. i2cNoAck:
    140.     banksel I2CTris
    141.     bcf     I2CTris, SDA        ; SDA as output
    142.     banksel I2CPort
    143.     bcf     I2CPort, SCL        ; Clock low: change of SDA allowed
    144.     call    ShortDelay
    145.     bsf     I2CPort, SDA        ; SDA high means no ack
    146.     call    ShortDelay
    147.     bsf     I2CPort, SCL        ; Clock high
    148.     call    ShortDelay
    149.     bcf     I2CPort, SCL
    150.     return                      ; Clock is left low
    151.  
    152.  
    153.  
    154. ;-----------------------------------------------------------------------------------------------;
    155. ; Main program starts here                                                                      ;
    156. ;-----------------------------------------------------------------------------------------------;
    157. Start:
    158.     banksel ANSEL
    159.     clrf    ANSEL                ; select Digital I/O on port C
    160.     clrf    ANSELH                ; select Digital I/O on port B
    161.  
    162.     banksel OSCCON
    163.     bsf     OSCCON,6
    164.     bsf     OSCCON,5
    165.     bcf     OSCCON,4            ; 4Mhz clock
    166.  
    167.     banksel TRISA
    168.     clrf    TRISA
    169.     clrf    TRISB
    170.     clrf    TRISC               ; all ports outputs
    171.  
    172.     banksel 0
    173.  
    174.  
    175. ReadSeconds:
    176.     call    i2cStart
    177.     movlw   DS3231Add           ; put DS3231 address into DataReg
    178.     movwf   DataReg
    179.     rlf     DataReg
    180.     bcf     DataReg,0           ; set bit 0 to a 0 (write)
    181.  
    182.     call    i2cSend
    183.  
    184.     ; could do something with w regarding acknowledge
    185.  
    186.     movlw   .0
    187.     movwf   DataReg             ; put DS3231 Seconds register into DataReg (address is 0)
    188.     call    i2cSend
    189.  
    190.     ; could do something with w regarding acknowledge
    191.  
    192.     call    i2cStop
    193.  
    194.     call    i2cStart
    195.  
    196.     movlw   DS3231Add           ; put DS3231 address into DataReg
    197.     movwf   DataReg
    198.     rlf     DataReg
    199.     bsf     DataReg,0           ; set bit 0 to a 0 (read)
    200.  
    201.     call    i2cSend
    202.  
    203.     ; could do something with w regarding acknowledge
    204.  
    205.     call    i2cReceive          ; DataReg now contains the value in the Seconds register in the DS3231
    206.  
    207.     call    i2cNoAck
    208.  
    209.     call    i2cStop
    210.  
    211.     ;------------------------------------------------;
    212.     ; do something with the data held in the DataReg ;
    213.     ;------------------------------------------------;
    214.  
    215.  
    216.  
    217.  
    218. WriteSeconds:
    219.     call    i2cStart
    220.     movlw   DS3231Add           ; put DS3231 address into DataReg
    221.     movwf   DataReg
    222.     rlf     DataReg
    223.     bcf     DataReg,0           ; set bit 0 to a 0 (write)
    224.  
    225.     call    i2cSend
    226.  
    227.     ; could do something with w regarding acknowledge
    228.  
    229.     movlw   .0
    230.     movwf   DataReg             ; put DS3231 Seconds register into DataReg (address is 0)
    231.     call    i2cSend
    232.  
    233.     ; could do something with w regarding acknowledge
    234.  
    235.     movlw   b'00010011'         ; value to send to the DS3231 Seconds register
    236.     movwf   DataReg
    237.     call    i2cSend
    238.  
    239.     ; could do something with w regarding acknowledge
    240.  
    241.     call    i2cStop
    242.  
    243.     ;-------------------------------------------------;
    244.     ; DS3231 Seconds register should contain 00010011 ;
    245.     ;-------------------------------------------------;
    246.  
    247.  
    248. end
    [/CODE]
     
    cristobalmunoz likes this.
  19. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    Sorry, but I absolutely refuse to read assembly code except for the rare occasions I've written some.
     
  20. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    OK. No problem. I'll wait till I get the RTC module and experiment.

    I have an old scope, so if I increase the delay for the clock pulses I should be able to see what is going on.
     
Loading...