von
Andre B.
(Firma: Insistro)
(qusoften )
27.09.2012 14:54
Hallo liebe Forum-Gemeinde,
ich hab mich nun nach langem Lesen dazu entschlossen, selbst Mitglied zu
werden=)
Und da starte ich mein Mikrocontroller.net-Leben gleich mit einer Bitte
zur Hilfestellung.
Folgendes Szenario:
Ich möchte den TPA81 (http://www.roboter-teile.de/datasheets/tpa81.pdf )
via I2C an mein STM32F103VE Board klemmen und auslesen.
Das klappt auch soweit ganz gut, zumindest 1 mal, danach zieht SDA auf
LOW und mein STM-Board interpretiert dies als BUSY.
I2C habe ich wie folg initialisiert:
1 GPIO_InitTypeDef GPIO_InitStructure ;
2 NVIC_InitTypeDef NVIC_InitStructure ;
3 I2C_InitTypeDef I2C_InitStructure ;
4
5 RCC_Configuration ();
6 GPIO_InitStructure . GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
7 GPIO_InitStructure . GPIO_Mode = GPIO_Mode_AF_OD ;
8 GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ;
9 GPIO_Init ( GPIOB , & GPIO_InitStructure );
10 GPIO_PinRemapConfig ( GPIO_Remap_I2C1 , ENABLE );
11
12 I2C_DeInit ( I2C1 );
13 I2C_InitStructure . I2C_Ack = I2C_Ack_Enable ;
14 I2C_InitStructure . I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;
15 I2C_InitStructure . I2C_ClockSpeed = 100000 ;
16 I2C_InitStructure . I2C_DutyCycle = I2C_DutyCycle_2 ;
17 I2C_InitStructure . I2C_Mode = I2C_Mode_I2C ;
18 I2C_InitStructure . I2C_OwnAddress1 = 0xD0 ;
19
20 I2C_Init ( I2C1 , & I2C_InitStructure );
21 I2C_Cmd ( I2C1 , ENABLE );
Um nun den TPA81 zu sagen was ich von ihm möchte nutze ich folgenden
Code:
Als Info: TFT_ShowString und TFT_ShowNum habe ich zum "debuggen"
eingesetzt damit ich seh wo er grad steht ;-)
1 while ( 1 )
2 {
3 TFT_CLEAR ( 0 , 0 , 240 , 320 );
4 while ( I2C_CheckEvent ( I2C1 , I2C_FLAG_BUSY ))
5 {
6 TFT_ShowString ( 10 , 10 , "I2C_Bus: FAIL" );
7 }
8 TFT_ShowString ( 10 , 10 , "I2C_Bus: OKAY" );
9 I2C_GenerateSTART ( I2C1 , ENABLE );
10 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_MODE_SELECT ))
11 {
12 TFT_ShowString ( 10 , 30 , "I2C_EventCheck: FAIL" );
13 }
14 TFT_ShowString ( 10 , 30 , "I2C_EventCheck: OKAY" );
15 I2C_Send7bitAddress ( I2C1 , 0xD0 , 0 );
16 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ))
17 {
18 TFT_ShowString ( 10 , 50 , "I2C_Master: FAIL" );
19 }
20 TFT_ShowString ( 10 , 50 , "I2C_Master: OKAY" );
21 I2C_Cmd ( I2C1 , ENABLE );
22 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_BYTE_TRANSMITTED ))
23 {
24 TFT_ShowString ( 10 , 70 , "I2C_M_Trans1: FAIL" );
25 }
26 TFT_ShowString ( 10 , 70 , "I2C_M_Trans1: OKAY" );
27 for ( j = 3 ; j < 10 ; j ++ )
28 {
29 I2C_Cmd ( I2C1 , ENABLE );
30 I2C_SendData ( I2C1 , j );
31 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_BYTE_TRANSMITTED ))
32 {
33 TFT_ShowString ( 10 , 90 , "I2C_M_Trans2: FAIL" );
34 }
35 TFT_ShowString ( 10 , 90 , "I2C_M_Trans2: OKAY" );
36 while ( I2C_CheckEvent ( I2C1 , I2C_FLAG_BUSY ))
37 {
38 TFT_ShowString ( 10 , 110 , "I2C_Bus: FAIL" );
39 }
40 TFT_ShowString ( 10 , 110 , "I2C_Bus: OKAY" );
41 I2C_GenerateSTART ( I2C1 , ENABLE );
42 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_MODE_SELECT ))
43 {
44 TFT_ShowString ( 10 , 130 , "I2C_EventCheck2: FAIL" );
45 }
46 TFT_ShowString ( 10 , 130 , "I2C_EventCheck2: OKAY" );
47 I2C_Send7bitAddress ( I2C1 , 0xD1 , 1 );
48 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ))
49 {
50 TFT_ShowString ( 10 , 150 , "I2C_M_Trans3: FAIL" );
51 }
52 TFT_ShowString ( 10 , 150 , "I2C_M_Trans3: OKAY" );
53 I2C_Cmd ( I2C1 , ENABLE );
54 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_BYTE_RECEIVED ))
55 {
56 TFT_ShowString ( 10 , 170 , "I2C_Master_RX: FAIL" );
57 }
58 TFT_ShowString ( 10 , 170 , "I2C_Master_RX: OKAY" );
59 TFT_ShowNum ( 140 , 10 + ( j * 20 ), I2C_ReceiveData ( I2C1 ));
60 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_BYTE_RECEIVED ))
61 {
62 TFT_ShowString ( 10 , 190 , "I2C_Master_RX1: FAIL" );
63 }
64 TFT_ShowString ( 10 , 190 , "I2C_Master_RX1: OKAY" );
65 delay_ms ( 100 );
66 I2C_AcknowledgeConfig ( I2C1 , DISABLE );
67 while ( ! I2C_CheckEvent ( I2C1 , I2C_EVENT_MASTER_BYTE_RECEIVED ))
68 {
69 TFT_ShowString ( 10 , 210 , "I2C_Master_RX2: FAIL" );
70 }
71 TFT_ShowString ( 10 , 210 , "I2C_Master_RX2: OKAY" );
72 TFT_ShowNum ( 180 , 10 + ( j * 20 ), I2C_ReceiveData ( I2C1 ));
73 I2C_GenerateSTOP ( I2C1 , ENABLE );
74 while ( I2C_GetFlagStatus ( I2C1 , I2C_FLAG_STOPF ))
75 {
76 TFT_ShowString ( 10 , 230 , "I2C_Stop: FAIL" );
77 }
78 TFT_ShowString ( 10 , 230 , "I2C_Stop: OKAY" );
79 I2C_AcknowledgeConfig ( I2C1 , ENABLE );
80 delay_ms ( 100 );
81 }
82 TFT_ShowNum ( 10 , 280 , i );
83 i ++ ;
84 delay_ms ( 100 );
85 }
Die Routine läuft genau 1 mal durch, danach ist schluss. SDA wird immer
auf LOW gezogen.
Ich habe zu diesem Problem etliche Foren durchforstet, Manuals gelesen
und mich auch ausgiebig mit dem I2C bzw. TWI Bus beschäftigt und stoße
solangsam an meine Grenzen :-(
Leider habe ich kein Oszi daheim stehen.
Ich bedanke mich schon mal vorab für Tips / Kritik und weitere Infos zu
dem Thema I2C, STM32 sowie TPA81
Hallo,
ich empfehle dir folgende Infos anzuschauen:
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00209826.pdf
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Attachments/19516/i2croutines.c
Hier siehst du das es gar nicht so einfach ist mir der STM32 i2c HW zu
arbeiten. 1,2, und mehr bytes sind jeweils spezielle Sequenzen.
Ich vermute mal das du das lesen des letzten bytes anderst machen must.
Also vor dem lesen des letzten bytes ein STOP schicken.
Dein Device will vermutlich ein weiteres byte schicken und deshalb kann
der Master nichts schicken. Theoretisch könnte man auch einfach an der
SCL takten bis SDA auf high geht. Dann ist der Bus wieder frei.
Siehe z.B hier... http://www.microchip.com/forums/m175368-print.aspx
Aber das sollte man eigentlich nur als letzte möglichkeit verwenden.
Gruss
Michael
von
Klaus (Gast)
27.11.2012 16:05
Michael Andres schrieb:
> Also vor dem lesen des letzten bytes ein STOP schicken.
Das geht bei I2C nicht, Nach einem Stop wartet der Slave auf das nächste
Start mit folgender Adresse.
Der Fehler klingt nach "lesen mit ACK", statt beim letzten Byte "lesen
mit NACK" zu machen.
MfG Klaus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.