CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Odd spike in I2C data pulse. Nofloat_high not doing its job?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

Odd spike in I2C data pulse. Nofloat_high not doing its job?
PostPosted: Sun Oct 04, 2009 12:16 pm     Reply with quote

Update: Problem solved, apparently. As per recommendations here, I dropped the value of the pullup resistors, and dropped the nofloat_high. Once that was done, the odd 0.48V bumps disappeared, as did the spikes, and all the data pulses were still reasonably squared-up.



Hello all,
I'm using a PIC18F4520 to serve as a sort of clock/calendar timeserver along with a DS3231 realtime-clock, which uses I²C for communication.

It does communicate normally with the PIC, except I do sometimes get odd lockups in the PIC, which even the watchdog timer is unable to handle. The LCD (the usual Hitachi-based 16x2 display I see used commonly) becomes corrupted when these lockups occur, and a hard-reset is required. (This may well be worthy of a thread by itself.)


Anyway, I don't know if this is the cause, but it's still something I'm investigating: I get an odd spike in voltage when I'm writing the DS3231's address to the chip, using the built-in i2cwrite() feature.
The oscilloscope I have to work with has no image export function that I know of, so you'll have to put up with sketches for now. Embarassed

Here is a sketch of the entire pulse (SDA line). The black pulse shows what I get when I do not have nofloat_high within the #use i2c section.
The red pulse is what I get when I do use it. Note the sudden spike at the end there.



Here's a closeup of the spike itself. You can see that it is very short in duration, only 104nS, but it does manage to work itself all the way up to 2.480V.



Here's what I'm using for the #use section:
Code:
#use i2c(Master,fast=400000,sda=PIN_C4,scl=PIN_C3,nofloat_high)


I get the spike just the same if I use "fast=100000" or "slow" for the speed, though it is scaled up proportionately in duration as the duration of the accompanying data pulse increases. I opted for quicker speeds simply to speed up the time spent in my I²C sections. With "slow" (or possibly "slow=40000") as the speed, the entire reading of the clock data takes 2500µS. With "fast=400000," it takes only 340µS.


So then, the questions:
1) With nofloat_high enabled, why does it still manage to get up to 0.480V?

2) What's with that spike at the end? Is the compiler, and therefore PIC, not forcing the pin to 0V for the full length of the data pulse due to a bug?

3) Can such a short spike be interpreted as data by the PIC, and thus possibly cause problems?

4) Please don't tell me I need to write my own I²C read/write functions.Sad

