MC13224V I2C

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC13224V I2C

3,081 Views
Brillo
Contributor I

Having Problems with I2C Interface on SRB Sensor Board.

I used sound.c as an example.

 

I called JC_I2C_Init first, then I2c_Enable which returned code 0 (success)

If I call I2c_Enable a second time I get a return code of 1 indicating I2C is already Enabled

 

The problem is that when I call I2c_SendData the code hangs there forever.

 

An oscilloscope shows no activity on Data or clock leads.

 

Is there an application for the demo board using I2C that can be compiled and run. THe demos I see don't appear to actually call the functions in the sound.c code.

 

Any thoughts?

Thanks!

 

 

 

 

Tags (1)
0 Kudos
Reply
12 Replies

1,892 Views
sverige
Contributor I

Hi,

 

I think I had the same problem some months ago. Is your I2C device connected properly? If not, the driver hangs. How to you use the I2c_SendData? Maybe you don't release the bus after the transfer? I use this code:

 

I2c_SendData(myAddress, &buffer[0], 2, gI2cMstrReleaseBus_c);

 

greets,

Franz 

 

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

Franz,

Thank you so much for the reply. I was using the same options in the SendData as you suggested.

I have not connected the I2C to anything yet. On the SRB(Sensor Board) that I'm using, the I2C is already properly connected to the volume control function. While the data I'm sending is ultimately for another device and should fail with the volume control function, the MC13224 should attempt to send it without hanging, and I should see the initial start bit and address go out (looking at it using an oscilloscope). So, now what I've done is send a I2c_RecoverBus() command from inside my I2C configuration routine and it also hangs (function doesn't return). The Configuration function returns 0 (good). Here's the code I'm executing:

 

void JC_I2C_Init(void)
{
  I2c_Init();
}

 

/***********************************************************************************/
 void JC_I2C_Configuration(void)
{
  I2cConfig_t i2cConfig;
  i2C_Err_Msg = I2c_Enable();
  i2cConfig.i2cBroadcastEn = FALSE;
  i2cConfig.freqDivider   = 0x20;   /*Divider = Decimal 160 (24 mhz / 160 = 150 kb*/
  i2cConfig.saplingRate   = 0x01;   /* For Noise filtering   Default = 0x10*/
  i2cConfig.slaveAddress   = 0x00;  /* Freescale is Master - so this is 0 */
  i2cConfig.i2cInterruptEn = FALSE;
  I2c_SetConfig(&i2cConfig);
  I2c_RecoverBus();
 
}

 

Thanks again Franz

0 Kudos
Reply

1,892 Views
sverige
Contributor I

Unfortunately I don't see the problem in your code, the one I use looks quite similar. Here is what I do. This works.

 

void I2c_Init_Config(){
I2cConfig_t i2cConfig;

I2c_Init(); //must be called bevore any further I2c operation

Gpio_SetPinFunction(gGpioPin12_c, gGpioAlternate1Mode_c); //sets GPIO Pin to I2C_SCL
Gpio_SetPinFunction(gGpioPin13_c, gGpioAlternate1Mode_c); //sets GPIO Pin to I2C_SDA

I2c_Enable();
i2cConfig.i2cBroadcastEn = FALSE;
i2cConfig.freqDivider = FDR_VAL;
i2cConfig.saplingRate = 0x01;
i2cConfig.slaveAddress = TCN75A_Address;
i2cConfig.i2cInterruptEn = FALSE;
I2c_SetConfig(&i2cConfig);

}
 

Maybe your GPIO Pins are not configured properly? 

0X20 in hex is not 160 decimal, but i would wonder if this was the problem. 

greets,

Franz

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

FRANZ,

I believe that the 0X20 is converted to a divider of 160  by the driver. See   

Table 14-5. I2C Clock Divide Ratio vs. FDR Setting on page 14-11 in MC1322x Reference Manual - MC1322xRM.

 

SPeaking of the Reference Manual, I should have read it closer. You were correct that I had not configured the GPIO pins for I2C. I had falsely assumed that they had a fixed purpose since the pins were labeled  I2C_SDA and I2C_SCL. I should have read the manual closer. Wouldn't have expected the driver to hang in this instance. Lesson learned.

 

