Hi,
ich möchte mit einem STM32F103RB Derivat ein I2C Device ansprechen. Der
Mikrocontroller soll dabei als Master und das anzusprechende Device als
Slave fungieren. Mein Code sieht folgendermaßen aus:
Initialisierung:
GPIOB->CRL=(GPIOB->CRL&~0xFF000000)|0xFF000000;//PB6 und PB7 als Alternate Function Output Open Drain
20
21
}
Sende-Routine:
1
voidsend(){
2
I2C1->CR1|=I2C_CR1_START;//sende Start-bit
3
while(!(I2C1->CR1&I2C_SR1_SB));//warte bis SB Flag gesetzt wurde
4
I2C1->DR=0x20;//schreibe Slave Adresse ins data register (Adresse fuers Schreiben = 32dez)
5
while(!(I2C1->SR1&I2C_SR1_ADDR));//warte bis ADDR gesetzt wurde <- hier bleibt das Programm haengen
6
}
Und das Hauptprogramm:
1
intmain(void){
2
init_i2c();
3
send();
4
5
for(;;){
6
}
7
}
Mir ist bewusst, dass die Sende-Routine nicht vollständig ist, doch um
das Problem einzukreisen hab ich das Programm auf das notwendigste
reduziert. Und zwar bleibt das Programm in dieser Zeile:
"while(!(I2C1->SR1 & I2C_SR1_ADDR));" hängen. Ich hab mir dann mit dem
Debugger die entsprechenden I2C1-Register angesehen und festgestellt,
dass das BUSY Flag dauerhaft gesetzt ist. Wenn ich mit dem Oszi die
Taktleitung ansehe, dann ist diese dauerhaft auf High. Da sollte ja
eigentlich ein schöner Clock zu messen sein, oder?!
Hat jemand einen Tipp was das Problem sein könnte?
Bevor ichs vergesse: Sowohl SDA als auch SCL besitzen einen Pullup gegen
VCC (also eigentlich sinds auf jeder Leitung zwei Pullups, masterseitig
10k Ohm und slaveseitig 4k7 Ohm - ergibt also 3,19k Ohm)
Gerade ist mir aufgefallen, dass in der Initialisierungsroutine ein paar
'~' gefehlt haben. Das hatte aber keine Auswirkungen, weil die
entsprechenden Register zu Beginn sowieso mit 0 initialisiert waren.
Dennoch hier der korrigierte Sourcecode:
GPIOB->CRL=(GPIOB->CRL&~0xFF000000)|0xFF000000;//PB6 und PB7 als Alternate Function Output Open Drain
20
21
}
Sollte der I2C Master (also in meinem Fall der uC) nicht den Takt
generieren? Also wenn, aus welchen Gründen auch immer, der Slave nicht
auf die gesendete Adresse reagiert, dann müsste doch zumindest ein
Taktsignal auf der SCL Leitung zu messen sein. Oder irre ich da?
Matthias K. schrieb:> AFIO braucht Du nicht freigeben. Nur wenn Du die alternativen Pins> benutzt. Dann müsste aber noch eine Zuweisung erfolgen.
Alles klar - war mir da nicht 100% sicher. Die FW-Library mag ich
irgendwie nicht - ich würds viel lieber selbst ausprogrammieren.
Bernhard schrieb:> Die FW-Library mag ich> irgendwie nicht - ich würds viel lieber selbst ausprogrammieren.
Kannst ja trotzdem mal die FW-Lib verwenden und wenn's geht mit dem
Debugger die Registerwerte anschauen.
Grüße
Sven
Zuerst solltest du mal alles überflüssige rausschmeißen. I2C_CR1 und 2
haben als Resetwert 0. Wenn du vorher evtl. im Programm schon etwas
verändert haben solltest, setz die Register einfach mit I2C->CR1 = 0;
auf 0 und mach nicht x Löschbefehle für einzelne Bits. Dann wird es
zumindest übersichtlicher.
Hallo,
hab es jetzt, wie vorgeschlagen, mit der Standard Library versucht. Ein
bisschen weiter bin ich damit gekommen. Ich bekomme jetzt einen AF
(acknowledge failure) nachdem ich die Slave Adresse an den Bus anlege.
Mein Programm sieht so aus:
Da ich keinerlei Erfahrung mit der Library hab, hab ich mich fast 1:1 an
das Demoprogramm gehalten. Was ich jedoch am Sourcecode nicht ganz
verstehe: Warum muss ich im Master Mode die eigene Slave Adresse
(I2C1_SLAVE_ADDRESS7) festlegen? Ich dachte, das muss man nur im Slave
Mode machen?
Mein Problem deckt sich mit dem was ich hier[1] gefunden habe, bis auf
die Tatsache, dass ich ein anderes STM32 Derivat einsetze.
[1]
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=17515&Source=/public/STe2ecommunities/mcu/Tags.aspx?tags=C
Ich hoffe, jemand hat Erfahrung mit der Lib und kann mir einen Tipp
geben.
Bernhard schrieb:> /* I2C configuration */> I2C_Configuration();>> /* GPIO configuration */> GPIO_Configuration();
Sollte die Reihenfolge nicht andersrum sein?
Bernhard schrieb:> /* I2C Peripheral Enable */> I2C_Cmd(I2C1, ENABLE);> /* Apply I2C configuration after enabling it */> I2C_Init(I2C1, &I2C_InitStructure);
Die Reihenfolge muß auch gedreht werden, sonst läuft der I2C ja mit den
Resetwerten los.
Hallo Bernhard,
hast du inzwischen das Problem gelöst? Bei mir ist es nämlich ganz genau
das gleiche:
Ich schicke die 7-bit-Adresse, und als Antowrt kommt anstatt EV6 immer
nur ein AF.
Komischerweise hatte das gleiche Programm ein paar Stunden vorher ohne
Probleme funktioniert, aber auf einmal baff, ohne das irgendetwas
geändert wurde ........
nur noch AF und das nun seit 2 Tagen.
Irgendeine Lösung?
Gruß
Sylvia
Hallo,
ich hab genau das selbe Problem mit meinem I2C Port am STM32VL
Discovery, wie es hier beschrieben ist mit der Firmware-Lib. Die
Pull-Ups sind gesetzt, Master-Seite 10k und Slave-Seite 4,7k.
Gibt es schon eine Lösung zu diesem Problem? Wäre cool wenn es einer von
euch posten könnte.
mfg
Paul