(And....forgive me, but nofloat_high is defined as "Does not allow signals to float high, signals are driven from low to high." What exactly does that mean? Without it enabled, it does look like the signal floats up to 3.3V, but with it enabled, it looks like the signal moves rapidly to 3.3V - ie, it is "driven" there. Perhaps I'm looking at it wrong?)


Other info that might be helpful or needed:
- Both the PIC and DS3231 are running off of the same 3.3V line.
- The traces for the SDA and SCL lines are quite short, easily less than an inch.
- Pullup resistor value for anything on the board that needs them is 10k.
- CCS Compiler v4.062


Last edited by Jeff7 on Wed Oct 07, 2009 10:55 am; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 1:14 pm     Reply with quote

Post a short test program that will allow us to try to duplicate the problem.
I mean a really, really short program. Something like this:
Code:

#include <18F4520.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)

#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
//======================================
void main(void)
{

while(1)
  {
   i2c_write(0x55);
   delay_us(100);
  }

}

The shorter the program is, the easier it will be for us to help you.
Put in your fuses, and your clock speed, etc. Test it and verify that
you see the failure, and post it.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 2:06 pm     Reply with quote

I think, you didn't tell at all, which signal is shown in your sketched waveform. Is it SDA? If so, what's the green trace?

Quote:
Pullup resistor value for anything on the board that needs them is 10k
The slow rising black trace seems to suggest, that there's no sufficient pullup on this line (SDA?).
Ttelmah
Guest







PostPosted: Sun Oct 04, 2009 2:55 pm     Reply with quote

The 'no_float_high' spec, sets up the code to momentarily drive the sgnal 'high', when it transitions, to improve the rising edge. The key though is the word _momentarily_. You still should provide standard I2C pullups on the lines. For a 3.3v bus, at 100K, with no series resistors, the _maximum_ value of the pullup resistors specified, is just over 3KR. The minimum, is just on 1KR.
The lines do not look to be being driven high properly at all...
Remember the low level drive is only specified as 0.6v. Nothing lower is needed.

Best Wishes
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 3:11 pm     Reply with quote

It's SDA, and just one bit of the data that's being sent.
The SCL line looks about like you'd expect - just series of evenly-spaced pulses during the time between i2c_start and i2c_stop.

In this particular section, I'm performing this simplified code:

Code:

   #define i2c_address  0xD0


   i2c_start();
   i2c_write(i2c_address);
   i2c_stop();


That's pretty much it.



The SDA line has a 10k pullup resistor, connected to 3.3V on the other side. The DS3231 datasheet gives this equation for calculating the pullup resistor: RPU = tR/CB
However, no units are specified for this equation. Do I use the base units of ohms, seconds, and farads?
Doing it that way, I use 300nS and 400pF (pg 4 of the datasheet).
....huh, and this time I get a value of only 750 ohms. The last time I did it, I think it was more like 75k. So I guess I should try out a much much much lower pullup resistor then, and go without nofloat_high?
Also, the datasheet says that tR ranges from 20+0.1CB, but again it gives no units, and (20+0.1CB) would seem to give units in farads, not seconds - unless there's some unit reduction going on in that 0.1 "constant").


The green lines simply indicate the point on the gently-sloping curve where the red line jumps to 0.48V.

That is to say, with nofloat_high enabled, the SDA line jumps to 0.48V when, without nofloat_high enabled, it would be reaching 1.5V. At that point, it's almost like the line wants to go high to 3.3V, but is being kept low by nofloat_high, right up until that brief peak at the end.


My #FUSES page:
Code:

#include "18F4520.h"
#device adc=10

#FUSES WDT                      //Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV25                   //Brownout reset at 2.5V
#FUSES MCLR                     //Master Clear pin enabled
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection

#use delay(clock=20000000,RESTART_WDT) // Clock = 20000000, for 20MHz.

// DS3231's I2C declaration
#use i2c(Master,fast=400000,sda=PIN_C4,scl=PIN_C3,nofloat_high)//force_hw)





Ttelmah wrote:
The 'no_float_high' spec, sets up the code to momentarily drive the signal 'high', when it transitions, to improve the rising edge. The key though is the word _momentarily_. You still should provide standard I2C pullups on the lines. For a 3.3v bus, at 100K, with no series resistors, the _maximum_ value of the pullup resistors specified, is just over 3KR. The minimum, is just on 1KR.
The lines do not look to be being driven high properly at all...
Remember the low level drive is only specified as 0.6v. Nothing lower is needed.

Best Wishes

I think I see now - instead of the signal going slowly towards 3.3V, when the PIC senses a rise, it forcibly drives the line to 3.3V in a darn hurry - and mine is only giving a sloping rising edge because the pullup resistor's value is way too high.


The one thing that sucks about thinking about work on weekends: You can't do anything about it until the weekday. Shocked


Last edited by Jeff7 on Sun Oct 04, 2009 3:26 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 3:24 pm     Reply with quote

Quote:

#FUSES WDT //Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES DEBUG //No Debug mode for ICD
#FUSES LVP //No low voltage prgming, B3(PIC16

I would have preferred that you post a complete test program, and not
code fragments. Comments on what you did post:

1. Don't use the Watchdog timer in a test program.

2. Don't use the debugger in a test program. Just program it and run it.
Don't enable the debug executive code.

3. Don't enable Low Voltage Programming mode unless you have an LVP
programmer. (Hardly anyone does). Change the fuse to NOLVP.


Quote:
#use i2c(Master,fast=400000,sda=PIN_C4,scl=PIN_C3,nofloat_high)//force_hw)

Don't use i2c Fast mode in a test program, unless it's necessary to show
the problem.


Quote:
The SDA line has a 10k pullup resistor, connected to 3.3V on the other side.

Those are a little light. I would have run 1ma pull-ups. This is 3.3K on
a 3.3v system. For Fast mode, I would have run half of that, or less.
ie., 1.5K.

Quote:
The SDA line has a 10k pullup resistor, connected to 3.3V on the other side.

Do you have a pull-up on the SCL line ? What value ?
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 3:31 pm     Reply with quote

I edited my post; the FUSES I posted apparently was from a slightly older version of this code.
LVP and DEBUG have in fact been disabled.

And I'm not sure how much I'm really permitted to post of the code. I figured posting a few innocuous things would be ok though. And really, that's all that was run in order to generate the odd waveform.

1) Why no watchdog timer though, even on a test program? I have been bitten before by disabling it while writing and testing code, and then enable it, only to find that it was causing odd resets. I can give it a go with it disabled though.

