Mikrocontroller und Digitale Elektronik
›
Thread
STM32F4 I2C immer busy
PB
Patrick B.
(p51d)
OP
28.12.2012 13:29
#2973178
Hallo miteinander
Ich möchte ein wenig mit dem I2C der STM-Familie herumspielen, aber
bisher leider ohne Erfolg. Beim Versuch etwas zu senden oder Empfangen
ist das Modul immer busy, ohne das etwas gemacht wird.
Ich habe mich nun schon seit 3 Tagen an diesem ding generft. Vieleicht
fällt einem ja auf, was falsch ist:
1 void HMC5883L_init ( void )
2 {
3 GPIO_InitTypeDef GPIO_InitStructure ;
4 I2C_InitTypeDef I2C_InitStructure ;
5
6 // write CONFIG_A register
7 uint8_t tmp = ( HMC5883L_AVERAGING_8 << ( HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1 )) |
8 ( HMC5883L_RATE_15 << ( HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1 )) |
9 ( HMC5883L_BIAS_NORMAL << ( HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1 )) ;
10
11 // Enable clock
12 RCC_APB1PeriphClockCmd ( HMC5883L_I2C_RCC_Periph , ENABLE );
13 RCC_AHB1PeriphClockCmd ( HMC5883L_I2C_RCC_Port , ENABLE );
14
15 // Performing a Reset
16 RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SYSCFG , ENABLE );
17 RCC_APB1PeriphResetCmd ( HMC5883L_I2C_RCC_Periph , ENABLE );
18 RCC_APB1PeriphResetCmd ( HMC5883L_I2C_RCC_Periph , DISABLE );
19
20 // Connect Pins to AF function
21 GPIO_PinAFConfig ( HMC5883L_I2C_Port , HMC5883L_I2C_SCL_Pin , HMC5883L_I2C_SCL_AF );
22 GPIO_PinAFConfig ( HMC5883L_I2C_Port , HMC5883L_I2C_SDA_Pin , HMC5883L_I2C_SDA_AF );
23
24 // Configure I2C SCL Pin(Pin10), SDA Pin (pin11)
25 GPIO_InitStructure . GPIO_Pin = HMC5883L_I2C_SCL_Pin | HMC5883L_I2C_SDA_Pin ;
26 GPIO_InitStructure . GPIO_Mode = GPIO_Mode_AF ;
27 GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ;
28 GPIO_InitStructure . GPIO_OType = GPIO_OType_OD ;
29 GPIO_InitStructure . GPIO_PuPd = GPIO_PuPd_NOPULL ;
30 GPIO_Init ( HMC5883L_I2C_Port , & GPIO_InitStructure );
31
32 // Configure I2C
33 I2C_DeInit ( HMC5883L_I2C );
34 I2C_InitStructure . I2C_Mode = I2C_Mode_I2C ; // I2C mode
35 I2C_InitStructure . I2C_DutyCycle = I2C_DutyCycle_2 ; // 50% duty cycle -> standard
36 I2C_InitStructure . I2C_OwnAddress1 = 0 ; // not relevant in master mode
37 I2C_InitStructure . I2C_Ack = I2C_Ack_Enable ;
38 I2C_InitStructure . I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ; // Set address length to 7 bit addresses
39 I2C_InitStructure . I2C_ClockSpeed = I2C_SPEED ;
40 I2C_Init ( HMC5883L_I2C , & I2C_InitStructure );
41
42 /*ENABLE*/
43 I2C_Cmd ( HMC5883L_I2C , ENABLE );
44
45 HMC5883L_I2C_ByteWrite ( HMC5883L_DEFAULT_ADDRESS , & tmp , HMC5883L_RA_CONFIG_A ); // <== Hier hängt er sich auf
46 }
1 void HMC5883L_I2C_ByteWrite ( uint8_t slaveAddr , uint8_t * pBuffer , uint8_t WriteAddr )
2 {
3 // Diese Schlaufe wird nie verlassen
4 while ( I2C_GetFlagStatus ( HMC5883L_I2C , I2C_FLAG_BUSY )); // wait until I2C is not busy anymore
5
6 /* Send START condition */
7 I2C_GenerateSTART ( HMC5883L_I2C , ENABLE );
8
9 /* Test on EV5 and clear it */
10 while ( ! I2C_CheckEvent ( HMC5883L_I2C , I2C_EVENT_MASTER_MODE_SELECT ));
11
12 /* Send HMC5883 address for write */
13 I2C_Send7bitAddress ( HMC5883L_I2C , slaveAddr , I2C_Direction_Transmitter );
14
15 /* Test on EV6 and clear it */
16 while ( ! I2C_CheckEvent ( HMC5883L_I2C , I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ));
17
18 /* Send the HMC5883L internal address to write to */
19 I2C_SendData ( HMC5883L_I2C , WriteAddr );
20
21 /* Test on EV8 and clear it */
22 while ( ! I2C_CheckEvent ( HMC5883L_I2C , I2C_EVENT_MASTER_BYTE_TRANSMITTED ));
23
24 /* Send the byte to be written */
25 I2C_SendData ( HMC5883L_I2C , * pBuffer );
26
27 /* Test on EV8 and clear it */
28 while ( ! I2C_CheckEvent ( HMC5883L_I2C , I2C_EVENT_MASTER_BYTE_TRANSMITTED ));
29
30 /* Send STOP condition */
31 I2C_GenerateSTOP ( HMC5883L_I2C , ENABLE );
32 }
Testweise habe ich die I2C-Lib etwas angepasst: 1 FlagStatus I2C_GetFlagStatus ( I2C_TypeDef * I2Cx , uint32_t I2C_FLAG )
2 {
3 FlagStatus bitstatus = RESET ;
4 __IO uint32_t i2creg = 0 , i2cxbase = 0 ;
5 uint32_t SR1 = 0 , SR2 = 0 ;
6 /* Check the parameters */
7 assert_param ( IS_I2C_ALL_PERIPH ( I2Cx ));
8 assert_param ( IS_I2C_GET_FLAG ( I2C_FLAG ));
9
10 /* Get the I2Cx peripheral base address */
11 i2cxbase = ( uint32_t ) I2Cx ;
12
13 /* Read flag register index */
14 i2creg = I2C_FLAG >> 28 ;
15
16 /* Get bit[23:0] of the flag */
17 I2C_FLAG &= FLAG_MASK ;
18
19 if ( i2creg != 0 )
20 {
21 /* Get the I2Cx SR1 register address */
22 i2cxbase += 0x14 ;
23 }
24 else
25 {
26 /* Flag in I2Cx SR2 Register */
27 I2C_FLAG = ( uint32_t )( I2C_FLAG >> 16 );
28 /* Get the I2Cx SR2 register address */
29 i2cxbase += 0x18 ;
30 }
31 SR1 = ( * ( __IO uint32_t * ) ( i2cxbase - 0x18 + 0x14 ));
32 SR2 = ( * ( __IO uint32_t * ) i2cxbase );
33 if ((( * ( __IO uint32_t * ) i2cxbase ) & I2C_FLAG ) != ( uint32_t ) RESET )
34 {
35 /* I2C_FLAG is set */
36 bitstatus = SET ;
37 }
38 else
39 {
40 /* I2C_FLAG is reset */
41 bitstatus = RESET ;
42 }
43
44 /* Return the I2C_FLAG status */
45 return bitstatus ;
46 }
SR1 = 0;
SR2 = 2; -> Busy Flag ist gesetzt
Was habe ich falsch gemacht?
Besten Dank für die Hilfe
MFG
Patrick
DL
dein Lehrer
Gast
28.12.2012 13:58
#2973235
Patrick B. schrieb:
> ding generft. Vieleicht
> fällt einem ja auf, was falsch ist:
richtig wäre
Ding genervt. Vielleicht
F
frame
Gast
29.12.2012 18:02
#2974806
Hast du schon einmal nachgemessen, was auf dem Bus passiert ?
Ein Oszilloskop ist hier sehr hilfreich.
Zumindest statisch sollten die Pegel stimmen. I2C ist ein Open-Drain
Bus, das ist dir schon bewußt. Sprich, du brauchst einen
Pullup-Widerstand. Fehlt der, ist der Bus auch immer "busy".
Und wenn das alles in Ordnung ist: manchmal starten diverse I2C-Slaves
nicht korrekt, weil sie irgendeine Störung als Bussignal bewerten. Dann
kann es helfen, auf SCL 9 Taktimpulse auszugeben, damit der Slave SDA
wieder freigibt. Dazu müßtest du die I2C-Pins als GPIO betreiben.
↑ Nach oben
← Zurück zu Mikrocontroller und Digitale Elektronik
Antwort schreiben