cancel
Showing results for 
Search instead for 
Did you mean: 

software i2c not working..

hitsumen
Associate II
Posted on March 09, 2012 at 16:41

Want to read my LIS302 sensor with software I2C (bit banging)

Hardware i2c works.

Here is some code.

Please help me with software i2c...

http://pastebin.com/d0M9jRaY

21 REPLIES 21
hitsumen
Associate II
Posted on March 15, 2012 at 23:07

I use Keil uvision armcc c compiler v 4.1.0.894.

About timing..  For example, I took the function delay(int); from some keil library. It looks like this:

static void delay (int cnt) {

  cnt <<= 18;

  while (cnt--);

}

now we make some led blink test for 1 sec. I found that 1 sek = delay(40); 40 <<== 18 ~= 10kk, so if 1-- is equal to 1 tick then we have 10MHz freq right? 

My test looked like this..

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); 

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_13;

  GPIO_Init(GPIOD, &GPIO_InitStructure); 

  

   while(1)

{

GPIOD->BRR = 1<<3;

GPIOD->BRR = 1<<4;

        GPIOD->BRR = 1<<13;

delay(40);

        GPIOD->BSRR = 1<<3;

GPIOD->BSRR = 1<<4;

GPIOD->BSRR = 1<<13;

        delay(40);

}

lis302dl in i2c can run at 400khz.

I tried to use 100hz to 400khz frequency, nothing helped.. i2c hardware read function looks which works looks like this:

uint8_t I2C_Read(uint8_t DeviceAddr, uint8_t RegisterAddr)

{

  I2C_InitTypeDef I2C_InitStructure;

  uint8_t Temp_Addr = DeviceAddr;

  Temp_Addr &= ~0x0001;  

  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

  I2C_InitStructure.I2C_OwnAddress1 = 0x00;

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

  I2C_InitStructure.I2C_ClockSpeed = 400000;

  

  I2C_Init(I2C1, &I2C_InitStructure);

  

  I2C1->CR1 |= 0x0100; //generate i2c start

  while(!(I2C1->SR1 & 0x0001)); //checking when start is sent 

  I2C1->CR1 &= ~0x0400; //dissable ack

 

  I2C1->DR = Temp_Addr; //sending address to transmitter

    

  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  

  I2C1->DR = RegisterAddr; //sending address   

  

  I2C1->CR1 |= 0x0100;    //ganerate start

  

  while(!(I2C1->SR1 & 0x0001)); //checking when start is sent

  

  I2C1->DR = DeviceAddr+1;  //sending adress to receiver

  

  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

  

  I2C1->CR1 |= 0x0200;      //sending stop bit  

  

  return (uint8_t)I2C1->DR; // reading data and returning

  

}

frankmeyer9
Associate II
Posted on March 16, 2012 at 11:59

Just to add my 2 cent...

i2c ist static, so you can set a breakpoint and single step through the send/receive code.

This way you can check the levels even with a voltmeter.

I have done it this way. I used bitbanging code, because it was available, tested and proven.

You will have to trim those delay routines to the hardware - this part is less portable.

My first advice would be to singlestep through the adressing, and check for an ACK from the target. Also check if the address is correct. A lot of datasheets specify 7-Bit adresses, the LSB is implicit. This could be confusing.

emalund
Associate III
Posted on March 19, 2012 at 15:33

<i>I use Keil uvision armcc c compiler v 4.1.0.894.

About timing..  For example, I took the function delay(int); from some keil library. It looks like this:

static void delay (int cnt) {

  cnt <<= 18;

  while (cnt--);

}

now we make some led blink test for 1 sec. I found that 1 sek = delay(40); 40 <<== 18 ~= 10kk, so if 1-- is equal to 1 tick then we have 10MHz freq right? </i>

what does some arbitrary delay (who cares if the LED blinking rate would change some day) have to do with what you are doing?

somehow cut and pase do not work any more, but the single stepping is a good idea, just remember it say Nothing about your timing, you WILL need a scopt to check that

Erik.

frankmeyer9
Associate II
Posted on March 19, 2012 at 17:00

If you referring to my comment, I totally agree with you.

A simple busy-loop delay is somehow arbitrary. If you use it here, you have to measure and adapt everywhere else. But using bitbanging has another, even greater disadvantage. Usually, a sequence of 3, 4 or more consecutive read/write accesses is required to get one value in or out. This ties up the controller for milliseconds, basically doing almost nothing all the time.

Having been plagued by company-owned bitbanging code for long times, I just wanted to call attention to the most common mistake : not actually addressing the slave.

If the address is not correct, the rest is futile. So one should see an ACK from the slave, either with the scope or with a voltmeter.

frankmeyer9
Associate II
Posted on March 19, 2012 at 17:01

If you referring to my comment, I totally agree with you.

A simple busy-loop delay is somehow arbitrary. If you use it here, you have to measure and adapt everywhere else. But using bitbanging has another, even greater disadvantage. Usually, a sequence of 3, 4 or more consecutive read/write accesses is required to get one value in or out. This ties up the controller for milliseconds, basically doing almost nothing all the time.

Having been plagued by company-owned bitbanging code for long times, I just wanted to call attention to the most common mistake : not actually addressing the slave.

If the address is not correct, the rest is futile. So one should see an ACK from the slave, either with the scope or with a voltmeter.

emalund
Associate III
Posted on March 19, 2012 at 17:46

fm,

you may not have noticed, since the OP insist on including the kitchen sink in all his posts, that the OP does not want to develope bit-banging I²C but ''something similar'' and am using this a an excersize.

my first post was ''WHY?'' since I agree that bit-banging I²C is just about the ultimate performance/functionality destroyer. I recall the 'interesting' constructs from the days before HW I²C to get around the performance kill (one bit per cycle through the main loop, ....)

Erik

frankmeyer9
Associate II
Posted on March 20, 2012 at 09:01

Erik, I think you are right.

This reminds me on a story called 'Siddhartha' by H. Hesse. Even the most enlighted man was not able to pass his live experiences on to his son.

I guess everybody must touch this bare wire himself.

pkumar1883
Associate II
Posted on March 20, 2012 at 12:15

nikolaj

could you please tell me, what do you mean by Hardware I2C?

emalund
Associate III
Posted on March 20, 2012 at 14:22

RTFM

the STM32 has a hardware I²C engine as describ ed in the documentation.

Erik

hitsumen
Associate II
Posted on March 21, 2012 at 11:59

Hardware: There is a some electronics inside the microcontroller, that is used for I2C, so in this case, you can shift your data to/from the registers easily.

Software: You can simulate the hardwarish I2C, sending data manually bit by bit.. but nobody recommend on doing this..

If you need some code samples of both, I can share(but software does not work, trying to figure out what is wrong..)..

So what if I do not get an ACK?

Maybe you people have some code sample of software I2C, or something?