My  I2C_SendData function now works (doesn't hang) !

 

Thank you so much. You are the best!

Brillo 

0 Kudos
Reply

1,892 Views
WolleW
Contributor I

Hi,

I have the same problem as Brillo at the beginning. When I want to send data with I2c_SendDate() the code hangs forever. I adjusted my settings to yours but still the code hangs. Do I need to set up the Transfertype (Transmit or Receive)? If yes, how do I do that.

Here are my settings. I hope you can help me. Thank you in advanced.

 

void InitI2CInterface(void)

{

  I2cConfig_t I2cConfig;
  I2c_Init();
 
  /* Init GPIOs for I2C */
  Gpio_SetPinFunction(gGpioPin12_c, gGpioAlternate1Mode_c);
  Gpio_SetPinFunction(gGpioPin13_c, gGpioAlternate1Mode_c);
 
  I2c_Enable();
 
  I2cConfig.i2cBroadcastEn = FALSE;
  I2cConfig.freqDivider = 0x20;         /* 0x20 FDR = 160 decimal */
  I2cConfig.saplingRate = 0x01;         /* Default would be 0x10*/
  I2cConfig.slaveAddress = 0x00;        /* MC1322x is master so it is 0 */
  I2cConfig.i2cInterruptEn = FALSE;
 
  I2c_SetConfig(&I2cConfig);

}

 

void BeeAppInitTempSensor(void)

{
  uint8_t SetConfigReg = 0x20;    /* to enable one-shot mode */
  uint8_t SlaveAddr = 0x48;


  /* setup data buffer */ 
  uint8_t DataBuff[2];
  DataBuff[0] = AddrConfigReg;    /* 0x03 */
  DataBuff[1] = SetConfigReg;      /* 0x20 */
 
  I2c_SendData(SlaveAddr, &DataBuff[0], 2, gI2cMstrReleaseBus_c);     /* code hangs when I call this function */

}

 

 

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

WolleW,

Been a while since I worked on the I2C code. I looked over your code and my current code and don't see a problem.

You must be using a custom board with a temperature sensor because the Sensor eval board uses an ADC to interface the temperature sensor.  If so, are you sure that the I2C is properly connected to your MC13224 and with pullup resistors on SDA and SCL? By the way, its a good idea to enable the watchdog to recover from any I2C hangups.

 

One thing you might try is to check the return code for your i2c_Enable call. (e.g., i2C_Err_Msg = I2c_Enable():smileywink: . Perhaps you need a delay after i2c_Enable and before I2c_SendData.

 

Brillo

0 Kudos
Reply

1,892 Views
WolleW
Contributor I

Hi Brillo,

 

Thank you very much for your help. I made a mistake with the pullup resistors. But I've got one more question. I'm a little confused because of the different slave addresses of your settings in this forum. One of you says

      i2cConfig.slaveAddress = TCN75A_Address;TCN75A_Address

and the other says

      i2cConfig.slaveAddress   = 0x00;  /* Freescale is Master - so this is 0 */

 

In want to use the Freescale chip as master and an ADT7410 Temperature Sensor as slave. What do I have to write to the "i2cConfig.slaveAddress"?

 

Cheers,

WolleW

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

WolleW,

The TCN75A_Address is a define for some actual hex address value.

In my code I explicitely specified the hex address for my device (0x00).

Since the I2C buss can have multiple devices hanging off of it, there needs to be a way of "addressing" which device you want to talk to at any point in time. I'm guessing that you only have one device as do I. I am not familiear with your temperature sensor. However, I quickly took a look at the spec on the ADT7410 and see that it can be configured for 1 of 4 addresses. Those addresses are specified in Table 20 on page 17. You choose which one by what you connect to pins A1 and A0 of the ADT7410. For example, the schematic Fig 14 shows both pins connected to ground. Thus, they both have a input logic level of "0". Thus, per Table 20 the address to use for that case is 0x48. Check to see how you have those two pins wired and use Table 20 to give you the address. The idea is that if you had 2  I2C devices (e.g., two of your temperature sensors) hanging off of the bus you'd have to wire them differently so that they could be accessed independantly via different addresses per Table 20.

 

regards,

Brillo

0 Kudos
Reply

1,892 Views
WolleW
Contributor I

Brillo,

That was clear so far. A0 and A1 are connected to ground. So the address of the ADT7410 should be 0x48. I watch the SDA and SCL on a scope. When I set the   i2cConfig.slaveAddress   = 0x00;

like this and call

I2c_SendData(0x48, &DataBuff[0], 2, gI2cMstrReleaseBus_c);

I can only see the serial bus address byte on the scope and the return value (error) says NoDeviceResponse.

 

But when I set the

i2cConfig.slaveAddress   = 0x48;

like this and call

I2c_SendData(0x48, &DataBuff[0], 1, gI2cMstrReleaseBus_c);

then I can see the serial bus address byte and the data byte. But in this case I would say, I talk to "myself".

 

And, which makes me even more confused, I can receive data.

When I call

I2c_ReceiveData(0x48, &DataBuffRead[0], 1 , gI2cMstrReleaseBus_c);

the first byte, which is the serial bus address, is 0x49 and the actual data byte is always 0xFF.

 

I guess it is just a little think that I'm overlooking.

 

WolleW

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

WolleW,

Why do you say " But in this case I would say, I talk to "myself"."?

The MC13224 is sending the address to the Temp Sensor not to itself.

The SendData addresses your sensor and tells it to take a temperature reading and have it ready for the following ReceiveData request  from the MC13224. What did you set the value of DataBuff[0] on your SendData? THis register must contain the ADT7410 starting internal register address you want to read from next on the ReceiveData. I see that you are reading only 1 data byte, so you will receive only 1 data register value. Did you read and understand Page 19? You can read a block of registers in one read oryou can skip around (eg, read a status register, then read a data register. But, to do that you must send another SendData to establish th next register address to read if you are skipping registers because otherwise the ADT7410 aut increments the register address. The address registers are on Page 13.

 

you say:

I2c_ReceiveData(0x48, &DataBuffRead[0], 1 , gI2cMstrReleaseBus_c);

the first byte, which is the serial bus address, is 0x49 and the actual data byte is always 0xFF

 

Did you misstype 0x49? The serial buss address you selected was 0x48

The data byte received depends on the register address you received which I'm assuming you would set to 0x00 for "temperature Register". But in that case you must select 2 bytes to read on your ReceiveData command because the sensor data register is 2 bytes long (MSB,LSB).

 

I didn't see in the document where it tells you how long it takes the sensor to take a temperature reading. You might have to either delay a bit (i'd start with 20 milliseconds) between your SendData and ReceiveData. Or, read the status register first and do the read of the sensordata register when the status is Ready.

 

Note: This chip doesn't allow block reads except for 2 byte registers. So, you can't do a  3 byte read to get the value in the status register (address 0x03). You must read it separately which means 1 write to establish the staus register read, a 1 byte read, then a write to establish the temperature value register, then a 2 byte read. If you are only going to read the Temperature value register every time then supposedly you don't need to repeat the SendData because the chip always uses the same register address until you tell it different - doesn't auto increment like some other devices.

 

 

 Now, to get good readings from your temp sensor I'm assuming you might have to first send some configuration data to the other registers to properly configure the chip. You only need to do this once. You could for instance load the proper values for all registers 0x00 - 0x0A into your DataBuf and send 11 bytes. After that for each sensor reading, you send the SnedData message you have been sending (1 byte, 0x48 etc) then follow it with a read of 2 or 3 bytes). But, perhaps you can use thedefault values for your application or testing.

 

Finally, you should read the return code on your ReceiveData commands to see if they fail. I suspect that if the data is not ready when you try to read it, that you will see a read failure.

 

BTW, There's some code at this site and others:

http://mbed.org/users/tkreyche/libraries/ADT7410/llxdvz

 

Hope this helps and I'm not telling you stuff you already know.

Brillo

 

0 Kudos
Reply

1,892 Views
WolleW
Contributor I

Brillo,

Thank you so much for your help and your patience. The Link you've posted showed me the solution for my problem.

I overlooked that the bus slave address is only a 7bit value. So I set the ADT7410Addr to 0x90 instead of 0x48 and now it works.

 

-WolleW

0 Kudos
Reply

1,892 Views
Brillo
Contributor I

you are welcome. I've received good help here and its a pleasure to give a little back.

Brillo

0 Kudos
Reply