2) Done.
3) Done.

4) I2C Fast Mode - this unusual waveform happens just the same with slow or fast mode.

5) Pullups on the SCL and SDA lines are 10k now. I'll definitely try out something much lower when I'm back at the office.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 4:01 pm     Reply with quote

Although 10k pullup is possibly a bit high, it should not cause the discussed behaviour. I asked for the pullup, because SDA seems to have a rather slow risetime, that can't be explained with e.g. 20 pF pin capacitances and a 10 pF oscilloscope probe. The said 400 pF is a maximum bus load for a large multi-drop bus and doen't apply for your design, of course. Or did you connect a 1:1 100 pF probe?

From a complete bus transaction, with SCL and SDA recorded, one can possibly see, which side is generating the spike. If I understand right, the nofloat_high option is only available with software I2C, because it's no hardware feature of the PIC I2C interface. I wonder, why you're using software I2C on the standard I2C pins, that would allow hardware I2C as well?

Apart from what causes the "spike", I don't see a sufficient explanation, why it should also involve the other reported problems, unless you have a defective chip or another serious hardware issue.
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

PostPosted: Sun Oct 04, 2009 4:20 pm     Reply with quote

FvM wrote:
Although 10k pullup is possibly a bit high, it should not cause the discussed behaviour. I asked for the pullup, because SDA seems to have a rather slow risetime, that can't be explained with e.g. 20 pF pin capacitances and a 10 pF oscilloscope probe. The said 400 pF is a maximum bus load for a large multi-drop bus and doen't apply for your design, of course. Or did you connect a 1:1 100 pF probe?

I'll try to check tomorrow; offhand, I don't know what kind of probe it was.


Quote:
From a complete bus transaction, with SCL and SDA recorded, one can possibly see, which side is generating the spike. If I understand right, the nofloat_high option is only available with software I2C, because it's no hardware feature of the PIC I2C interface. I wonder, why you're using software I2C on the standard I2C pins, that would allow hardware I2C as well?



If I use "force_hw" in the #use i2c line, if that's what you're referring to, the PIC resets itself the first time it tries to do anything related to I²C routines, with or without nofloat_high present.


Quote:
Apart from what causes the "spike", I don't see a sufficient explanation, why it should also involve the other reported problems, unless you have a defective chip or another serious hardware issue.

And this isn't unique to this board, so it's not defective hardware - that funky little spike appears on any of these boards I'm working with.
This particular part of the circuit isn't terribly complex or bizarre either. It's pretty well wired up according to the recommended layout on the DS3231's datasheet, the chip is located fairly close to the PIC, and the lines don't appear to be at all noisy.





Sometimes I almost don't like having an interesting/fun job - it almost makes weekends painful. Shocked
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

PostPosted: Mon Oct 05, 2009 11:19 am     Reply with quote

Some updates:
- The oscilloscope is a Tektronix TDS 210.
As for the probes, they're 1x/10x probes, without any markings on them as to capacitance.

- I swapped out the 10k pullups and used 1.2k instead, and got rid of nofloat_high. I've got much sharper rises now, and all signals are either 0V or 3.3V; that little 0.48V "bump" is gone now. Rise time is about 412ns to hit 3V from 0V. Fall time is less than 100ns. (This is in fast=400000 mode.)


