Hi, Ich benutze den I2C2 des STM32L mit dem SMBus bzw PMBus Protokoll. Um die Adressen am Bus herauszufinden Frage ich jede Adresse ab und warte auf einen Timeout. Wenn dieser nicht stattfindet ist die Address gültig und wird gespeichert. In meinem Code hab ich das ganze mit einer for-Schleife über alle Adressen von 0x01 - 0x7F gelöst. Da die I2C Routine Event Abhängig ist musste ich aber ein paar warte schleifen Einbauen. Als erstes Warte ich bis meine Bytes versendet werden, dann warte ich bis das I2C Busy Flag gelöscht ist und als letztes warte ich bis die hardware das Stopbit Flag gelöscht hat. Sollte von der Theorie her funktionieren. Jedoch springt der controller seit dem ich die Schleifen implementiert habe nicht mehr in die Interrupt Routine sonder pollt nur noch die Bytes die noch versendet werden sollen (erste Schleife), die jedoch nie versendet werden können, da die Interrupt Routine nicht startet. Für Infos und Tips würde ich mich sehr freuen und bedanke mich bereits dafür. Gruß R. Griesser Code: for - Schleife: extern "C" void EXTI1_IRQHandler(void) { int i; GPIO_SetBits(GPIOA,GPIO_Pin_12); for (i=0;i<100000;i++); // wait a bit GPIO_ResetBits(GPIOA,GPIO_Pin_12); for (i=0;i<100000;i++); // wait a bit int bufferPointer = 0; data[0] = 0x01; data[1] = 0x80; for (i=0x01;i<0x7F;i++) { address = i; success = 0; bytes = 2; transmitted = 0; //enable I2C2 interrupts I2C_ITConfig(I2C2, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE); //transfer data I2C_GenerateSTART(I2C2,ENABLE); //wait until all bytes are transmitted while (bytes > 0); //wait until I2C Busy flag is cleared while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); //Wait until Stop bit is cleared by hardware while ((I2C2->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP); if (success == 0) { addressBuffer[bufferPointer] = address; bufferPointer++; } } EXTI_ClearITPendingBit(EXTI_Line1); } I2C Interrupt Routine: extern "C" void I2C2_EV_IRQHandler(void) //I2C2 event interrupt { Event = I2C_GetLastEvent(I2C2); switch (Event) { case I2C_EVENT_MASTER_MODE_SELECT: I2C_Send7bitAddress(I2C2,address,I2C_Direction_Transmitter); break; case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: I2C_SendData(I2C2,data[transmitted]); transmitted++; bytes--; if(bytes == 0) { I2C_ITConfig(I2C2, I2C_IT_BUF, DISABLE); } break; case I2C_EVENT_MASTER_BYTE_TRANSMITTING: I2C_SendData(I2C2,data[transmitted]); transmitted++; bytes--; if(bytes == 0) { I2C_ITConfig(I2C2, I2C_IT_BUF, DISABLE); } break; case I2C_EVENT_MASTER_BYTE_TRANSMITTED: I2C_GenerateSTOP(I2C2, ENABLE); transmitted = 0; I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE); break; default: break; } I2C_ClearFlag(I2C2,I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF); I2C_ClearITPendingBit(I2C2,I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF); }
1. dir ist bewusst das du da in einem Interrupt Warteschleifen einbaust? Und das nedmal wenige? 2. Wie hast du deine Variablen definiert? Insbesondere "byte" 3. Du schickst im falschen "Event" das nächste Byte raus.. Erst schicken wenn "BYTE_TRANSMITTED" auftritt, checken ob noch mehr Daten notwendig sind, wenn ja schicken, wenn nein Stop. Überdenke nochmal deine Idee...
Problem gelöst. Habe den Code aus der IR exportiert und nun funktioneirt es!
Danke dir ich werd das nochmal überarbeiten... PS: Die Variable ist global
Hab eher an volatile gedacht ;) Aber zumindest gehts jetzt mal :) optimieren kannst ja dann noch
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.