STM32F saç baş yolduran I2C problemi (AF, BUSY.. vs)

Başlatan strom, 01 Mayıs 2014, 23:47:39

strom

Herkese iyi forumlar.

Elimde STM32F407, STM32F429 ve STM32F207 geliştirme kitleri var. Bunlarla bazı I2C protokolüne sahip cihazları kontrol etmeye çalışıyorum (mpu6050, hmc5883, d6t,...) ancak gel gelelim denemediğim kütüphane, denemediğim yöntem kalmadığı halde bu cihazlardan sürekli bir ölçüm alamadım. Sürekli ölçümden kastım; mesela I2C_ReadByte fonksiyonumuz olsun ve bu fonksiyon X adresinde register'ın değerini bize döndürsün. Fonksiyonu while içerisine yazıyorum ve tam kodun üzerine breakpoint koyuyorum. Her "run" tuşuna bastığımda fonksiyonu birkez çalışıtırıyor. İşte durum tam buyken sorunsuz bir şekilde 3-5 okuma yapıyor ama run tuşuna hızlı bastığımda veya tekrar sayısını artırdığımda bağlantıyı kaybediyorum. Bağlantıyı kaybetmekten kastımıda birkaç senaryoyla açıklamaya çalışayım.
Senaryo 1:
SR1&SR2 yazmaçları 0x3001 değerini alıyor. Kullandığım bütün kütüphanelerde bu kombinasyonu karışlıyan bir event handler yok. Bu yüzden kodda "while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_MODE_SELECT));" tarzı döngülerde sıkışıp kalıyorum.

Senaryo 2:
Durup durmadık yere AF (Arbitration Lost) hatası alıyorum. Bu durumda da program bir while() kontrolü içinde sıkışıyor.

