2014-09-26 07:43 AM
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 oneIn 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 #board2014-09-30 06:20 AM
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?
2014-09-30 07:06 AM
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.
2014-09-30 07:57 AM
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 (microcontroller 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
).2014-10-01 03:51 AM
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.
2014-11-13 12:54 AM
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?