Lis302dl I2C İletişimi

Başlatan Mucit23, 05 Mart 2013, 15:39:50

Mucit23

Arkadaşlar Merhaba.

MCBSTM32C board üzerindeki LIS302DL ivme sensörünü çalıştırmak için uğraşıyorum.

Sensör Board üzerinde STM32F107 ye i2c donanımı üzerinden bağlanmış. SDA ve SCL hattı PB8 ve PB9 a bağlı. İnternette Bu protokol kullanarak iletişim kuran hiçkimse yok .

Ben bu iş için bir lis302dl nin datashetine ve örnek kodlara bakarak kütüphane yazdım fakat i2C donanımını çalıştıramadım.

Yazdığım kodlar bunlar.

LIS302DL.h

#include "stm32f10x_lib.h"
#include <stdint.h>

#define DEVICE_WRITE    0x38     // Default LIS302DL I2C address - write
#define DEVICE_READ     0x39     // Default LIS302DL I2C address - read
#define CONTROL_REG1    0x20 
#define I2C_SPEED       100000   // 100Khz speed for I2C

#define X_Axis          0x29     // X ekseni Out Registeri
#define Y_Axis          0x2B     // Y ekseni Out Registeri
#define Z_Axis          0x2D     // Z ekseni Out Registeri

#define SUCCESS    0
#define FAILURE    1

extern void I2C_Setup(void);
extern void LIS302DL_init(void);
extern char LIS302DL_Read_Axis(char reg);


LIS302DL.c

#include "LIS302DL.h"

void I2C_Setup(void){
	
	  GPIO_InitTypeDef GPIO_InitStructure;
	  I2C_InitTypeDef I2C_InitStructure;
	
	  RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	
	  /*GPIO configuration */
	  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9;
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	  GPIO_Init(GPIOB, &GPIO_InitStructure);
	 
	  /*I2C configuration */
	  I2C_DeInit(I2C1);
	  I2C_InitStructure. I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure. I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure. I2C_OwnAddress1 = 0xA0; // kullanilmiyor ama donanimsal olarak gerekli
    I2C_InitStructure. I2C_Ack = I2C_Ack_Enable; // ACK sinyalleri kullanilacak
    I2C_InitStructure. I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 bit adres + 1 bit RW
    I2C_InitStructure. I2C_ClockSpeed = I2C_SPEED;	// 100 kHz I2C hizi

    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);

}

void LIS302DL_init(void){
	I2C_Setup();  //I2C Donanimi Hazirlaniyor.
	
	I2C_GenerateSTART(I2C1,ENABLE);
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
	
	I2C_Send7bitAddress(I2C1,DEVICE_WRITE,I2C_Direction_Transmitter);
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
	
	I2C_SendData(I2C1,CONTROL_REG1);  //Control Reg1
	
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_SendData(I2C1,0x43);  //0b01000111 Xen=1, Yen=1, Zen=1, PD=1
	
	while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTOP(I2C1,ENABLE);
}

char LIS302DL_Read_Axis(char reg){
	char value;
	
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1,ENABLE);
	
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
	
	I2C_Send7bitAddress(I2C1,DEVICE_WRITE,I2C_Direction_Transmitter);
	
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
	
	I2C_SendData(I2C1,reg);
	
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTART(I2C1,ENABLE);
	
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
	
	I2C_Send7bitAddress(I2C1,DEVICE_READ,I2C_Direction_Receiver);
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
	
	value=I2C_ReceiveData(I2C1);
	
	I2C_GenerateSTOP(I2C1,ENABLE);
	return value;
}


Main Programım ise bu şekilde.

#include "stm32f107.h"
#include "string.h"
#include "LIS302DL.h"

#define     __IO    volatile  

char data;

int main()
{
		 SystemInit();              // Sistem Ayarlari yapiliyor..
		 initRS232(38400);          // RS232 Ayarlamalari yapiliyor
		 setTimer1(1000,0,0);       // Timer Ayarlamalari yapiliyor..
		 LIS302DL_init();           // LIS302DL ayarlari Yapiliyor.
		 setOutMode(portE,0xFFFF);  // PortE Çikis Yapildi.
		 setOutMode(portA,0xFFFF);  // PortA Çikis Yapildi.
		 setOutMode(portD,0xFFFF);  // PortD Çikis Yapildi. 
  while(1){
     data=LIS302DL_Read_Axis(X_Axis);
  }
}

void Timer1_Interrupt()
{   
    GPIO_Write(GPIOD,0xFFFF);
}


Program derleniyor.

İşlemciye yükleyip I2C hattını osiloskop ile izliyorum. I2C hattında hiçbir hareket görünmüyor. I2C donanım ayarlarındamı sıkıntı var? Normalde Bu şekilde çalışması gerekirdi. 


