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 CCS Technical Support

I2C Bus Crashing

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



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

I2C Bus Crashing
PostPosted: Fri Dec 27, 2013 4:37 pm     Reply with quote

Hi all,

I am using the PIC24 development kit with the PIC24FJ128GA006. I have successfully communicated with a honeywell HSC pressure sensor, but am not able to release the bus.

When using the i2c_stop function the bus crashes. If I do not use the i2c_stop function, everything works well, but the bus is never released. It is always held LOW.

Did i forget something that is causing the bus to hang when using i2c_stop?

Thanks!

Code:
#include <24FJ128GA006.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOJTAG                   //JTAG disabled
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled

#device ICSP=2
#use delay(crystal=20000000)

#use i2c(master, SCL=PIN_G2, SDA = PIN_G3, FAST, STREAM = I2CM)
#use rs232(baud=9600, xmit=PIN_F3, rcv=PIN_F2)

typedef struct{   //Define structure for pressure and temperature variables

         double Temperature;
         double Pressure;
} Sensor;

Sensor HSCM;

void GetRawSensorData(int);
int8 GetHSCMData(int8);
void main()
{



   while(TRUE)
   {
     
      GetHSCMData(0xD1);
      delay_us(50);
     
   }

}

void GetRawSensorData(int8 Address,int8 *RawData){

   int data = 0;

   i2c_start();   //Start I2C connection
   i2c_write(Address);
 
   
   for(int i = 0; i < 3; i++){ //Read the bytes on less time than required
   
      RawData[i] = i2c_read(I2CM,1);  //Read I2C data into the array.
   }
   
   RawData[3] = i2c_read(I2CM,0); //Read the last byte, dont send an ACK back to the slave
                                          //this is specified in the I2C document of the sensor
                                         
   //i2c_stop(I2CM);    /*******************************************************/                                 
                        /****THIS STOP CAUSES THE BUS TO HANG ******************/                   
                                       

}

int8 GetHSCMData(int8 Address){

   int8 RawSensorData[4];  //Make an array to store the raw data from the sensor
   
   GetRawSensorData(Address, &RawSensorData);   //Get data from sensor
   
   //int8 StatusBits = RawSensorData[0];
   //printf("StatusBits: %X \n\r", StatusBits);

}


Last edited by demedeiros on Sat Dec 28, 2013 5:11 am; edited 1 time in total
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Fri Dec 27, 2013 5:31 pm     Reply with quote

Can you further explain what you mean by the "bus crashes" with the i2c_stop() in? What exactly happens? On thing that I notice from your code is that you aren't setting any of the oscillator fuses like you should. There are two fuses that setup the oscillator that should be set.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Fri Dec 27, 2013 8:35 pm     Reply with quote

By bus crashing, I mean that the program appears to stop/freeze and activity on the i2c bus stops.

I set up the fuses and settings using the pic24 wizard, I will try to add them manually. What fuses do you say I am missing?

Thank you!
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 4:05 am     Reply with quote

A bus that is high, is idle.....

I2C pulls low for activity. A device that wants to 'hold' the bus, pulls it low.

Comments:

1) You are using streams for some commands, and not others. Either have one I2C statement, get rid of the stream name, and use functions without streams, or use stream names in all I2C operations. Don't 'mix and match'....

2) I'd be explicit on the clock rate. Though 'fast' should default to 400KHz, be safe, and specify this, since 400K is the fastest the sensor supports.

3) Now, your PIC is a 3v device. Have you got the 3v version of the sensor?. '3' at the end of the part number.

4) What pullups have you got on the I2C bus?. 1K minimum for the device. At 3v, using 'fast' I'd suggest 1K8 or 1K5R.

5) Your device ends '6A3' meaning it uses address 0x68?.

6) In C, the name of an array _is_ it's address. You are taking the address of the address.....

&RawSensorData

Should be:

RawSensorData

or

&RawSensorData[0]

7) NACK is always required on the last byte of an I2C multi-byte transfer. This is 'standard I2C', not a sensor specific feature.

8) The status bits are:

(RawSensorData[0]>>6) & 3

Not the whole byte.

