Wie Sie initialisiert die I2C-Schnittstelle auf STM32F0?
Vor kurzem ich habe versucht, den I2C-bus arbeiten auf der STM32F030F4P6 MCU, aber mit wenig Glück.
Ich bin mit einem STM32F0-Modul und gefunden haben, ausreichende Ressourcen für die STM32F1-Modul I2C Initialisierung, aber nichts spezifisches über die STM32F0-Initialisierung/transfer-Prozess.
Hier ist mein code für die Initialisierung:
void i2c_init(uint8_t ownAddress)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
//Enable GPIOA clocks
RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
//Configure I2C1 clock and GPIO
GPIO_StructInit(&GPIO_InitStructure);
/* I2C1 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* I2C1 SDA and SCL configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* I2C1 Reset */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
/* Configure I2C1 */
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
//I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
Um zu testen, um zu sehen, ob meine Einstellung richtig war, entwarf ich einige I2C-übertragung code, der die übertragung von Daten in einem nie endenden Schleife. Hier ist der code für:
while(1)
{
I2C_SlaveAddressConfig(I2C1, RegName);
I2C_GenerateSTART(I2C1, ENABLE);
I2C_NumberOfBytesConfig(I2C1, 8);
I2C_SendData(I2C1,0b00000000);
I2C_GenerateSTOP(I2C1, ENABLE);
}
Wo:
RegName = 0x75
SDA = GPIO_PIN_10 auf GPIOA
SCL = GPIO_PIN_9 auf GPIOA
I2C = I2C1
ownAdrress = 0x68
Wenn ich den Umfang der I2C-Leitungen nach beginne ich diesen code bekomme ich eine schwebende Spannung um 160mV. Wenn ich den code schrittweise Durchlaufen jedes der I2C-Funktionsaufrufe geschehen und abgeschlossen, so dass ist, warum ich dachte, es hatte etwas mehr damit zu tun, mit meiner Initialisierung des pins selbst.
Mein problem ist sehr ähnlich zu diesem thread, aber wurde nie beantwortet:
Edit 1: Hier ist meine aktuelle code, funktioniert immer noch nicht (Edit 2: Aktualisiert, was ich derzeit habe; bewegte Dinge mehr in die richtige Position):
void i2c_init(uint8_t ownAddress)
{
/* TypeDefs for GPIOA and I2C1 */
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* Enable GPIOA clocks and I2C1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Configure I2C1 clock and GPIO */
GPIO_StructInit(&GPIO_InitStructure);
/* I2C1 SDA and SCL configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //UP
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
/* GPIO AF Configuration -> GPIO_AF_1: USART2, CEC, Tim3, USART1, USART2,EVENTOUT, I2C1, I2C2, TIM15 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* I2C1 Reset */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
//I2C_DeInit(I2C1);
/* Configure I2C1 */
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
//I2C_AcknowledgeConfig(I2C1, ENABLE);
}
Wie Sie sehen können habe ich noch die zwei Zeilen GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
und GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
wo ich fand, dass GPIO_AF_1 hatte die Alternative Funktion der I2C1 von die STM32F0 Standard-Peripherie-bibliotheek.
Irgendwelche anderen Ideen? Ich habe das Spiel mit den Uhren zu sehen, ob das etwas geändert und wurden snippets hinzufügen, anderer Leute code, nur um zu sehen, ob das hat keine Auswirkungen auf die Ausgabe von meinem Gerät.
Edit 3: ich habe versucht, ziehen sowohl die SDA-und SCL-Linien bis VCC mit einem 1kohm-Widerstand entsprechend der Anweisungen dieser Anleitung: https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations
->(3.3 V-0,4)/3mA ~= 1kohm
Edit 4: Nachdem er durch meinen code-Zeilen habe ich versucht die Ausgabe der verschiedenen flag bit Register. Genau diese registriert: isr = I2C1->ISR;
, cr1 = I2C1->CR1;
, und cr2 = I2C1->CR2;
Die Flagge, ich bekomme nach der Einleitung der I2C übertragung Umgang mit I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
war 0x8001
die entziffert werden kann und die zwei Fehler:
#define I2C_ISR_BUSY ((uint32_t)0x00008000) /*!< Bus busy */
und
#define I2C_ISR_TXE ((uint32_t)0x00000001) /*!< Transmit data register empty */
Ich habe festgestellt, dass einige Problemumgehungen Arbeit unter diesem link hier (entfernen Sie die Leerzeichen nach https: gehen Sie zu dem link -> stack-überlauf wird nicht lassen Sie mich nach mehr als 1 link aus irgendeinem Grund): https: //my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32L151RB%20I2C%20Busy%20flag%20always%20set&FolderCTID=0x01200200770978C69A1141439FE559eb459d7580009c4e14902c3cde46a77f0ffd06506f5b¤tviews= 690, ich bin auf der Suche zu implementieren und werde berichten, sobald ich Sie ausprobieren.
Hey es DoxyLover, versucht und hat nicht funktioniert. Glaube nicht, dass Sie hoch angesetzt, bevor ich den code ausführt.
Was hast du genau angeschlossen, die I2C Leitungen? Was ist das slave-Gerät? Sind Sie sich bewusst, dass Sie, müssen pull-up-widerstände angeschlossen, die zwischen jeder I2C-Leitung und Vcc?
So jetzt habe ich nicht angeschlossen, alle anderen Geräte überhaupt; es ist einfach ein Meister mit einem separaten Zug für die jeweils von der SCL und SDA Leitung. Und ja, ich bin mir bewusst, dass ich irgendwann benötigen einen pullup für jedes Gerät habe ich es angeschlossen. Jetzt habe ich nicht einmal ein signal ausgehen (ich sollte in der Lage sein zu sehen, die raw-Daten ist mit meinem aktuellen code oder zumindest das start-signal).
Sie fehlt
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_Pin_9); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_Pin_10);
. Ich bin mir nicht sicher, ob es zählt, aber Sie müssen möglicherweise tun Sie es vor aufrufen GPIO_Init
.InformationsquelleAutor Stroodlemuffin | 2014-11-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Habe ich die I2C-Schnittstelle arbeitet als master und slave auf F0. Die wichtigste Frage, die ich sehen kann, bei deinem code ist, dass im master-Modus müssen Sie absolut gesetzt, die
I2C_Timing
Initialisierung Struktur-member. Sehen RM0091 für die sample-Werte entsprechen der Frequenz, die Sie erzeugen möchten auf SCL. Im slave-Modus die Uhr ist wieder von der master-also das timing-Mitglied scheint nicht verwendet zu werden.Wie die anderen schon sagten, externe pullups an Vcc auf SCL und SDA sind nicht optional und müssen vorhanden sein, einmal pro bus nicht pro peripheren als Sie fälschlicherweise angegeben, in einem Kommentar. Sie wurden Recht zur Nutzung der Rechner bei der Auswahl von geeigneten Werten, da die internen pullups der STM32 bei etwa 30-50K sind viel zu schwach für die Verwendung als I2C-pullups.
I2C_InitStructure.I2C_Timing = 0x50330309;//400kHz
Allerdings bin ich noch immer nichts auf die sowohl die SCL-und SDA-Leitungen. Ich habe nur ein master-Gerät jetzt mit den pullups drauf, aber ich werde im Hinterkopf behalten, dass ich nur benötigen einen pullup pro bus für zukünftige Referenz.Nun nehmen Sie einen Blick auf Ihre übertragung Logik, bezieht sich auf, wie ST es tun, in Ihrem Beispiel-code. Die basic-pseudocode-Sequenz zu übermitteln, die Adresse ist: I2C_TransferHandling() -> warten TXIS -> I2C_SendData(Adresse) -> warten TCR.
Theoretisch, wenn ich überspringen Sie die Wartezeit für TXIS und TCR-bits, würde mein bus nicht nur Daten übertragen, die unabhängig von jeder Art von Bestätigung vom slave? Wie jetzt, der Einfachheit halber, habe ich nur noch einen master auf den gesamten bus und bin einfach nur versuchen, um zu sehen, ob der bus auch Ausgang etwas. Würde den code habe ich oben in meiner main-Schleife nicht erheblich sein nur um etwas zu bekommen, dass ich Umfang?
InformationsquelleAutor Andy Brown
Das problem ist, dass Sie nicht konfigurieren, die richtigen AF (Alternative Funktion) Quelle für die I2C-pins. Nach reset Register konfigurieren AF sind alle 0, und I2C ist die Funktion 1 ist, also Ihre I2C-Peripherie ist in der Tat getrennt von den GPIOs.
Technisch macht es keinen Unterschied, wenn Sie konfigurieren, dass, aber es ist am besten zu tun, bevor GPIO-Konfiguration zu minimieren, unerwünschte übergänge auf die pins.
Bearbeiten: Sie MÜSSEN die pullups auf den I2C pins - ohne Sie haben Sie "low" - level gibt es, und I2C-Peripherie erkennt, dass Sie als bus-Fehler, was natürlich verhindert, dass es ordnungsgemäß funktioniert. Entweder schließen Sie die externen widerstände, oder zumindest aktivieren der internen pullups statt "keine pullups/keine pulldowns" - Konfiguration.
Außerdem - es ist einfach nicht möglich für ein "open drain" - pin, um richtig zu arbeiten, ohne pullup.
Ok, vielleicht habe ich falsch verstanden, "könnte" für "muss" - es ist früh... (; aber Trotzdem - dein Kommentar nicht erklären das Problem und die Lösung, und wahrscheinlich (ich weiß nicht verwenden, SPL, wie das ist Mist) der code ist falsch - Sie sollten die NF-Quelle statt des "GPIO_Pin_9" - es gibt einige Makros, wie AF_SOURCE_I2C oder sth like, die.
Hat diese code-Zeilen; siehe meine Antwort oben editiert für ein update auf die situation.
siehe Antwort bearbeitet.
Chopin versuchte ich, die erste Sache, wenn DoxyLover schlug es gestern; noch immer nichts an der Ausgabe.
InformationsquelleAutor Freddie Chopin
Den Kern der Cortex-M0 ist dann anders Kern Cortex M3, STM32f030f4 hat AHB und APB1 (gebrückt) nur. Der C-code des STM32f1xx nie unter STM32f0xx.
Verwenden STM32F0xx_Snippets_Package für die Lösung Ihrer wichtigsten Probleme.
InformationsquelleAutor Marcinlas102
Mir gerade aufgefallen ist, auch diese:
So dass Sie deaktiviert haben, die Uhr, nachdem Sie es aktiviert hat. Ich sehe nicht, wo Sie re-aktiviert es später.
InformationsquelleAutor Russ Troxel
Merke ich, dass Sie die Zuordnung der pins zu
AF_1
und das ist für denUART
Funktion.Müssen Sie ordnen Sie Sie
AF_4
zu verwenden, dieI2C
Funktion.InformationsquelleAutor Russ Troxel