cancel
Showing results for 
Search instead for 
Did you mean: 

I have a problem with i2c communication(I have written my i2c library)

xavius
Associate II
Posted on April 24, 2011 at 13:37

Hi

i2c.c

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

&sharpinclude <stm32f10x.h>

&sharpinclude ''i2c.h''

void i2c_hazirla(void) //i2c_init function.

{

RCC->APB1RSTR = 0x00200000; //I2C1 reset.

RCC->APB1RSTR &=0xFFDFFFFF; //I2C1 exit at reset state.

RCC->APB1ENR |= 0x00200000; //I2C1 clock enabled.

//I2C1 PB8,PB9(SCL,SDA) 

AFIO->MAPR &= 0x00000000;

AFIO->MAPR |= 0x00000002;

GPIOB->CRH &= 0x00000000;

GPIOB->CRH |= 0x000000DD; //OpenDrain,Max 10MHz

I2C1->CR2 |= 0x0008; //Freq = 8MHz

I2C1->CCR |= 0x0028;

I2C1->TRISE &= 0x0000;

I2C1->TRISE |= 0x0009; //1000ns SCL rise time  (1000/Tpclk1)+1=9 , I did Pclk1 = 8MHz so  Tpclk1 = 125ns

I2C1->CR1 &= 0x0000;

I2C1->CR1 |= 0x0001; //PE: Peripheral enable

I2C1->CR1 |= 0x0400; //ACK: Acknowledge enable

}

void i2c_baslat(void)   //i2c_start funciton.

{

i2c_mesgul(); //wait for idle.

I2C1->CR1 |= 0x0100; //Start verildi(START BIT = 1)

while(!(I2C1->SR1 & 0x0001)); //Wait to SB bit is set.

}

void i2c_durdur(void) //i2c_stop funciton.

{

i2c_mesgul(); //wait for idle.

I2C1->CR1 |= 0x0200; //Stop

}

void i2c_restart(void)

{

i2c_mesgul();

I2C1->CR1 |= 0x8000; //software reset.

}

unsigned char i2c_adress_yaz(unsigned char adress) //I'm writing Atmel24C02 eeprom's adress here.

{

I2C1->DR = adress;

i2c_mesgul();

I2C1->OAR1 |= 0x4000; //14.bit 1 olmak zorundaym??(In datasheet says, this 14th bit must be Set.)

i2c_mesgul();

while(!(I2C1->SR1 & 0x0002)); //ADDR bit . if this bit did set so this means I already sent Device adress.

return 1;

}

unsigned char i2c_yaz(unsigned char data) //i2c_write  funciton.

{

i2c_mesgul();

I2C1->DR = data;

// while(!(I2C1->SR1 & 0x0004));

return 1;

}

unsigned char i2c_oku(unsigned char wadress) //i2c_read funciton.

{

unsigned char data=0;

i2c_mesgul();

i2c_yaz(wadress);

i2c_mesgul();

data=I2C1->DR;

return (unsigned char)data;

}

void i2c_mesgul(void) //i2c_busy  funciton.

{

while((I2C1->SR2 & 0x0002)); //wait for Idle.

}

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

i2c.h

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

extern void i2c_hazirla(void);   //i2c_init funciton

extern void i2c_baslat(void); //i2c_start funciton

extern void i2c_durdur(void); //i2c_stop funciton

extern void i2c_restart(void);

extern unsigned char i2c_adress_yaz(unsigned char adress); //i2c_deviceadress_write  funciton.

extern unsigned char i2c_yaz(unsigned char data); //i2c_write  funciton.

extern unsigned char i2c_oku(unsigned char wadress); //i2c_read funciton.

extern void i2c_mesgul(void); //i2c_busy funciton.

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

I'm trying to send data of my Atmel24C02 eeprom then read it.

The problem is:After I started i2c with i2c_baslat() funciton ,The BUSY(I2C_SR2 register's first bit) bit staying at 1 so I cant pass the idle state to write Atmel24c02 device adress.

 

I'm supplying i2c bus with +4.5V(with stm32's 5V pin) and the pull ups resistors are 4.7k

 

 

main.c

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

&sharpinclude <stm32f10x.h>

&sharpinclude ''LCD.h''

&sharpinclude ''i2c.h''

void rcc_init(void);

void delay(unsigned long delay);

unsigned char x=0;

int main(void)

{

rcc_init();

GPIOC->CRL &= 0x0000000;

GPIOC->CRL |= 0x1111111; //10MHz max.

GPIOA->CRL &= 0x0000000; GPIOA->CRL |= 0x00000008; //PA0 input pulldown.

GPIOC->CRH &= 0x00000000; GPIOC->CRH |= 0x00000022; //2MHz max pushpull.

lcd_hazirla();

i2c_hazirla();

GPIOC->ODR = 0x00000300;

    

     //LD3 and LD4 are high.

i2c_baslat();

i2c_adress_yaz(0xA0); //24C02 device adress is 0b1010000(0)-> write mode. (A0=low,A1=low,A2=low) and 

i2c_yaz(0x00); //Eepromun 0x00h adresine gidiyoruz

i2c_yaz('N'); //0x00h adresine N yaz?ld?.

i2c_durdur();

i2c_baslat();

i2c_adress_yaz(0xA1);

x=i2c_oku(0x00);

i2c_durdur();

imlec(1,1);

lcd_karakter(x);

for(;;);

}

void rcc_init(void)