Seems like that may take care of this problem, unless anyone has any followup questions or hanging issues that they want answered. Smile
Now it's on to determine the cause of these mysterious lockups. Confused
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Oct 05, 2009 1:02 pm     Reply with quote

Unfortunately, I can't explain the mysterious lookups from a distance.

Regarding probe impedances, you can expect 10-15pF || 10 MOhm in 10x position and about 100 pF || 1 MOhm in 1x mode. So it's strongly recommended to set the probe to 10x for an (almost) undisturbed signal acquisition.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Oct 06, 2009 10:48 am     Reply with quote

I've seen this 'spike' quite a bit. It's, usually, when one device releases the line. I see it just before the ACK, when one of the devices releases the bus and the other one takes over to send the ACK. Is this where the spike is happening?

One other thought might be that there could be some contention between devices where one is trying to pull high while another is trying to pull low. Shouldn't happen but I've seen it, especially when I was trying to bit-bang things and didn't have things timed quite right.

You might try a bus accelerator like the LTC1694-1. I always use this in my I2C designs to make sure the signals are squared up properly.

Ronald
Jeff7



Joined: 22 Sep 2009
Posts: 13

View user's profile Send private message

PostPosted: Tue Oct 06, 2009 8:53 pm     Reply with quote

The spike appeared to be happening at the end of what should have been a logic high (I think that's the proper terminology), being driven there by the DS3231, but as best as I can figure, the PIC tried driving it low, but then for whatever reason it stopped trying about 100ns before the DS3231 stopped what it was doing.

Once I dropped the values of those pullup resistors way the heck down, and got rid of nofloat_high, the signals squared up well enough, the spikes went away (since the signal was already at 3.3V, it had nowhere to spike to), and where those odd little 0.48V-pulse+spikes had been, there were only clean logic highs coming off of the DS3231.





On an unrelated matter, though not really worthy of its own thread, the lockups I mentioned have also gone away, apparently. I think it was a memory management issue of sorts.
The way the code was done up before, the menus were all in one BIG function, consisting of a switch statement with oodles of cases after it. And some of the menus needed to call functions within them. For example, when setting the time on this particular product, it would first run another function to perform time zone calculations, which would call another function to do Daylight Savings Time calculations, which would call another function.....I think it went somewhere around 6 deep at some point, complete with all kinds of local variables being passed around.

When the menu() function was originally made, it was quite small, with only 4 screens. Since then it's grown in complexity to include 19 screens, some of which call functions, as described above.

In my brief and unskilled time with an ICD-U40, I saw that this massive Menu function was of course being shoved onto the stack. Sometimes the function calls that would cause this would initialize local variables consisting of 1-dimensional arrays of up to 212 characters, and a 2-dimensional array 4x70 characters.
As best as I can figure to the best of my relatively unskilled abilities, something was shoving things into places in memory or in the stack where they weren't allowed, causing either resets or hard lockups.


Anyhow, I pushed the calls to those functions which required large data buffers outside of the menu function, and instead used flags to enable them to be run.

These large buffers are being used to accept long strings of GPS data in through a software UART. If I tried to do any sort of processing of the information while it was arriving, I almost always lost a lot of it, so I instead used a large buffer to collect it all en masse, and then process it afterward to pluck out what I needed.




(Also, forgive any misuse of terminology. Corrections are welcome. Just be gentle. Smile)
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Wed Oct 07, 2009 10:23 am     Reply with quote

FvM wrote:
I think, you didn't tell at all, which signal is shown in your sketched waveform. Is it SDA? If so, what's the green trace?

Quote:
Pullup resistor value for anything on the board that needs them is 10k
The slow rising black trace seems to suggest, that there's no sufficient pullup on this line (SDA?).


Also, read up on the I2C spec, for slow (100Kb/s) and fast (400Kb/s) there are some specific rise/fall times that must be met.

10K with a lot of capacitance might be too high. 4.7K might work better.

With that I2C spec, it also lists what a device must need to sink in order to operate the describes speeds...

I agree with the others, sounds like a little bit of bus contention (which depending on the timing, might be ok - you need to read the I2C spec)

The I2C protocol spec can be found here:
http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group