Jump to content
ELFORUM - Forumul electronistilor

Problema de comunicare pe i2c


moro
 Share

Recommended Posts

Va salut, de 2 zile ma chinui sa fac un stm32f4 sa "vorbeasca" cu un senzor bmp085 pe i2c, dupa ce am incercat de la propriile initializari ale registrilor , precum si diferite exemple de pe net, la care ma voi opri cu urmatorul cod postat jos ( sursa )

 

Ideea e ca luand la puricat cu analizorul logic, nu se intampla nimic pe SDA si SCL, pentru moment am incercat doar sa trimit date catre senzor cu el/fara scos din montaj

 

In schimb daca pastrez aceiasi parametrii de initializare a gpio`ului si i2c si fac o bucla doar cu start si stop, pe sda si scl vad intradevar semnalele de start si stop, precum si clock-ul ok.

 

while(1) {

I2C_GenerateSTART(I2C1, ENABLE);

I2C_GenerateSTOP(I2C1, ENABLE);

 

}

 

 

Din ce am citit pe net, initializarea i2c-ului la arm... e mai buclucasa...

Codul il scriu in IAR 6.30, n-am nici o eroare la compilare, debuggerul merge... totul e atza.... Imi scapa ceva?

#include <stm32f4xx.h>#include <stm32f4xx_i2c.h>#define SLAVE_ADDRESS 0x3D // the slave address (example)void init_I2C1(void){GPIO_InitTypeDef GPIO_InitStruct;I2C_InitTypeDef I2C_InitStruct;// enable APB1 peripheral clock for I2C1RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);// enable clock for SCL and SDA pinsRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);/* setup SCL and SDA pins* You can connect I2C1 to two different* pairs of pins:* 1. SCL on PB6 and SDA on PB7* 2. SCL on PB8 and SDA on PB9*/GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // we are going to use PB6 and PB7GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;	// set pins to alternate functionGPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	// set GPIO speedGPIO_InitStruct.GPIO_OType = GPIO_OType_OD;	// set output to open drain --> the line has to be only pulled low, not driven highGPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;	// enable pull up resistorsGPIO_Init(GPIOB, &GPIO_InitStruct);	// init GPIOB// Connect I2C1 pins to AFGPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);	// SCLGPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA// configure I2C1I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHzI2C_InitStruct.I2C_Mode = I2C_Mode_I2C;	// I2C modeI2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;	// 50% duty cycle --> standardI2C_InitStruct.I2C_OwnAddress1 = 0x00;	// own address, not relevant in master modeI2C_InitStruct.I2C_Ack = I2C_Ack_Disable;	// disable acknowledge when reading (can be changed later on)I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addressesI2C_Init(I2C1, &I2C_InitStruct);	// init I2C1// enable I2C1I2C_Cmd(I2C1, ENABLE);}/* This function issues a start condition and* transmits the slave address + R/W bit** Parameters:* I2Cx --> the I2C peripheral e.g. I2C1* address --> the 7 bit slave address* direction --> the tranmission direction can be:* I2C_Direction_Tranmitter for Master transmitter mode* I2C_Direction_Receiver for Master receiver*/void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction){// wait until I2C1 is not busy anymorewhile(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));  // Send I2C1 START conditionI2C_GenerateSTART(I2Cx, ENABLE);// wait for I2C1 EV5 --> Slave has acknowledged start conditionwhile(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));// Send slave Address for writeI2C_Send7bitAddress(I2Cx, address, direction);/* wait for I2C1 EV6, check if* either Slave has acknowledged Master transmitter or* Master receiver mode, depending on the transmission* direction*/if(direction == I2C_Direction_Transmitter){while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));}else if(direction == I2C_Direction_Receiver){while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));}}/* This function transmits one byte to the slave device* Parameters:* I2Cx --> the I2C peripheral e.g. I2C1* data --> the data byte to be transmitted*/void I2C_write(I2C_TypeDef* I2Cx, uint8_t data){I2C_SendData(I2Cx, data);// wait for I2C1 EV8_2 --> byte has been transmittedwhile(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));}/* This function reads one byte from the slave device* and acknowledges the byte (requests another byte)*/uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){// enable acknowledge of recieved dataI2C_AcknowledgeConfig(I2Cx, ENABLE);// wait until one byte has been receivedwhile( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );// read data from I2C data register and return data byteuint8_t data = I2C_ReceiveData(I2Cx);return data;}/* This function reads one byte from the slave device* and doesn't acknowledge the recieved data*/uint8_t I2C_read_nack(I2C_TypeDef* I2Cx){// disabe acknowledge of received data// nack also generates stop condition after last byte received// see reference manual for more infoI2C_AcknowledgeConfig(I2Cx, DISABLE);I2C_GenerateSTOP(I2Cx, ENABLE);// wait until one byte has been receivedwhile( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );// read data from I2C data register and return data byteuint8_t data = I2C_ReceiveData(I2Cx);return data;}/* This funtion issues a stop condition and therefore* releases the bus*/void I2C_stop(I2C_TypeDef* I2Cx){// Send I2C1 STOP ConditionI2C_GenerateSTOP(I2Cx, ENABLE);}int main(void){init_I2C1(); // initialize I2C peripheraluint8_t received_data[2];while(1){I2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Transmitter); // start a transmission in Master transmitter modeI2C_write(I2C1, 0x20); // write one byte to the slaveI2C_write(I2C1, 0x03); // write another byte to the slaveI2C_stop(I2C1); // stop the transmissionI2C_start(I2C1, SLAVE_ADDRESS<<1, I2C_Direction_Receiver); // start a transmission in Master receiver modereceived_data[0] = I2C_read_ack(I2C1); // read one byte and request another bytereceived_data[1] = I2C_read_nack(I2C1); // read one byte and don't request another byte, stop transmission}}
Link to comment
Share on other sites

  • Replies 3
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Cel putin la M0 (cu care m-am jucat eu), I2C1 mai are nevoie de o setare pentru ceas. Rutina mea (pentru stm32f0 si testata cu I2C2) arata ca mai jos. Codul e scris in arm-gcc... (compilatorul oficial arm). Poti incerca sa folosesti rezistente pull-up externe, la mine parca n-a mers fara (desi nu mai sunt sigur).

void vInitI2C(I2C_TypeDef* I2Cx) {GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;I2C_DeInit(I2Cx);  //clear any previous settings//I2C1 & I2C2 have different configurationsif (I2Cx == I2C1) {// Set I2C1 clock to SYSCLK (see system_stm32f0.c)RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);//(#) Enable peripheral clock using// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2Cx, ENABLE)//    function for I2C1 or I2C2.RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);//(#) Enable SDA, SCL  and SMBA (when used) GPIO clocks usingRCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);//(#) Peripherals alternate function://    (++) Connect the pin to the desired peripherals' AlternateGPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1); //If I2C1, then PB8 && PB9GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);// i2c pins open collector & PullUp enabledGPIO_StructInit(&GPIO_InitStructure); //reset the GPIO_InitStructure to the default valuesGPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //If I2C1, then PB8 && PB9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //activate the internal pullup. For i2c communication should be enoughGPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //for i2c should use the open drain outputsGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);} else if (I2Cx == I2C2) {//(#) Enable peripheral clock usingRCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);//(#) Enable SDA, SCL  and SMBA (when used) GPIO clocks usingRCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);//(#) Peripherals alternate function://    (++) Connect the pin to the desired peripherals' AlternateGPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1); //If I2C1, then PB8 && PB9GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);// i2c pins open collector & PullUp enabledGPIO_StructInit(&GPIO_InitStructure); //reset the GPIO_InitStructure to the default valuesGPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //If I2C1, then PB8 && PB9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //activate the internal pullup. For i2c communication should be enoughGPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //for i2c should use the open drain outputsGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);} // else if (I2Cx == I2C2)// Settings common for both port types//(#) Program the Mode, Timing , Own address, Ack and Acknowledged//    Address using the I2C_Init() function.I2C_StructInit(&I2C_InitStructure); //reset the I2C_InitStructre to the default valuesI2C_InitStructure.I2C_Ack = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;I2C_InitStructure.I2C_DigitalFilter = 0;I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_OwnAddress1 = 0;I2C_InitStructure.I2C_Timing = 0x10805E89; // ~100 kHz. @ 48 MHz (HSI) see the script to calculate itI2C_Init(I2Cx, &I2C_InitStructure);//(#) Enable the I2C using the I2C_Cmd() function.I2C_Cmd(I2Cx, ENABLE);}

 

Edited by Liviu M
Link to comment
Share on other sites

Salut, m-am uitat si n-am gasit registrul ala. Oricum sunt ceva mai optimist astazi, am observat ca daca nu apelez rutina pentru stop, am comunicare normala pe i2c. M-am jucat toata noaptea cu registrii direct cum is definiti in stm34f4xxx.h fara sa apelez la libraria i2c

 

I2C1->CR1 |=I2C_CR1_START;  /* Generate a START condition */  I2C1->DR =0x33; // writes adress value to registerI2C1->CR1 |=I2C_CR1_STOP;  /* Generate a STOP condition */

 

Daca nu apelez CR1_Stop ala, pe SDA imi trimite 0x33 si clock-ul este ok.

M-am uitat sa vad daca nu`s ceva intreruperi pornite, dar sunt doate pe default reset 0. Ideea e ca imi termina comunicarea, apuca sa de-ie start si apoi stop, intr-o bucla infinita....

