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.