Mucit23

Arkadaşlar I2C de konfigürasyonunda eksik yaptığım şey nedir?

işlemci,

    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))

Bu komuta gelince donuyor.

I2C hiç çalışmıyor.

fatih6761

Alıntı yapılan: Mucit23 - 06 Mart 2013, 09:14:33
Arkadaşlar I2C de konfigürasyonunda eksik yaptığım şey nedir?

işlemci,

    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))

Bu komuta gelince donuyor.

I2C hiç çalışmıyor.
Hocam buraya aktarırken mi yanlışlık oldu yoksa while parantezinin sonunda ';' noktalı virgül yok mu?

Mucit23

Yok hocam yazım hatası yok. Derleniyor program. Sanırım buraya aktarırken koymamışım.

Bu i2C işi canımı sıkmaya başladı. Bugün başka kodlar buldum. Yine i2C kullanılıyor ama kütüphane yok. Yarın birde onu deneyeceğim.

Sanırım I2C kütüphanesi biraz sıkıntılı. Google den anladığım kadarıyla tek sıkıntı çeken ben değilim.

muhittin_kaplan

mucit f4 e göre hazırlanmış bir örnek var ı2c için(standart kütüphane ile). belki birşeyler çıkar
http://www.coocox.org/repo/cb48a1c0-d0ad-11e1-918f-60eb69f2f4ad/example/7b4eee90-d143-11e1-9217-60eb69f2f4ad/I2C_Exp.zip

Mucit23

Hocam Buldum birşeyler.

STM32F10X için yazılmış I2C kütüphanesini buldum. Elimdeki Deney kitinin Örnek kodlarından aldım. Deney kiti üzerindeki Touch çipi okunuyor.

Kendi Programıma oturttum. Şimdi Sensörü okumaya çalışıyorum.

Bundan önce Keilin Kendi ST kütüphanesi ile yazılmış birkaç örnek program üzerinde çalıştım fakat hiçbirinde çiple haberleşmeyi bırakın daha I2C yi bile çalıştıramadım.

Burada Kütüphane kullanılmamış. Register tabanlı işlem yapılmış(Bunun Bir adı varsa öğrenmek isterim)
Kütüphane kodları bunlar. Lazım olur.

I2C.h

/******************************************************************************/
/* I2C.h: I2C function prototypes                                             */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2005-2009 Keil Software. All rights reserved.                */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/

#include "stm32f10x_lib.h"
#include <stdint.h>

#ifndef _I2C_H
#define _I2C_H

extern void          I2C_Setup  (void);
extern void          I2C_Start  (void);
extern void          I2C_Stop   (void);
extern void          I2C_Addr   (unsigned char adr);
extern void          I2C_Write  (unsigned char c);
extern unsigned char I2C_Read   (int ack);
extern unsigned char I2C_getbyte(unsigned char address, unsigned char cmd);
extern void I2C_putbyte(unsigned char address, unsigned char cmd, unsigned char data);
extern unsigned short int I2C_getword(unsigned char address, unsigned char cmd);
#endif /* _I2C_H */


I2C.c

/******************************************************************************/
/* I2C_STM32.c: STM32 low level I2C routines                                  */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2005-2009 Keil Software. All rights reserved.                */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/

#include "I2C.h"

/************************ Local auxiliary functions ***************************/

/*******************************************************************************
* I2C communication status                                                     *
*   Parameter:                                                                 *
*   Return:               status                                               *
*******************************************************************************/

static __inline unsigned int I2C_sr (void) {
  unsigned int sr;

  sr  = I2C1->SR1;
  sr |= I2C1->SR2 << 16;
  return (sr);
}

/************************ Exported functions **********************************/

/*******************************************************************************
* Initialize I2C interface in master mode                                      *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Setup (void) {
  unsigned int tout;

  /* Enable clock for I2C1, GPIOB and AFIO                                    */
  RCC->APB2ENR |= (1 << 3) | (1 << 0); //
  RCC->APB1ENR |= (1 << 21);

  /* I2C1 pins remapped, use PB8, PB9                                         */
  AFIO->MAPR   |= 0x00000002;  // Remap=1: (SCL/PB8, SDA/PB9)
  GPIOB->CRH   |= 0x000000FF;  // Alternate IO PB8 and PB9

  I2C1->CR1     = 0x8000;               /* Reset I2C peripheral               */
  for (tout = 1000000; tout; tout--);
  I2C1->CR1     = 0x0000;

  /* Configure I2C peripheral                                                 */
  I2C1->CR1     = 0x0001;		// PE - Peripheral Enable
  I2C1->CR2     = 0x0024;	  	// Freq 36 MHz
  I2C1->CR1     = 0x0000; 		// PE Disable
  I2C1->TRISE   = 0x0025;  		//Time Rise - program when PE=0 
  I2C1->CCR     = 0x00B4;  		// 0x005A = 400 KHz (36MHz / 90) 	0x00B4 = 200 KHz
  I2C1->CR1    |= 0x0401;
  I2C1->OAR1    = 0x40A0;
}


