Troubles with I2C_Write


Closed Thread
Results 1 to 11 of 11
  1. #1
    Join Date
    Aug 2009
    Posts
    13

    Default Troubles with I2C_Write

    I'm trying to send an I2C message to a non-EEPROM. Now everyone may laugh and say "So what's the problem?"
    Every I2C example I've seen written is for EEPROMs. The I2C_WRITE command seems built around them.

    The complicating part is the EEPROM address BYTE. That may seem odd, but I have a good reason. I'm not sending an address byte. I'm just sending pure data. In this case, I'm sending it to an I2C-driven DAC.

    Right now, I'm using this method and nothing is working.

    'Assuming 'result' is a word variable containing a 10-BIT value shifted left twice with 4 bits of empty header (per the DAC datasheet):
    'So it looks like 0000xxxx-xxxxxx00

    I2CWRITE PORTB.1, PORTB.4, $9C, result.HIGHBYTE, [result.LOWBYTE]

    I'm using PBP 2.5, an ICD2, a PIC16F819, and a DAC101C085.

    Any suggestions?

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Here is an example with a RTC
    http://www.picbasic.co.uk/forum/showthread.php?t=12671

    But the problem might be with the placement of the [ ]

    Showing your whole code may also help. Where is the data coming from?
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    In the manual, there are small clues that take some getting used to.

    I2CWRITE DataPin,ClockPin,Control,{Address,}[Value{,Value...}]{,Label}

    The curly braces around Address means it's optional.

    If you don't need to send an address, leave it out.
    Then put the HIGHBYTE data inside the square brackets.
    <br>
    Last edited by Darrel Taylor; - 22nd March 2010 at 04:39.
    DT

  4. #4
    Join Date
    Aug 2009
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    This is a trimmed down version of my code. And frankly, nothing is working. I'm not a hardware guy, so I can't tell if my setup is wired wrong. The guy I work with put it together for me. He's a professional so I'm not going to doubt him. But something, somewhere, isn't working.

    Code:
    ;@   __CONFIG    _HS_OSC & _WDT_OFF
    
    DEFINE  OSC 20
    DEFINE	ADC_BITS	10			'10-bit ADC
    DEFINE	I2C_SLOW		1
    
    ' Define used register flags
    SSPIF   VAR     PIR1.3          ' SSP (I2C) interrupt flag
    BF      VAR     SSPSTAT.0       ' SSP (I2C) Buffer Full
    R_W     VAR     SSPSTAT.2       ' SSP (I2C) Read/Write
    D_A     VAR     SSPSTAT.5       ' SSP (I2C) Data/Address
    CKP     VAR     SSPCON.4        ' SSP (I2C) SCK Release Control
    SSPEN   VAR     SSPCON.5        ' SSP (I2C) Enable
    SSPOV   VAR     SSPCON.6        ' SSP (I2C) Receive Overflow Indicator
    WCOL    VAR     SSPCON.7        ' SSP (I2C) Write Collision Detect
    ADCGO	VAR		ADCON0.2 		' ADC GO /DONE bit: High to start. Automatically goes low when finished.
    
    
    ' Define constants
    I2Caddress	CON	$12 * 2			' Make our address twice the actual address (bit shifted left)
    BUFFERSIZE	CON	$10				' 16 Word addresses
    BUFFERTOP	CON  BUFFERSIZE - 1	' Top of Buffer
    DATASIZE	CON	20
    
    
    ' Allocate RAM
    modLevel	VAR		WORD[BUFFERSIZE]' Modulation Level                      '32
    dataout		VAR     BYTE[2]			' Data out array                        '18
    result		VAR		WORD			' ADC result                            '2
    Counter     VAR		BYTE			' Counter for Arrays                    '1
    Iter    	VAR		BYTE			' Generic Iterator						'1
    compHi		VAR		WORD            ' Comparison Hi Value                   '2
    compLo		VAR		WORD            ' Comparison Lo Value                   '2
    TempWord	VAR		WORD			' Swap Variable
    
    
    
    ' Initialize ports and directions
    		ADCON0 = $81			' Clock /32
            ADCON1 = $81			' PORTA.0 analog
    '        TRISB.1 = 1				' Pin for SDA
    '        TRISB.4 = 1				' Pin for SCL
            TRISB.1 = 0				' Pin for SDA
            TRISB.4 = 0				' Pin for SCL
    		
            TRISA.2	= 1				' Pin RA.2 for AN2
    		TRISA.3	= 0
    		TRISA.4	= 0
    
    mainloop:						' Main program loop
    '/////////////////////////////////////////////////////////////////////////////
    'This is the portion I'm testing out
    '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    		result =	512
    		result = result << 2
    		I2CWRITE PORTB.1, PORTB.4, $9C, [result.HIGHBYTE, result.LOWBYTE]	
    
    
    
    loopforfun:
    	GOTO	loopforfun
    '//////////////////////////////////////////////////////////////////////////////

  5. #5
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    You say nothing is working. Is there a LED on board that can be made to blink to see if the chip is even running?

    This line bothers me
    Code:
    ;@   __CONFIG    _HS_OSC & _WDT_OFF
    I take it you are using the default in the inc file?
    Dave
    Always wear safety glasses while programming.

  6. #6
    Join Date
    Aug 2009
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    Actually, that's something I had not considered.
    Let me go do some research, and I'll get back with an answer to that.

  7. #7
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by The Altruist View Post
    And frankly, nothing is working. I'm not a hardware guy, so I can't tell if my setup is wired wrong. The guy I work with put it together for me. He's a professional so I'm not going to doubt him. But something, somewhere, isn't working.
    Since someone else built the hardware for you, check and make sure that there is a resistor to pull MCLR high.

    I just wasted a big chunk of my weekend trying to figure out what configuration fuses and register(s) weren't configured right on a "new to me" chip.
    Turned out I forgot to pull MCLR high, so the chip wasn't running at all.



    steve

  8. #8


    Did you find this post helpful? Yes | No

    Default

    Do you have appropriate pullup resistors on the I2C clock and data lines ?
    I have seen values from 1.2k to 10k work to good effect. The lower the value the less susceptible the signals are to noise

  9. #9
    Join Date
    Aug 2009
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    Hm.... false alarm. The DAC chip was bad.
    We have it (or at least a simple saw tooth wave demo) working now:
    Code:
    ;@   __CONFIG    _HS_OSC & _WDT_OFF
    
    DEFINE  OSC 20
    DEFINE	I2C_SLOW		1
    
    
    
    
    ' Allocate RAM
    result		VAR		WORD			' ADC result                            '2
    Iter    	VAR		BYTE			' Generic Iterator						'1
    
    
    ' Initialize ports and directions
            TRISB.1 = 0				' Pin for SDA
            TRISB.4 = 0				' Pin for SCL
    		
    
    mainloop:						' Main program loop
    		'This should set the DAC to output.
    		FOR ITER =0 TO 254
    		result = ITER
    		result=result<<4
    		PAUSE	100
    		I2CWRITE PORTB.1, PORTB.4, $9C, [result.HIGHBYTE, result.LOWBYTE]
    		NEXT
    		FOR ITER =255 TO 1 STEP -1
    		result = ITER
    		result=result<<4
    		PAUSE	100
    		I2CWRITE PORTB.1, PORTB.4, $9C, [result.HIGHBYTE, result.LOWBYTE]
    		NEXT
    		goto mainloop

  10. #10
    Join Date
    Aug 2009
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    While I have your attention, I'm puzzling over how to efficiently do a 10-bit by 10-bit division (which will yield a value 0<x<1) then multiply it again by 1023 to get a number (0<=x<=1023). I'd prefer not to use LONG values as they eat up precious RAM, but I also want to keep it reasonably quick. I have plenty of words set up, but no LONGs.
    Here's the math:
    a, b, and x are WORDs
    x=1023*(a-b)/(a+b)
    Any thoughts?
    EDIT: Oh. Ha ha. I don't even have LONGs to work with. Yeah... that makes a difference now, doesn't it?
    The only thing I can conceive of is using a two-fold mechanism that combines this:
    Code:
    'Shift RESULT left 10 times
    FOR Iter=1 to 10
    	RESULT=RESULT<<1
    NEXT
    with this:
    Code:
    'RESULT= B / A
    RESULT=0
    WHILE B>A
    	B=B-A
    	RESULT=RESULT+1
    WEND
    The trick is to keep the working value inside 16-bits, but inside 10 bits at the very end.
    Last edited by The Altruist; - 23rd March 2010 at 02:23.

  11. #11
    Join Date
    Aug 2009
    Posts
    13


    Did you find this post helpful? Yes | No

    Default

    For those of you wondering, this algorithm gives decently accurate 10-bit ratios with a Big O of (n^2). I hope some one finds it useful.
    Bear in mind that the Numerator MUST be smaller than the Denominator, and that the denominator bit-shifted left to be bigger than the Power of 2 you're trying to fit it in. Therefore, don't change the 1024 to 16384 and expect it to work (while still using 16-bit WORDs).

    Code:
    TenBitRatio:
    		Result=0
    		while Denominator<1024 
    			Numerator=Numerator<<1
    			Denominator=Denominator<<1
    		WEND
    		while	Denominator>0
    			Digit=0
    			while	Numerator>Denominator
    				Numerator	=	Numerator	-	Denominator
    				Digit=Digit+1
    			WEND
    			Denominator	=	Denominator>>1
    			Result	=	Result	<<	1
    			Result	=	Result	+	Digit
    		WEND
    Last edited by The Altruist; - 23rd March 2010 at 23:59.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

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