Senaryo 3: (En kötüsü)
Bazen sadece busy biti 1 kalıyor. Bu durum en berbatı. Reset atmak, fişi takıp çıkarmak filan hiçbir işe yaramıyor. Kafayı yedirti bana. Hiçbir modül bağlamıyorum, sadece I2C modlünü aktif ediyorum yinede BUSY biti anında set oluyor. Veya modülü bağlıyorum ama veri göndermiyorum yine daha I2C modülünü hazırlar hazırlamaz BUSY biti 1 oluyor. Gücü kesiyorum, reset atıyrum olmuyor.
Bu durum saatlerimi aldı. Hem 429'da hem 407 denedim sorun aynıydı. Sensörde sorun var mı diye 3 farklı sensör denedim yine deişmedi. Tam bu noktada zilyon tane farklı kütüphane ve varyasyon denedim ama yinede düzeltemedim. En sonunda STM'nin kendi kütüphaneleri içinde şu fonksiyonu buldum ve bu sorunu hallettim;
uint8_t IOE_TimeoutUserCallback(void)
{
  I2C_InitTypeDef I2C_InitStructure;

  I2C_GenerateSTOP(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, DISABLE);
  
  IOE_GPIO_Config();

  /* CODEC_I2C peripheral configuration */
  I2C_DeInit(IOE_I2C);
  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 = 100000;
  
	I2C_DMACmd(I2C1, ENABLE);
	I2C_DMALastTransferCmd(I2C1, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
  /* Enable the I2C peripheral */
  I2C_Cmd(IOE_I2C, ENABLE);  
  I2C_Init(IOE_I2C, &I2C_InitStructure);
  
  return 0;
}

Sorunu çözdü ama niye olduğu hakkında hiçbir fikrim yok.

Neyse gelelim senaryo 1 ve 2'ye. Şimdi gün içeriisnde bir çok deneme yaptım ve en son DMA kullanarak olayı çözmeye çalıştım. Daha sonra her while kontrolü içerisinde TimeOut koyarak, belli bir süre içinde çıkmazsa "IOE_TimeoutUserCallback" içine gidecek şekilde ayarladım. Daha sonra AF hatası içinde kesme hazırlayarak, bu hata geldiğinde kesme içerisinde "IOE_TimeoutUserCallback" fonksiyonunu çağırdım. Bu biraz olsun çözüm oldu. Program içinde defalarca IOE_TimeoutUserCallback fonksiyonu çağırılmak zorunda kalsada bir çözüm oldu. Buna rağmen çok ilginçtir yine bir noktadan sonra kesmeye girmemeye başlıyor ve program yine tıkanıyor.

Yaptığım birkaç kod denemesine paylaşayım:

DMA + Timer kullanarak:

Not: Bu kodda kesmeler anlamadığım bir sebepten çalışmıyor. Timer saymaya devam etmesine rağmen 2 defa kesme oluştuktan sonra bir daha kesme fonksiyonuna girmiyor. I2C error kesmesinede sadece 1 kez giriyor ve uygun koşul oluşsa bile bir daha kesmeye girmiyor.

void I2C_BufferRead(I2C_TypeDef* I2Cy, u8 slaveAddr, u8* pBuffer, u8 readAddr, u16 NumByteToRead)
{
 // ENTR_CRT_SECTION();

  /* While the bus is busy */
  while(I2C_GetFlagStatus(I2Cy, I2C_FLAG_BUSY));

  /* Send START condition */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send MPU6050 address for write */
  I2C_Send7bitAddress(I2Cy, slaveAddr, I2C_Direction_Transmitter); 

  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(I2Cy, ENABLE);

  /* Send the MPU6050's internal address to write to */
  I2C_SendData(I2Cy, readAddr);

  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send STRAT condition a second time */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send MPU6050 address for read */
  I2C_Send7bitAddress(I2Cy, slaveAddr, I2C_Direction_Receiver);

  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2Cy, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	DMA_SetCurrDataCounter(DMA1_Stream5, NumByteToRead);
	DMA_Cmd(DMA1_Stream5, ENABLE);
	

  /* Enable Acknowledgement to be ready for another reception */

//  EXT_CRT_SECTION();

}


void I2C_ReSend()
{
	IOE_TimeoutUserCallback();
	I2C_BufferRead(I2C1, (0x0A << 1), data, 0x4C, 35);
}


extern "C"
{
	void DMA1_Stream5_IRQHandler()
	{
		DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5 |DMA_IT_HTIF5); 
		//DMA_ClearFlag(DMA1_Stream5, DMA_IT_TCIF5 |DMA_IT_HTIF5);

		I2C_GenerateSTOP(I2C1, ENABLE);
		I2C_AcknowledgeConfig(I2C1, ENABLE);

	}
	
	void I2C1_ER_IRQHandler()
	{
		I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
		//I2C_ClearFlag(I2C1, I2C_IT_AF | I2C_IT_ARLO);
		IOE_TimeoutUserCallback();
		I2C_ReSend();
	}
	
	void TIM7_IRQHandler()
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
		I2C_BufferRead(I2C1, (0x0A << 1), data, 0x4C, 35);		

	}

}


void	initI2C1()
{
	GPIO_InitTypeDef gpio;
	I2C_InitTypeDef i2c;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOBEN, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1EN, ENABLE);
	

	gpio.GPIO_Mode = GPIO_Mode_OUT;
	gpio.GPIO_OType = GPIO_OType_OD;
	gpio.GPIO_PuPd = GPIO_PuPd_UP;
	gpio.GPIO_Speed = GPIO_Speed_50MHz;
	gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Init(GPIOB, &gpio);
	//Setting alternating functions
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);


	
	I2C_SoftwareResetCmd(I2C1, ENABLE);
	I2C_SoftwareResetCmd(I2C1, DISABLE);


	i2c.I2C_Ack = I2C_Ack_Enable;
	i2c.I2C_ClockSpeed = 100000;
	i2c.I2C_DutyCycle = I2C_DutyCycle_2;
	i2c.I2C_Mode = I2C_Mode_I2C;
	i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	i2c.I2C_OwnAddress1 = 0x1E;
	I2C_Init(I2C1, &i2c);

	I2C_DMACmd(I2C1, ENABLE);
	I2C_DMALastTransferCmd(I2C1, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
	
	I2C_Cmd(I2C1, ENABLE);
	

}


void dmaInit()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_DMA1EN, ENABLE);
	
	DMA_InitTypeDef dma;
	dma.DMA_BufferSize = 35;
	dma.DMA_Channel = DMA_Channel_1;
	dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
	dma.DMA_Memory0BaseAddr = (uint32_t)data;
	dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
	dma.DMA_Mode = DMA_Mode_Normal;
	dma.DMA_PeripheralBaseAddr = (uint32_t) &I2C1->DR;
	dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	dma.DMA_Priority = DMA_Priority_High;
	DMA_Init(DMA1_Stream5, &dma);
	
	NVIC_InitTypeDef nvic;
	nvic.NVIC_IRQChannel = DMA1_Stream5_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 1;
	nvic.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&nvic);
	
	nvic.NVIC_IRQChannel = I2C1_ER_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 1;
	nvic.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&nvic);
	
	
	DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);

	
}


int main()
{

	Init();

	dmaInit();
	initI2C1();

	IOE_TimeoutUserCallback();
	timerInit();
	while(1)
	{
	}
}


DMA ve TimeOut kullanarak:

bool I2C_EventTimeOut(I2C_TypeDef* I2Cy, uint32_t event)
{
	uint32_t timeOut = 0xFFFF;
	while(!I2C_CheckEvent(I2Cy, event))
	{
		if(timeOut-- == 0) return 0;
	}
	return 1;
	
}

void timerInit()
{
	
}

void IOE_GPIO_Config()
{

  GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOBEN, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1EN, ENABLE);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  
  RCC_APB1PeriphResetCmd(RCC_APB1RSTR_I2C1RST, ENABLE);
  RCC_APB1PeriphResetCmd(RCC_APB1RSTR_I2C1RST, DISABLE);
	
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
    
  /* IOE_I2C SCL and SDA pins configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);	
}

uint8_t IOE_TimeoutUserCallback(void)
{
  I2C_InitTypeDef I2C_InitStructure;

  I2C_GenerateSTOP(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, DISABLE);
  
  IOE_GPIO_Config();

  /* CODEC_I2C peripheral configuration */
  I2C_DeInit(IOE_I2C);
  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 = 100000;
  
		I2C_DMACmd(I2C1, ENABLE);
	I2C_DMALastTransferCmd(I2C1, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
  /* Enable the I2C peripheral */
  I2C_Cmd(IOE_I2C, ENABLE);  
  I2C_Init(IOE_I2C, &I2C_InitStructure);
  
  return 0;
}
void I2C_ReSend()
{
	IOE_TimeoutUserCallback();
	I2C_SendCmd(I2C1, 0x0A, 0x4C);
	I2C_TriggerRead(I2C1,0x0A); 
}