Link to comment
Share on other sites

Pana la urma am reusit sa-i dau de cap oarecum,  in cazul de fata lucrez cu un senzor de presiune/temperatura de la bosch, pe care acum o luna, doua l-am folosit cu succes pe un PIC18F si stiam ca este functional. Dupa ce am stat vreo 4 zile cu nasu` prin headere si librariile de la ST, m-am enervat si am luat "tzaraneste" fiecare bit cu bit si registru si n-am mai folosit nici o librarie. In datasheet  RM0090 la pagina 829 prezinta o diagrama cu time event-ul transmisiei pe i2c, dupa ce am citit putin mai atent eventurile alea , am vazut ca in st32f4xx.h is definite niste flag-uri care desciu exact acele eventuri. Asa ca m-am pus sa verific fiecare event din i2c, acum vad ca functioneaza

#define Addr 0xEE#define Regg 0xF6#define Data 0x2Ewhile(1){I2C_GenerateSTART(I2C1, ENABLE); // generate start conditionwhile( !(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) );  I2C_Send7bitAddress(I2C1,Addr , I2C_Direction_Transmitter);  while( !(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) );    I2C1->DR = Regg;   /* Send the  Register address */while( !(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)));I2C1->DR = Data;   /* Send the Data to Register */while( !(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)));I2C1->CR1 |= I2C_CR1_STOP; /* Generate a STOP condition */while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); // stop bit flag}

post-174735-0-26458000-1400065341_thumb.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share




×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines