AnsweredAssumed Answered

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

Question asked by yildiz.nazim.001 on Apr 24, 2011
Latest reply on Nov 29, 2012 by neff.rob

#include <stm32f10x.h>
#include "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)
     I2C1->CR1 |= 0x8000;                     //software reset.
unsigned char i2c_adress_yaz(unsigned char adress)           //I'm writing Atmel24C02 eeprom's adress here.
          I2C1->DR = adress;
          I2C1->OAR1 |= 0x4000;                    //14.bit 1 olmak zorundaymış(In datasheet says, this 14th bit must be Set.)
          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.
     I2C1->DR = data;
//     while(!(I2C1->SR1 & 0x0004));
     return 1;               
unsigned char i2c_oku(unsigned char wadress)           //i2c_read funciton.
     unsigned char data=0;
     return (unsigned char)data;
void i2c_mesgul(void)                              //i2c_busy  funciton.
     while((I2C1->SR2 & 0x0002));               //wait for Idle.

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

#include <stm32f10x.h>
#include "LCD.h"
#include "i2c.h"

void rcc_init(void);
void delay(unsigned long delay);
unsigned char x=0;
int main(void)
     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.

     GPIOC->ODR = 0x00000300;          //LD3 and LD4 are high.

     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ı.
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)

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