bool I2C_SendCmd(I2C_TypeDef *I2Cy, uint8_t slaveAddr, uint8_t cmd)
{
  /* Send START condition */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
	//while (I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_SB) == RESET);
	
  /* Send MPU6050 address for write */
  I2C_Send7bitAddress(I2Cy, (slaveAddr << 1), I2C_Direction_Transmitter);

  /* Test on EV6 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;

  /* Send the MPU6050's internal address to write to */
  I2C_SendData(I2Cy, cmd);

  /* Test on EV8 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;

  /* Send STOP condition */
  I2C_GenerateSTOP(I2Cx, ENABLE);	
	
	return 1;
}
bool I2C_TriggerRead(I2C_TypeDef *I2Cy, uint8_t slaveAddr)
{
	DMA_SetCurrDataCounter(DMA1_Stream5, 35);
	DMA_Cmd(DMA1_Stream5, ENABLE);
  /* Send START condition */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_MODE_SELECT)) return 0;	
	
  /* Send address for read */
  I2C_Send7bitAddress(I2Cy, (slaveAddr<<1), I2C_Direction_Receiver);

  /* Test on EV6 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;	
	
}
bool I2C_Trigger(I2C_TypeDef *I2Cy, uint8_t slaveAddr, uint8_t cmd)
{
  /* Send START condition */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
	//while (I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_SB) == RESET);
	
  /* Send MPU6050 address for write */
  I2C_Send7bitAddress(I2Cy, (slaveAddr << 1), I2C_Direction_Transmitter);

  /* Test on EV6 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;

  /* Send the MPU6050's internal address to write to */
  I2C_SendData(I2Cy, cmd);

  /* Test on EV8 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;	
	
	DMA_SetCurrDataCounter(DMA1_Stream5, 35);
	DMA_Cmd(DMA1_Stream5, ENABLE);
  /* Send START condition */
  I2C_GenerateSTART(I2Cy, ENABLE);

  /* Test on EV5 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_MODE_SELECT)) return 0;	
	
  /* Send address for read */
  I2C_Send7bitAddress(I2Cy, (slaveAddr<<1), I2C_Direction_Receiver);

  /* Test on EV6 and clear it */
  if(!I2C_EventTimeOut(I2Cy, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;	
}

extern "C"
{
	void DMA1_Stream5_IRQHandler()
	{
		DMA_ClearFlag(DMA1_Stream5, DMA_IT_TCIF5 |DMA_IT_HTIF5);
		//if(!I2C_SendCmd(I2C1, 0x0A, 0x4C)) I2C_ReSend();
		//if(!I2C_TriggerRead(I2C1,0x0A)) I2C_ReSend(); 
		if(!I2C_Trigger(I2C1,0x0A, 0x4C)) I2C_ReSend(); 
		I2C_GenerateSTOP(IOE_I2C, ENABLE);

	}
	
	void I2C1_ER_IRQHandler()
	{
		I2C_ClearFlag(I2C1, I2C_IT_AF | I2C_IT_ARLO);
		IOE_TimeoutUserCallback();
		I2C_ReSend();
	}
	
	void I2C1_EV_IRQHandler()
	{
		I2C_ClearFlag(I2C1, I2C_IT_SB);
		IOE_TimeoutUserCallback();
		I2C_ReSend();
	}
}







void init()
{
	

  IOE_GPIO_Config();
	
  I2C_InitTypeDef I2C_InitStructure;


  if ((I2C1->CR1 & I2C_CR1_PE) == 0)
  {   
    /* IOE_I2C configuration */
    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 = 100000;
  
    /* Initialize the I2C peripheral */
    I2C_Init(I2C1, &I2C_InitStructure);
  
    /* Enable the I2C peripheral */
    I2C_Cmd(I2C1, ENABLE);
  }   
}

void	initI2C1()
{
	GPIO_InitTypeDef gpio;
	I2C_InitTypeDef i2c;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOBEN, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1EN, ENABLE);
	

	gpio.GPIO_Mode = GPIO_Mode_OUT;
	gpio.GPIO_OType = GPIO_OType_OD;
	gpio.GPIO_PuPd = GPIO_PuPd_UP;
	gpio.GPIO_Speed = GPIO_Speed_50MHz;
	gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Init(GPIOB, &gpio);
	//Setting alternating functions
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);


	
	I2C_SoftwareResetCmd(I2C1, ENABLE);
	I2C_SoftwareResetCmd(I2C1, DISABLE);


	i2c.I2C_Ack = I2C_Ack_Enable;
	i2c.I2C_ClockSpeed = 100000;
	i2c.I2C_DutyCycle = I2C_DutyCycle_2;
	i2c.I2C_Mode = I2C_Mode_I2C;
	i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	i2c.I2C_OwnAddress1 = 0x1E;
	I2C_Init(I2C1, &i2c);

	I2C_DMACmd(I2C1, ENABLE);
	I2C_DMALastTransferCmd(I2C1, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
	I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
	
	I2C_Cmd(I2C1, ENABLE);
	

}

void dmaInit()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_DMA1EN, ENABLE);
	
	DMA_InitTypeDef dma;
	dma.DMA_BufferSize = 35;
	dma.DMA_Channel = DMA_Channel_1;
	dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
	dma.DMA_Memory0BaseAddr = (uint32_t)data;
	dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
	dma.DMA_Mode = DMA_Mode_Normal;
	dma.DMA_PeripheralBaseAddr = (uint32_t) &I2C1->DR;
	dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	dma.DMA_Priority = DMA_Priority_High;
	DMA_Init(DMA1_Stream5, &dma);
	
	NVIC_InitTypeDef nvic;
	nvic.NVIC_IRQChannel = DMA1_Stream5_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 1;
	nvic.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&nvic);
	
	nvic.NVIC_IRQChannel = I2C1_ER_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 1;
	nvic.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&nvic);
	
	
	DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);
	DMA_Cmd(DMA1_Stream5, ENABLE);
	
}





