2011-04-24 04:37 AM
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-swd2011-04-24 12:30 PM
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);
-----------------------------------------------------------------------------------------------------------
2012-11-29 11:06 AM
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);