STM32 i2c Idle sorunu.

Başlatan NaMcHo, 24 Nisan 2011, 22:17:09

NaMcHo

Merhabalar
i2c startı verdikden sonra I2C1->SR2 registerındaki BUSY biti 1 de kalıyor(1: Communication ongoing on the bus) ve ilerlemiyor program.Neden kaynaklanıyor olabilir bu?(PCLK1 frekansım 8MHz) i2c hattını 2.9V(STM32 kitinin 3V3  yazan pininden.) ile besliyorum 4.7k pullup dirençler ile.Atmel24C02 eepromuna bişeyler yazıp sonra okumaya çalışıyorum.

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);                          //Eeprom word adresi yollanıyor.
	i2c_write('A');                              //A karakteri 0x00 adresine yazılıyor.
	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;			//1000ns SCL rise time(bu nerden geliyor?)  (1000/Tpclk1)+1=9 , I did Pclk1 = 8MHz so  Tpclk1 = 125ns
	I2C1->CR1 &= 0x0000;
	I2C1->CR1 |= 0x0400;			//ACK: Acknowledge enable
	I2C1->CR1 |= 0x0001;			//PE: Peripheral 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);



X-Fi

Hocam alttaki linkdeki uygulamalar arasında I2C donanımını çalıştırmıştım bi göz atmanızı öneririm.

http://www.expkits.com/pub/EX33DS_STM32_XFi_C_Samples.rar
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)

NaMcHo

#2
Teşekkür ettim debug yaparak inceliyim register değişimlerini.Pullup lar ve Vcc de sorun olma ihtimali varmıdır aceba çünki startı veriyorum sonra hat idle durumuna geçemediğine göre sanırsam 24C02 ye start komutu gitmiyor...
Büyük ihtimalle I2C çalışma hızı ayarlarında sorun var sanırsam gerçi datasheettekinin 1e bir aynısı yaptım ,  Thigh = CCR * TPCLK1   Tlow = CCR * TPCLK1
SCL nin datayı iletirken high ve low da kalma süre formülleri bunlar.I2Cx->CR2  deki FREQ 'ın belirlendiği 5 bitlik alan var FREQ=Fpclk1/1000000  benim PCLK1 clockğum 8MHz yani FREQ 8yazıyorum. CCR ise (pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1)) bu formülden bulunuyor bunun sonucuda 40 çıkıyor.
Rise time denilen sürede I2Cx->TRISE registerından ayarlanıyormuş oda FREQ+1=9 yazıyorum.ilk start verildikten sonra SCL ve START low dakalıyor ne hikmetse.SCL sürekli low da kalıyorsa demekki bu değerlerde sorun var.

Birde SR1-SR2 deki değişimleri kesmeler ile kontrol etmeyi deniyim.