cancel
Showing results for 
Search instead for 
Did you mean: 

Random ACK behavior of I2C in slave receive mode

sebestajan
Associate II
Posted on June 29, 2007 at 07:20

Random ACK behavior of I2C in slave receive mode

1 REPLY 1
sebestajan
Associate II
Posted on May 17, 2011 at 09:44

Hello, again helpless 🙂

I have to note I have special CPU version STR912FAZ44H (so maybe it is my small local problem).

So my target is to configure I2C interface in slave mode to receive command from master device and send back apropriate response. Now I play with command reception and I experienced problem that my I2C configured as slave does not allways acknowledge byte reception by ACK bit. More preciselly, received address byte is allways acknowledged by ACK, but usually the first or the second data byte is not acknowledged (instead of ACK bit NACK is sent to I2C master device - measured on oscilloscope).

And because of random behavior I have no clue why it happens. See my code bellow, maybe you will find something..

-------------------------------------------------------------------

/* INITIALIZATION */

#define I2C_DEF_ADDR 0xC0

//SCU config

I2C_DeInit(I2C1);

SCU_APBPeriphClockConfig(__I2C1,ENABLE); //enable clock to I2C1

SCU_APBPeriphReset(__I2C1,DISABLE); //cancel I2C1 reset

SCU_APBPeriphIdleConfig(__I2C1,DISABLE); //disable I2C1 in idle

SCU_APBPeriphDebugConfig(__I2C1,DISABLE); //disable I2C1 in debug

//SCU GPIO to alternate I2C1 functions

GPIO_InitTypeDef gpio;

gpio.GPIO_Pin = GPIO_Pin_2; //I2C1 SCL pin

gpio.GPIO_Direction = GPIO_PinInput;

gpio.GPIO_Alternate = GPIO_InputAlt1;

gpio.GPIO_IPConnected = GPIO_IPConnected_Enable;

GPIO_Init(GPIO2,&gpio);

gpio.GPIO_Pin = GPIO_Pin_3; //I2C1 SDA pin - bidir.

gpio.GPIO_Direction = GPIO_PinOutput;

gpio.GPIO_Type = GPIO_Type_OpenCollector;

gpio.GPIO_Alternate = GPIO_OutputAlt2;

gpio.GPIO_IPConnected = GPIO_IPConnected_Enable;

GPIO_Init(GPIO2,&gpio);

//I2C config

I2C_InitTypeDef i2c;

I2C_StructInit(&i2c);

i2c.I2C_CLKSpeed = 10000; //scl frequency 10kHz

i2c.I2C_OwnAddress = I2C_DEF_ADDR; //default address

i2c.I2C_GeneralCall = I2C_GeneralCall_Disable; //no general call

i2c.I2C_Ack = I2C_Ack_Enable; //we use ACK bit

I2C_Init(I2C1,&i2c); //initialize

/* RECEPTION LOOP */

//returns ''true'', when required flags indicated in stat register

#define flags(stat,flags) ((stat & flags) == flags)

//returns ''false'', when required flags indicated in stat register

#define nflags(stat,flags) ((stat & flags) != flags)

//flags definition

#define FL_ADSL 0x0004

#define FL_BTF 0x0008

#define FL_STOPF 0x0800

printf(''\nI2C test now running..'');

while(1)

{

u16 stat;

//wait for address matched flag - ADSL

//cleared by reading I2C_SR1

do {

stat = (I2C1->SR1) | ((I2C1->SR2) << 8);

} while(nflags(stat,FL_ADSL));

printf(''\nrxed: '');

//wait for byte transferred flag - BTF, cleared by reading I2C_DR

//or stop condition flag - STOPF, cleared by readng I2C_SR2

do {

do {

stat = (I2C1->SR1) | ((I2C1->SR2) << 8);

} while(nflags(stat,FL_BTF) && nflags(stat,FL_STOPF));

if (flags(stat,FL_BTF))

printf(''%d '',I2C1->DR);

} while(nflags(stat,FL_STOPF));

}

-------------------------------------------------------------------------

So here are some notes about the code:

- My I2C master device clock frequency is 10kHz

- I2C address transmitted by master is 0xC0, so the event flag ADSL is always indicated properly

- I tried to set-up I2C to generate interrupts and to handle I2C events in I2C1 interrupt handler, but I got exactly the same random behavior of ACK/NACK response..

- I read some forum messages about standard library about bug in intializing GPIO, so I avoided initializing GPIO8 & GPIO9 in the rest of my code

- when the reception is correct, then printf() fucntion displays received command on console (for example when transmitting two bytes ''1'' and ''2'', then I received ''rxed: 1 2'' = correct, but only sometimes, sometimes I have displayed only ''rxed: 1'', sometimes ''rxed: '' because of random acknowledgement bit)

I also investigated Hitex example 16 ''I2C Peripheral'', but this funny hitex document (Insiders Guide) says at the beginning of I2C chapter somehting about slave communication, but in real the code in text configures I2C as a master and also example 16 is not a loopback applicaton, but it reads data over I2C from temperature sensor and displays it on LCD, so a lot of uncorrect informations inside 🙂 In conclusion, there is no example of I2C configured as slave receiver, it seems to me, that nobody has tested it 🙂

Thank you for any response,

Jan