9) Get into the habit of using variables the traditional C way. Though CCS 'purports' to support declaration 'in code', it has a nasty habit of giving odd results when these are used....

Best Wishes
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 5:10 am     Reply with quote

Thanks Ttelmah,

Just realized that I made a mistake in my first post, bus is being held LOW, not high. Sorry.

Thank you for all of the comments, i'm really new to CCS and have minimal background in C/programming in general.

Heres some answers to the comments and questions.

1) Initially everything was done without streams, I added the streams to see if it would help the problem. It did not.

2) Makes sense, I will try FAST=400000 Monday morning.

3) I have the 5V version, but the pic IO are 5V tolerant and the sensors I2C high level is 0.8V. I've had this working with the master holding the bus low.

4)I have 4.7k pullups on the bus

5) 6A5, but yes address 0x68

6) Gotcha. So if I was passing a pointer to an int or char I would use the reference operator? Excuse my naivety, this is my first try at passing an array as pointer.

7)

8)My assumption here was that if I shifted to the right by 6, I would get rid of the 6 most significant bits. Thats not correct?

9) Could you elaborate on "the traditional C way?" I thought I was doing so.

Thanks Again!
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 5:22 am     Reply with quote

What happens to the upper bits when you shift is 'indeterminate'. If (for instance), you shift a signed value, then in some C's the sign bit is duplicated, while in others it is not. Hence always safer to explicitly mask the bits you don't want. In your code, you were not showing the value being shifted at all.

The standard in C, is to declare all variables at the start of a code block.

Yes, the array name without any index, is a C 'shortcut' to it's address. For everything else you need to use the '&' statement, and you can for the array if you want, as I show.

The SCL pin on your chip is _not_ 5v tolerant. Only the data line is. Try using software I2C, on two pins that are 5v tolerant. (G3/D0 for example). This could be a major problem.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 5:31 am     Reply with quote

Ahh! That makes sense. I had originally shifted the byte, but was having odd output. I printed the status byte to read its value. Thats why its commented

It is my understanding that the master always generates the clock in an I2C system. If that is correct, then why does it matter if the IO is 5V tolerant, since the SCL line will never be driven by the slave?

Thanks again!
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 6:45 am     Reply with quote

I2C lines are only pulled _low_ by the driving devices (master or slave). They are pulled up by the resistors.
The high level required by the chip is not '0.8v', it is '0.8*Vsupply'. So with a device running at 5v, the line needs to go up to 4v. Above the maximum supported by the pin on the PIC...

Best Wishes
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 7:40 am     Reply with quote

Man, I should lay off the data sheets in the morning.

Thanks for all of your help. I will implement a level shifter and give all the tips a try.

Thanks again!
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Sat Dec 28, 2013 10:41 am     Reply with quote

demedeiros wrote:

I set up the fuses and settings using the pic24 wizard, I will try to add them manually. What fuses do you say I am missing?

Thank you!


The wizard can be off a lot of times. For most PIC24FJxxxGAxxx family chips, the primary clock source is selected using two fuses:

One fuse has the following options
NOPR,HS,XT,EC

This tells the chip which type of circuit to use for the primary oscillator (none, high speed crystal, non-high speed crystal, or external clock chip respectively)

The other fuse specifies the source of the primary clock. It has many options that vary from chip to chip, so I can't list them, but the data sheet will tell you. Some examples of what I have seen:
PR - use the primary external oscillator
FRC - use the internal fast RC circuit
LPRC - use the internal low power RC circuit
etc.

There are sometimes PLL options in that second fuse.

While you may or may not be getting lucky with the defaults, it is usually best to specify what you want based on your circuit.

EDIT: some examples:
if using an external 22 MHz crystal
#FUSES HS
#FUSES PR

if using the internal FRC:
#FUSES NOPR
#FUSES FRC
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Sun Dec 29, 2013 8:08 pm     Reply with quote

Thank you,

I will try all of the suggested fixes to try and solve this issue!

Thanks!
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Mon Dec 30, 2013 7:43 am     Reply with quote

Well, the problem was in fact related to the fuses.

After setting #FUSES HS and #FUSES PR, the I2C bus no longer crashes/hangs, and is being pulled up when idle.

Still going to implement all the other suggestions though.

Thanks!
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