int main()
{

	Init();
	dmaInit();
	initI2C1();
	IOE_TimeoutUserCallback();
		//if(!I2C_SendCmd(I2C1, 0x0A, 0x4C)) I2C_ReSend();
		//if(!I2C_TriggerRead(I2C1,0x0A)) I2C_ReSend(); 
		if(!I2C_Trigger(I2C1,0x0A, 0x4C)) I2C_ReSend(); 
	 // I2C_Read(I2C1, 0x0A, 0x4C, data,  35, LITTLE_ENDIAN);

	while(1)
	{
		//I2C_BufferRead(0x14, data, 0x4C, 36);



Aslında kullanmak istediğim sensör d6t isimli, temassız sıcaklık ölçer. Bu sensöre 0x4C verisini gönderince bize 35 tane veri gönderiyor. Doğru ölçüm almama rağmen sürekli olmuyor. Aynı durum MPU6050, HMC5883, STMPE811 ilede başıma geldi. Çözemedim bir türlü. Sorunun neden olduğu hakkında fikir bile yürütemiyorum. Bütün fikirlerim tükendi. Kafam çorba gibi şu an.

Bu arada forumda buna benzer konular tartışıldğını hatırlıyorum ama google'da picproje için özel arama yapmama rağmen bi kaç topik dışında bişey çıkmadı. Acaba bende mi bir sorun var yoksa forumda mı?

erayurtseven

yaklaşık bir haftaadır aynı problemle bende uğraşıyorum. LIS302DL ile haberleşmeye çalışıyorum. Belirttiğiniz hatalardan kesin biri sorun çıkarıyor.

Birkaç foruma bende yazdım. Ancak cevap yok.

Deneyimi olan arkadaşlar yardımcı olursa sevinirim

erayurtseven

#2
strom  tekrar merhaba,

Bugün halletim ben, projeyi.

Öncelikle busy bayrağının sürekli set olmasının nedeni senin sensörden ek alman ama haberleşmeyi bitirememenden kaynaklanıyor. Dediğin gibi de busy bayrağı kolay kolay resetlenmiyor. ben 2-3 dk fişten çekerek yada başka bir program yükleyerek sıfırlıyordum.

arbitrration lost hatası ile ben hiç karşılaşmadım dolayısıyla ona yprum yapamıycam,

programın busy dışında çakması ise,benim adım adım debug etmemden kaynaklanıyormuş. yani data gönderme yada okuma işlemlerinde ve fonksiyonun içine girip, start condition, slave adress gönder ...... şeklinde tek tek yapıyordum. dolayısıyla, slave in 10us de gönderdiği ACK i yakalayamıyordum.

dolayısıyla data gönder ve data oku fonksiyonlarının debug ederken atlayarak(keil da f10 ile) debug edersem sıkıntı olmuyor.

Son olarak bu anlattıklarımı uygulamama rağmen data okurken sıkıntı oluyordu. bu sıkıntıyı data okuma yaparken ack disable yaparak aştım.
   
         ..........................
        I2C_Send7bitAddress(I2C1, address, I2C_Direction_Receiver);
   Delay(15);          // 15us
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
   uc = I2C_Read(0);
   I2C_GenerateSTOP(I2C1, ENABLE);
   I2C_Config();
   uc = I2C_Read(0);
   I2C_GenerateSTOP(I2C1, ENABLE);

I2C_Read fonksiyonu;
/******************************************************************************/
unsigned char I2C_Read (int ack)
{
  /* Enable/disable Master acknowledge                                        */
  if (ack) I2C1->CR1 |=  0x0400;
  else     I2C1->CR1 &= ~0x0400;

  while (!(I2C_sr() & 0x00000040));     /* Wait until RxNE bit set            */
  return (I2C1->DR);
}
umarım bu bilgiler yardımcı olur da sen de kurtulursun