I2C iletişim protokolünde veri aktarımı için SDA (Serial Data Line) ve SCL (Serial Clock) olmak üzere iki adet haberleşme hattı bulunur. SDA, cihazlar arasındaki veri aktarımının sağlandığı hattır. Bu hatta çift yönlü veri aktarımı olur. Hatta aktarılan verilerin senkronizasyonu, SCL hattı ile gerçekleştirilir. . SDA hattındaki veri iletimi, SCL sinyaline göre düzenlenir. SDA ve SCL hatları, pull-up dirençlerle VCC hattına bağlanmalıdır. I2C haberleşen cihazların GNDlerinin ortak olması gerekmektedir.
İletişim başlaması için ilk olarak master cihazı slave cihaza start komutunu gönderir. Ardından adres bilgisini ve veri göndereciğini yada veri alacağını belirten bilgi datasını göndermesi gerekir. Master slave'e ait adresi göndermişse slave master'a ack bilgisini gönderir. Eğer veri gönderilecekse master ACK bilgisini aldıktan sonra 8 bitlik data gönderir ve slave cihazdan verinin alındığına dair bir ACK bilgisi bekler. Gönderilmesi gereken data bitene kadar data iletimi 8 bit data-ACK-8 bit data-ACK şeklinde gönderilir . En son alınan ACK mesajından sonra master stop komutunu gönderir ve haberleşmeyi bitirir. Veri alımı yapılacak ise master slave adresini gönderdikten sonra veri alacağını slave'e gönderir slave adresi doğrulamak için ACK mesajını yollar ve ardından 8 bit datayı master'a yollar bu kez master slave'a ACK masajını gönderir ve veri iletimi bu şekilde devam eder. Master veri alamazssa slave'e NACK biti gönderir. Veri iletimi tamamlandığında master stop komutu gönderir ve haberleşmeyi bitirir.
STM32F4 kartı ile MPU6050 İvme ve Gyro Sensörü I2C iletişiminde STM32F4 master MPU6050 ise slave cihaz olacak. MPU6050'nin adresi AD0 pinine göre 68 veya 69 olarak seçilebilir. AD0 Low olursa 0x68 Hıgh olursa 0x69 kullanılır. I2C konfigürasyon aşarları ayarlamaları şu şekildedir.
void init_I2C1(void){ GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; // enable APB1 clock bus for I2C1 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // enable AHB1 clock bus for SCL and SDA pins RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* SCL on PB6 and SDA on PB7 SCL on PB8 and SDA on PB9 */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PB6 and PB7 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // set to alternate function GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; //set to open drain GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // pull up resistors GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); // SCL GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA // I2C1 I2C_InitStruct.I2C_ClockSpeed = 100000; I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = 0x00; // own address I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; // enable acknowledge I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 bit address length I2C_Init(I2C1, &I2C_InitStruct); // enable I2C1 I2C_Cmd(I2C1, ENABLE); }
Veri gönderme ve alma fonksiyonları bu şekildedir.
void write_i2c(I2C_TypeDef* I2Cx,uint8_t address, uint8_t data){ // wait until I2C1 is not busy anymore while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // I2C1 enable I2C_GenerateSTART(I2Cx, ENABLE); // wait for I2C1 EV5 --> Slave has acknowledged start condition while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send slave Address for write I2C_Send7bitAddress(I2Cx, address, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2Cx, data); // wait for I2C1 EV8_2 --> byte has been transmitted while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2Cx, ENABLE); } int read_i2c(I2C_TypeDef* I2Cx,uint8_t address) { // wait until I2C1 is not busy anymore while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // I2C1 enable I2C_GenerateSTART(I2Cx, ENABLE); // wait for I2C1 EV5 --> Slave has acknowledged start condition while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send slave Address for read I2C_Send7bitAddress(I2Cx, address, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); I2C_AcknowledgeConfig(I2Cx, DISABLE); I2C_GenerateSTOP(I2Cx, ENABLE); // wait until one byte has been received while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // read data from I2C data register uint8_t data = I2C_ReceiveData(I2Cx); return data; }
main fonksiyonu
int main(void){ init_I2C1(); // initialize I2C peripheral GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12 |GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ; GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; GPIO_Init(GPIOD,&GPIO_InitStructure); while(1){ write_i2c(I2C1,ADDRESS<<1,0X6B); // PWR_MGMT_1 register write_i2c(I2C1,ADDRESS<<1,0X00); // wakes up the MPU-6050 write_i2c(I2C1,ADDRESS<<1,0X3B);//ACCEL_XOUT_H xh=read_i2c(I2C1,ADDRESS<<1); write_i2c(I2C1,ADDRESS<<1,0x3C);//ACCEL_XOUT_L xl=read_i2c(I2C1,ADDRESS<<1); write_i2c(I2C1,ADDRESS<<1,0x3D);//ACCEL_YOUT_H yh=read_i2c(I2C1,ADDRESS<<1); write_i2c(I2C1,ADDRESS<<1,0x3E);//ACCEL_YOUT_L yl=read_i2c(I2C1,ADDRESS<<1); x =((xh<<8 | xl)); y =((yh<<8)| yl); xm=map(x,-17000,17000,0,100); ym=map(y,-17000,17000,0,100); delay(10000); if(0<xm & xm<50) { GPIO_SetBits(GPIOD,GPIO_Pin_14); GPIO_ResetBits(GPIOD,GPIO_Pin_12); } if(50<=xm & xm<=100) { GPIO_SetBits(GPIOD, GPIO_Pin_12); GPIO_ResetBits(GPIOD, GPIO_Pin_14); } if(0<ym & ym<50) { GPIO_SetBits(GPIOD, GPIO_Pin_13); GPIO_ResetBits(GPIOD,GPIO_Pin_15); } if(50<=ym & ym<100) { GPIO_SetBits(GPIOD, GPIO_Pin_15); GPIO_ResetBits(GPIOD,GPIO_Pin_13); } } }
Proje dosyasına buradan ulaşabilirsiniz. bu uygulamada MPU6050'ın konumuna göre STM32F4 üzerindeki ledler yanmaktadır.
Dostum bende adxl345 sensörü ile verileri basmaya çalışıyorum fakat register adres değerini gönderiyorum yanıt vermiyor
YanıtlaSilbi yardım et gözünü seveyim
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
#define Max 50
#define adxl_address 0x53<<1 //0xA6
GPIO_InitTypeDef GPIOStructure;
I2C_InitTypeDef I2CStructure;
char str[Max];
uint8_t cip=0;
void Config(void){
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIOStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PB6 and PB7
GPIOStructure.GPIO_Mode = GPIO_Mode_AF; // set to alternate function
GPIOStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOStructure.GPIO_OType = GPIO_OType_OD; //set to open drain
GPIOStructure.GPIO_PuPd = GPIO_PuPd_UP; // pull up resistors
GPIO_Init(GPIOB, &GPIOStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
I2CStructure.I2C_ClockSpeed = 100000;
I2CStructure.I2C_Mode = I2C_Mode_I2C;
I2CStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2CStructure.I2C_OwnAddress1 = 0x00;
I2CStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2CStructure.I2C_Ack = I2C_Ack_Enable;
I2C_Init(I2C1, &I2CStructure);
I2C_Cmd(I2C1, ENABLE);
}
void write_i2c(I2C_TypeDef* I2Cx,uint8_t address, uint8_t data){
// wait until I2C1 is not busy anymore
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// I2C1 enable
I2C_GenerateSTART(I2Cx, ENABLE);
// wait for I2C1 EV5 --> Slave has acknowledged start condition
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Send slave Address for write
I2C_Send7bitAddress(I2Cx, address, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2Cx, data);
// wait for I2C1 EV8_2 --> byte has been transmitted
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2Cx, ENABLE);
}
int read_i2c(I2C_TypeDef* I2Cx,uint8_t address)
{
// wait until I2C1 is not busy anymore
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// I2C1 enable
I2C_GenerateSTART(I2Cx, ENABLE);
// wait for I2C1 EV5 --> Slave has acknowledged start condition
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Send slave Address for read
I2C_Send7bitAddress(I2Cx, address, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);
// wait until one byte has been received
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
// read data from I2C data register
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
uint16_t x0,x1,Y0,Y1,z0,z1;
int main(void)
{
Config();
cip=read_i2c(I2C1,adxl_address);
write_i2c(I2C1,0x2d, 0x00);
write_i2c(I2C1,0x2d, 0x08);
write_i2c(I2C1,0x31, 0x01);
while (1)
{
write_i2c(I2C1,adxl_address,0x32);
x0 = read_i2c(I2C1,adxl_address);
write_i2c(I2C1,adxl_address,0x33);
x1 = read_i2c(I2C1,adxl_address);
write_i2c(I2C1,adxl_address,0x34);
Y0 = read_i2c(I2C1,adxl_address);
write_i2c(I2C1,adxl_address,0x35);
Y1 = read_i2c(I2C1,adxl_address);
write_i2c(I2C1,adxl_address,0x36);
z0 = read_i2c(I2C1,adxl_address);
write_i2c(I2C1,adxl_address,0x37);
z1 = read_i2c(I2C1,adxl_address);
}
}
merhaba. size bu proje hakkında küçük bir soru sormak istiyorum. mpu6050 sensörürünüm hassasiyetini nasıl değiştirebilirim. yardımcı olursanız sevinirim
YanıtlaSil