cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0 & I2C - reading data problem (FLAG RXNE)

slew
Associate II
Posted on September 26, 2014 at 16:43

Hello. I'm trying to run a simple I2C test with my STM32 board and I can't get it to work. I'm using STM32F0 Discovery kit (master) and one slave device (some module) that I want to communicate with via I2C bus. Devices are connected via lines SCL, SDA, GND, Vdd and Reset (active low; raised by master).

This is my first time using I2C bus on STM32 kit.

In datasheet of my module it says that after the module is either powered on or reset, the module controller will always send a special 4 byte long msg (kind of “Hello�? packet) to the host system (implying it is ready to work). So

for a quick test of I2C communication I just wanted my master (STM32) to read this »Hello« packet via I2C to see if it's working.

So my general idea (code) was to: 1.) initialize HW (I2C, GPIO, LEDs...). Using internal pull-up resistors in I2C init 2.) write I2C ''read'' function for reading ''Hello'' packet sent from slave device 3.) print out ''Hello'' packet to see if it is correct one

In my ''Reading'' part of my code I first force restart of the slave device by forcing ''reset'' pin low. Then I try to read the ''Hello'' package sent by slave:

I2C_TransferHandling(I2C1, DEVICE_ADDRESS1, Num_of_bytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
// read in Num_of_bytes (data)
for
(Cnt = 0; Cnt < Num_of_bytes; Cnt++)
{
// wait until the RX register is full
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);
if
(Num_of_bytes > 1)
{
Data[Cnt] = I2C_ReceiveData(I2C1);
...........

The problem is that the program gets stuck at the point of checking RXNE flag as the flag seems to never get set (always stays reset) and therefore no reading data occurs.

So my questions are: 1.)

Should I use external pull-up resistors? Currently I'm only using internal ones, as I read (on some blog) that it should be good enough for simple I2C communication

2.) Is my concept of reading data (sent from I2C slave) correct? Thanks! #i2c #discovery #board
5 REPLIES 5
slew
Associate II
Posted on September 30, 2014 at 15:20

Update: Now I also tried using external pull-up resistors but the problem (with RNXE flag)  is still there. Any idea what I'm doing wrong? Anyone?

frankmeyer9
Associate II
Posted on September 30, 2014 at 16:06

In datasheet of my module it says that after the module is either powered on or reset, the module controller will always send a special 4 byte long msg (kind of  “Helloâ€� packet)  to the host system (implying it is ready to work).

 

That can't be true - or you not actually speaking about I2C here.

EVERY transfer on the I2C bus is initiated by the master, which is the STM32 in your case. And to access a slave, he is addressed first.

Check out the I2C specification, using your favourite search engine.

slew
Associate II
Posted on September 30, 2014 at 16:57

Thanks for your answer. Basically you are right. Actually it's like this: this module can intent to transmit data to host (master) first because it uses (an additional) interrupt line (which I'm not using for my test) for notifying the host (master). Still, it's the master that should start the whole I2C data transfer (after noticing the interrupt), as you said correctly.

So perhaps I should change my ''reading data'' part of I2C code?

Any idea how could I just test if my master (STM32) can ''see'' the slave device on I2C, just to make sure my slave (7-bit) address is correct one? Because there's some confusion about this issue (m

icrocontroller peripherals tend to want the device address in the upper 7 bits while datasheets for devices tend to specify the address in the lower 7 bits

).

frankmeyer9
Associate II
Posted on October 01, 2014 at 12:51

Any idea how could I just test if my master (STM32) can ''see'' the slave device on I2C, just to make sure my slave (7-bit) address is correct one? Because there's some confusion about this issue (m

icrocontroller peripherals tend to want the device address in the upper 7 bits while datasheets for devices tend to specify the address in the lower 7 bits

).

 

I would not express it that way.

The I2C bus was basically developed for short-range connections on one PCB, so it expects a static setup. The master needs to know the proper slave addresses.

The LSB of the address (when send on the bus) is used to discern between read and write access - this makes up a 8-bit address, each slave consuming two addresses. One has to pay close attention on how the slave address is explained in the datasheet.

To check that a slave responds to an address, it acknowledges the addressing. You will need a scope to check that.

If you did not already, I suggest to download the I2C spec. and read it briefly, if only to clarify those I2C-specific terms like address, ack/nack, start, stop, etc.

slew
Associate II
Posted on November 13, 2014 at 09:54

My late update on this issue.

Having not found any solution to my reading data problem I then tried writing some data to the module instead, as this should be easier and shorter. So I tried to write command packet to module (slave) which should set the module Power State mode to be, say, Deep sleep. According to the datasheet, writing and reading is done by the master (STM32) sending 4 bytes long “command�? packet (e.g. 0x51 0x56 0x00 0x01) to the slave (module). There’s no mentioning of any sort of module’s internal instruction register address or something like that, just this kind of command packets. So I wrote the writing part of code as following:

1.

I2C_TransferHandling(I2C1, Slave_addr_w, Num_of_bytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Write); 
2.

TS_WaitForI2CFlag(I2C_ISR_TXIS);
3.

DelayMil(200);

TS_WaitForI2CFlag()

is just a function I wrote for checking I2C flags while

DelayMil

() is just a simple dalay function (ms). This part of code goes through, so obviously the slave address is correct and the master correctly starts START condition. Then I write the first byte (0x51) and wait for TXIS flag to be set:

1.

I2C_SendData(I2C1, 0x51);
2.

DelayMil(200);
3.

TS_WaitForI2CFlag(I2C_ISR_TXIS);

This part goes through too, so then I proceed with writing the second byte:

1.

I2C_SendData(I2C1, 0x56);
2.

TS_WaitForI2CFlag(I2C_ISR_TXIS); 
// code hangs here !!!

And this is the point where my program hangs as the TXIS flag is never set. Any idea what could be the problem?