/*******************************************************************************
* Generate start condition on I2C bus                                          *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Start (void) {
if ( I2C1->CR1 & ( 1 << 10 ) ) {
		I2C1->CR1 &= ~(1 << 10 );
	} 
  I2C1->CR1 |= 0x0100; //start genneration when bus free
  while (!(I2C_sr() & 0x0001));
}

/*******************************************************************************
* Generate stop condition on I2C bus                                           *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Stop (void) {

  I2C1->CR1 |= 0x0200;
  while (I2C_sr() & 0x00020000);        /* Wait until BUSY bit reset          */
}


/*******************************************************************************
* Write address on I2C interface                                               *
*   Parameter:    adr:    address to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Addr (unsigned char adr) {

  I2C1->DR = adr;
  while (!(I2C_sr() & 0x0002));	//Addr sent 
}


/*******************************************************************************
* Write a byte to I2C interface                                                *
*   Parameter:    c:      data to be written                                   *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Write (unsigned char c) {

  I2C1->DR = c;
  while (!(I2C_sr() & 0x00000004));     /* Wait until BTF bit set             */ 
}


/*******************************************************************************
* Read a byte from I2C interface                                               *
*   Parameter:                                                                 *
*   Return:               read data                                            *
*******************************************************************************/

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);
}

/******************************************************************************/

unsigned char I2C_getbyte(unsigned char address, unsigned char cmd) {
	unsigned char uc;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	uc = I2C_Read(0);		// Read 1 byte without Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( uc );
}

unsigned short int I2C_getword(unsigned char address, unsigned char cmd) {
	unsigned short int uw;
	//unsigned short int uw2;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	uw = I2C_Read(1) << 8;		// Read MSB  without Acknowledge
	uw |= I2C_Read(0); 			// Read LSB	 with Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( uw );
}
void I2C_putbyte(unsigned char address, unsigned char cmd, unsigned char data) {
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Write(data);		// Transfer Data to I2C device
	I2C_Stop();				// Stop I2C transfer
}

int I2C_getbytearray(unsigned char address, unsigned char cmd, int number, unsigned char *data) {
	int count;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	// Read number - 1 bytes with Acknowledge
	for ( count=0; count < number - 2; count++ ) {
		data[count] = I2C_Read(1);		// Read with Acknowledge
	}
	data[count] = I2C_Read(0);		// Last byte without Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( count+1 );
}



muhittin_kaplan

Alıntı YapBunun Bir adı varsa öğrenmek isterim
Low Level

Mucit23

#7
Hocam Sensörü okudum. X, Y ve Z eksen bilgilerini alabiliyorum.

Fakat biraz tutarsız. Bu sensörün kalibre edilmesi gibi bir olay mevcutmu, Örneğin sıfır ayarı. Mesela Düz bir zemine koyup değerleri sıfırlayabilir miyim.

Birde Z ekseni sürekli 60 geliyor. Bu yer çekiminden mi kaynaklanıyor? 

muhittin_kaplan

#8
Z ekseninde devamlı bir bilgi görmen normal.eğim yokken  x ve y de belli bir ofset değeri gören gerekir.

mesaj birleştirme:: 07 Mart 2013, 12:49:48

X yada Y yönünde 90 derece döndürdüğünde bu ofset değerinin düştüğünü yada arttığını görmen gerekir.

Mucit23

sıkıntı yok ozaman hocam

düz bir zemindeyken x ve y eksenlerinde +-4  birim ofset değeri var. Bu değerlerde +-1,birim sürekli oynuyor. (Bu okuduğum değerlerin bir birimi varsa öğrenmek isterim)

muhittin_kaplan

yer çekimi ivmesi "g", ama ölçüm değerinin max ı önemli 2 ve 8 oluyor sanırım.
(yerçekimi_ivmesi=okuduğun değer*(max_yerçekimi_ivmesi/2^8)
gibi birşey olması gerek)

Mucit23

Aldığım Değerler şuanda +-60 arasında değişiyor. Mesela Tam dik yaptığımda X ekseninin +-50-60 arası birşey olduğunu görüyorum. direk g değeri olması mümkün değil.

muhittin_kaplan

Açıyımı Hesaplayacaksın Mucit ?

Mucit23

Şimdilik Başka birşey yapıyorum ama aklıma gelmişken onuda yapayım bari :)



mistek

Aldığınız değeri hassasiyete böldünüz mü?
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R