{

RCC->CR |= 0x00030000; //HSEON=1

while(!(RCC->CR & 0x00020000));   //Wait to HSE be stabilized

RCC->CIR |= 0x00080000; //HSERDYC: HSE ready interrupt cleared

RCC->CR |= 0x00080000; //Clock security system Enabled.

RCC->CIR |= 0x00800000; //CSSC: Clock security system interrupt cleared.

// RCC->CR |= 0x00040000; //HSE bypassed.

RCC->CFGR |= 0x06000001; //SW[1:0]=01: HSE selected as system clock , MCO[26:24] = 110: HSE clock selected 

RCC->APB2ENR |= 0x0000001D; //PORT A,B,C AFIO aktif.

}

void delay(unsigned long delay)

{

while(delay--);

}

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

Note:I never tryed i2c communitacion before , this is my first experience 🙂

#i2c-afio-remap-swd
2 REPLIES 2
xavius
Associate II
Posted on April 24, 2011 at 21:30

I did some change but still the same problem on going.

main.c

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

#include <stm32f10x.h>

#include ''LCD.h''

#include ''i2c.h''

void rcc_init(void);

void delay(unsigned long delay);

unsigned char x=1;

int main(void)

{

rcc_init();

GPIOC->CRL &= 0x00000000; GPIOC->CRL |= 0x11111111; //PC0-7 max 10MHz pushpull.

GPIOC->CRH &= 0x00000000; GPIOC->CRH |= 0x00000022; //PC8,PC9 max 2MHz pushpull.

GPIOA->CRL &= 0x00000000; GPIOA->CRL |= 0x00000008; //PA0 giris olarak ayarlandı pulldown.

GPIOC->ODR = 0x00000300;

i2c_init();

i2c_start();

i2c_send_adress(0xA0);

i2c_write(0x00);

i2c_write('A');

i2c_start();

i2c_send_adress(0xA1);

x=i2c_read(0x00);

lcd_hazirla();

imlec(1,1);

lcd_karakter(x);

for(;;);

}

void rcc_init(void)

{

RCC->CR |= 0x00030000; //HSEON=1

while(!(RCC->CR & 0x00020000));   //Wait to HSE be stabilized

RCC->CIR |= 0x00080000; //HSERDYC: HSE ready interrupt cleared

RCC->CR |= 0x00080000; //Clock security system Enabled.

RCC->CIR |= 0x00800000; //CSSC: Clock security system interrupt cleared.

RCC->CFGR |= 0x06000001; //SW[1:0]=01: HSE selected as system clock , MCO[26:24] = 110: HSE clock selected 

RCC->APB2ENR |= 0x0000001D; //PORT A,B,C AFIO aktif.

}

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

i2c.c

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

#include <stm32f10x.h>

#include ''i2c.h''

void i2c_init(void)

{

RCC->APB1RSTR = 0x00200000; //I2C1 reset.

RCC->APB1RSTR &=0xFFDFFFFF; //I2C1 exit at reset state.

RCC->APB1ENR |= 0x00200000; //I2C1 clock enabled.

//I2C1 PB8,PB9(SCL,SDA) 

AFIO->MAPR &= 0x00000000;

AFIO->MAPR |= 0x00000002;

GPIOB->CRH &= 0x00000000;

GPIOB->CRH |= 0x000000DD; //OpenDrain,Max 10MHz

I2C1->CR2 |= 0x0008; //Freq = 8MHz

I2C1->CCR |= 0x0028;

I2C1->TRISE &= 0x0000;

I2C1->TRISE |= 0x0009; //At Standart mode 1000ns SCL rise time(bu nerden geliyor?)  (1000/Tpclk1)+1=9 , I did Pclk1 = 8MHz so  Tpclk1 = 125ns

I2C1->CR1 &= 0x0000;

I2C1->CR1 |= 0x0001; //PE: Peripheral enable

I2C1->CR1 |= 0x0400; //ACK: Acknowledge enable

}

void i2c_start(void)

{

i2c_busy();

I2C1->CR1 |= 0x00000100; //Start = High

while(!(I2C1->SR1 & 0x00000001)) //Wait for SB bit is set,when start generated this bit will set.

i2c_busy(); //Wait for idle.

}

void i2c_stop(void)

{

i2c_busy();

I2C1->CR1 |= 0x00000200; //Stop = High

}

unsigned char i2c_write(unsigned char data)

{

i2c_busy();

I2C1->DR = data;

return 1;

}

unsigned char i2c_send_adress(unsigned char sadress)

{

i2c_busy();

I2C1->DR = sadress;

i2c_busy();

while(!(I2C1->SR1 & 0x00000002)); //When ADDR is set continue.

while(!(I2C1->SR1 & 0x00000080)); //Wait for TxN set(High=Data register empty) 

return 1;

}

unsigned char i2c_read(unsigned char wadress)

{

unsigned char data;

i2c_busy();

i2c_write(wadress);

i2c_busy();

data=I2C1->DR;

return data;

}

void i2c_busy(void)

{

while(I2C1->SR2 & 0x00000002); //Wait for idle.

}

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

i2c.h

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

extern void i2c_init(void);

extern void i2c_start(void);

extern void i2c_stop(void);

extern unsigned char i2c_write(unsigned char data);

extern unsigned char  i2c_send_adress(unsigned char sadress);

extern void i2c_busy(void);

extern unsigned char i2c_read(unsigned char wadress);

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

rob239955_stm1
Associate II
Posted on November 29, 2012 at 20:06

I was wondering if anybody figured this out.  I had I2C working, then (enabled) and set the AFIO remap to free up JTAG lines (we use the two-line SWD), and now my I2C doesn't work anymore.

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, DISABLE);