​ ​ ​ ​ Bit banging i2c on 08M - Page 2
Page 2 of 4 FirstFirst 1 2 3 4 LastLast
Results 11 to 20 of 31

Thread: Bit banging i2c on 08M

  1. #11
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    This is the only way I could think of reading in one packet
    Code:
    Main:
     gosub Read_Time
      secs  = BcdToDec( secs  )		  
      mins  = BcdToDec( mins  )
      hours = BcdToDec( hours )
      date  = BcdToDec( date  )
      month = BcdToDec( month )
      year  = BcdToDec( year  ) 	 		
     sertxd ("----Start----",cr,lf)	
     sertxd ("b9=secs = ",#secs,cr,lf)
     sertxd ("b10=mins = ",#mins,cr,lf) 
     sertxd ("b11=hours = ",#hours,cr,lf) 
     sertxd ("b12=day = ",#day,cr,lf) 
     sertxd ("b13=date = ",#date,cr,lf) 
     sertxd ("b14=month = ",#month,cr,lf) 
     sertxd ("b15=year = ",#year,cr,lf)
     sertxd ("----End----",cr,lf)
      pause 10000
    Goto Main 
    
    		  
    Read_Time: Bptr = 9 
    For i2cAdr = $00 to $06
            Gosub I2cSendHeader
            Gosub I2cStart
            i2cDataByte = I2C_ADDRESS | $01
            Gosub I2cSendByte
            Input SDA                       ; SDA = 1 / Tri-State SDA
            For i2cBitCount = 0 To 7
              Gosub I2cStrobeScl		    
              i2cVal= i2cVal * 2 | i2cAckBit
            Next
      @bptrinc = i2cVal
    InitI2cDevice:
            Low SCL                         ; SCL = 0
            Low SDA                         ; SDA = 0
            Input SCL                       ; SCL = 1
            Input SDA                       ; SDA = 1
    Next   
            Return
    Theres probably a better way ..but its all I can think of right now
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  2. #12
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    24,373

    Default

    That is still reading each byte at a time. You need to perform a single multi-byte read rather than multiple single byte reads.

    There may be an example of bit-banged multi-byte read on the forum or you will have to look at the I2C specification and follow the sequence of start and stop bits, sending and reading bytes. The existing code can be used as a basis but needs to be changed.

  3. #13
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    Quote Originally Posted by hippy
    You need to perform a single multi-byte read rather than multiple single byte reads
    Now that is going over my head...although I will try but I am getting confused (sadly don't take much)
    Code:
            For i2cBitCount = 0 To 7
              Gosub I2cStrobeScl		    
              i2cVal= i2cVal * 2 | i2cAckBit
            Next
    because each byte needs to have 0 to 7 in order to read during a specific time
    I am learning tho ....well.....tiny bit
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  4. #14
    Senior Member
    Join Date
    Feb 2012
    Location
    London
    Posts
    2,886

    Default

    Hi,

    I think the aim is to send only one start sequence (and Slave address) and then read all 7 bytes quickly in sequence. That probably needs the For i2cAdr = $00 to $06 to be moved to immediately before the For i2cBitCount = 0 To 7 (but you may need to initaialise.i2cAdr in the original position for the unshown subroutine to work correctly). The corresponding next then needs to be located at least after the @bptrinc = i2cVal , but I'm not sure how much further down.... The program appears to "fall into" the InitI2cDevice: routine , which is a "trick" I often use myself,, but I do usually include a comment that it's supposed to happen.

    However, I think we can assume that the fall through is intended to happen because the code is very similar to that suggested by Technical in post #2 of this thread. As you may see from that thread, my preference was to use the hardware I2C and find an "alternative" solution to a pin conflict, so I've never actually tried that code.

    Cheers, Alan.

  5. #15
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    Thanks Allycat
    I am breaking down the code bit by bit so I can try to understand correctly ...
    Quote Originally Posted by Allycat
    That probably needs the For i2cAdr = $00 to $06 to be moved to immediately before the For i2cBitCount = 0 To 7 (but you may need to initaialise.i2cAdr in the original position for the unshown subroutine to work correctly). The corresponding next then needs to be located at least after the @bptrinc = i2cVal
    I will do some tests on how that might be done
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  6. #16
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    While I am doing my slow homework and studying the DS3231 datasheet I found here

    https://www.openimpulse.com/blog/wp-...-Datasheet.pdf
    I thought this might be interesting ..if I am reading it right ...on page 11 it states
    Figure 1 shows the address map for the DS3231 timekeeping
    registers. During a multibyte access, when the
    address pointer reaches the end of the register space
    (12h), it wraps around to location 00h. On an I2C
    START or address pointer incrementing to location 00h,
    the current time is transferred to a second set of registers.
    The time information is read from these secondary
    registers, while the clock may continue to run. This
    eliminates the need to reread the registers in case the
    main registers update during a read.
    Of course I still have to get the code to read a single multi-byte read...but thought maybe
    its impossible to get a misreading when the DS3231 updates ...its just my thought
    or do I have the page upside down


    UPDATE:
    I made the code line by line (with no gosubs) to make it easier to follow
    and 8hrs later I'm still missing something...I know it can be done ...but I have to understand a whole lot more
    btw
    Code:
     
            For i2cBitCount = 0 TO 7
              If i2cDataByte < $80 Then
                Low SDA                     ; SDA = 0
              Else
                Input SDA                   ; SDA = 1
              End If
              Gosub I2cStrobeScl
              i2cDataByte = i2cDataByte * 2
            Next
    is pure genius
    Last edited by newplumber; 15-04-2018 at 07:45.
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  7. #17
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    Hi
    on page 15 on the DS3231 data sheet (post #16)
    in the bottom right hand corner
    it states
    Acknowledge: Each receiving device, when
    addressed, is obliged to generate an acknowledge
    after the reception of each byte. The master device
    must generate an extra clock pulse, which is associated
    with this acknowledge bit.
    but the code is working as
    Acknowledging each BIT this is where i am frooze up
    because if I use
    Code:
    I2C_Send_Byte:      
       For i2cBitCount = 0 TO 7
           If i2cDataByte < $80 Then
            Low SDA                     ; SDA = 0
           Else
            Input SDA                   ; SDA = 1
          End If
                Input SCL                       ; SCL = 1
                 Do
                 Loop Until SCL_PIN = 1
            i2cAckBit = SDA_PIN
                Low SCL                         ; SCL = 0            
         i2cDataByte = i2cDataByte * 2             
       Next     
        Input SDA       
    Return
    it seems to me its acknowledging each bit
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  8. #18
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    24,373

    Default

    Quote Originally Posted by newplumber View Post
    if I use ...
    That's sending each of the 8 data bits but it's not reading the ACK after those 8 bits. At the end you need to make SDA an input so it floats high, then clock out an SCL pulse.

    The full sequence to read the data should be similar to this, untested -

    Code:
                            Gosub SendStartBit
    i2cDataByte = $D0 | 0 : Gosub SendByteAndReadAck                      ; Write to device $D0
    i2cDataByte = $00     : Gosub SendByteAndReadAck                      ; Set address to $00
                            Gosub SendStopBit
    
                            Gosub SendStartBit
    i2cDataByte = $D0 | 1 : Gosub SendByteAndReadAck                      ; Read from device $D0
                            Gosub ReadByteAndSendAck : secs = i2cDataByte ; Read location $00
                              :                                                            :
                            Gosub ReadByteAndSendAck : year = i2cDataByte ; Read location $06
                            Gosub SendStopBit
    Code:
    SendByteAndReadAck:      
      For i2cBitCount = 0 TO 7
        If i2cDataByte < $80 Then
          Low SDA                                ; SDA = 0
        Else
          Input SDA                              ; SDA = 1
        End If
        Input SCL                                ; SCL = 1
        Do : Loop Until SCL_PIN = 1
        Low SCL                                  ; SCL = 0            
        i2cDataByte = i2cDataByte * 2             
      Next     
      Input SDA
      Input SCL                                  ; SCL = 1
      Do : Loop Until SCL_PIN = 1
      i2cAckBit = SDA_PIN
      Low SCL                                    ; SCL = 0            
      Return
    Code:
    ReadByteAndSendAck:
      Input SDA      
      For i2cBitCount = 0 TO 7
        Input SCL                                ; SCL = 1
        Do : Loop Until SCL_PIN = 1
        i2cDataByte = i2cDataByte * 2 | SDA_PIN            
        Low SCL                                  ; SCL = 0            
      Next     
      Input SCL                                  ; SCL = 1
      Do : Loop Until SCL_PIN = 1
      Low SCL                                    ; SCL = 0            
      Return
    Last edited by hippy; 16-04-2018 at 20:15. Reason: Added extra clock-stretch handling

  9. #19
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    Quote Originally Posted by hippy View Post
    That's sending each of the 8 data bits but it's not reading the ACK after those 8 bits. At the end you need to make SDA an input so it floats high, then clock out an SCL pulse.
    Thanks Hippy ...I will look into that example ....you might of saved me 2 weeks
    I see/read how the sequence is to send/receive to the DS3231 but how to send bytes from M(master) to S (slave) is confusing for me
    so in a example your do/loop until

    Code:
      
    SendByteAndReadAck:      
      For i2cBitCount = 0 TO 7
        If i2cDataByte < $80 Then
          Low SDA                                ; SDA = 0
        Else
          Input SDA                              ; SDA = 1
        End If
        Input SCL                                ; SCL = 1
        Do : Loop Until SCL_PIN = 1
    For me it means its (do/loop) waiting for the DS3231 to send SCL high and that means its ready for the next bit?
    but it is not the end of the "byte" "acknowledge bit" as shown in the data sheet? ...hopefully I make sense
    programming a picaxe is some what like playing chess....and I'm horrible at chess

  10. #20
    Senior Member
    Join Date
    Apr 2013
    Location
    north dakota
    Posts
    483
    Blog Entries
    2

    Default

    Its a sweet example Hippy ...but for some reason its stuck on reading seconds only like showing
    "terminal"
    start sertxd
    b9=secs = 23
    b10=mins = 165
    b11=hours = 165
    b12=day = 255
    b13=date = 165
    b14=month = 165
    b15=year = 165
    end sertxd

    start sertxd
    b9=secs = 26
    b10=mins = 165
    b11=hours = 165
    b12=day = 255
    b13=date = 165
    b14=month = 165
    b15=year = 165
    end sertxd
    Code:
     
    Main:				
    				
    				    Gosub I2C_Start
    i2cDataByte = I2C_ADR | 0 : Gosub SendByteAndReadAck                      ; Write to device $D0
    i2cDataByte = $00         : Gosub SendByteAndReadAck                      ; Set address to $00
                                Gosub I2C_Stop
    
                                Gosub I2C_Start
    i2cDataByte = I2C_ADR | 1 : Gosub SendByteAndReadAck                      ; Read from device $D0
                                Gosub ReadByteAndSendAck : secs   = i2cDataByte ; Read location $00
                                Gosub ReadByteAndSendAck : mins   = i2cDataByte ; Read location $01
    				    Gosub ReadByteAndSendAck : hours  = i2cDataByte ; Read location $02
    				    Gosub ReadByteAndSendAck : day    = i2cDataByte ; Read location $03
    				    Gosub ReadByteAndSendAck : date   = i2cDataByte ; Read location $04
    				    Gosub ReadByteAndSendAck : month  = i2cDataByte ; Read location $05
    				    Gosub ReadByteAndSendAck : year   = i2cDataByte ; Read location $06				    
                                Gosub I2C_Stop				
    			          gosub Sertxd_Time                       'sertxd out all 6 bytes of data recieved by ds3231
    Goto Main
    Its been this kind of problem 36 hrs ago ...and my simple brain can only read it with resending the data address
    which in turn is not a single multi-byte read ...maybe i am missing the Ack after the
    Gosub ReadByteAndSendAck : secs = i2cDataByte ; Read location $00
    Code:
      
    Main:				
    				
    				    Gosub I2C_Start
    i2cDataByte = I2C_ADR | 0 : Gosub SendByteAndReadAck                      ; Write to device $D0
    
    
    i2cDataByte = $00         : Gosub SendByteAndReadAck                      ; Set address to $00
                                Gosub I2C_Stop
    
                                Gosub I2C_Start
    i2cDataByte = I2C_ADR | 1 : Gosub SendByteAndReadAck                      ; Read from device $D0
                                Gosub ReadByteAndSendAck : secs   = i2cDataByte ; Read location $00
    i2cDataByte = $00         : Gosub SendByteAndReadAck                      ; Set address to $00
                                Gosub I2C_Stop
    
                                Gosub I2C_Start
    i2cDataByte = I2C_ADR | 1 : Gosub SendByteAndReadAck                      ; Read from device $D0
                                Gosub ReadByteAndSendAck : mins  = i2cDataByte ; Read location $00
           				    
                                Gosub I2C_Stop				
    			          gosub Sertxd_Time                       'sertxd out all 6 bytes of data recieved by ds3231
    Goto Main
    But always I am having fun learning how the bits are biting
    programming a picaxe is some what like playing chess....and I'm horrible at chess

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •