Forum: Mikrocontroller und Digitale Elektronik STM32 F103 - I2C Probleme


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
Hallo alle Miteinander,
ich bin zur Zeit dabei, mich in die 32Bit Welt einzuarbeiten. Hierzu 
habe ich mir ein Nucleo Board gekauft. Nun möchte ich damit ein I2C 
Display zu laufen bringen.
Allerdings habe ich hierbei kein Erfolg. Warum auch immer kommt absolut 
kein I2C Signal raus (Oszi hängt an SDA und SCL).

Programmieren tu ich mit Atollic TrueStudio und STM32 CubeMX.
Die Hardwaresettings habe ich in CubeMX durchgeführt.

Verwendet habe ich erfolglos schon folgende Befehle:
1
HAL_I2C_Master_Transmit(&hi2c1, 0x3C, outbuffer, sizeof(outbuffer), 1);
2
3
HAL_I2C_Mem_Write(&hi2c1, 0xA0, 0x1AAA, I2C_MEMADD_SIZE_16BIT, (uint8_t*)wmsg,strlen(wmsg)+1, HAL_MAX_DELAY);

I2C Port ist in CubeMX auf Standard und auf Pin PB6 und PB7 eingestellt. 
Pullups sind angelötet (je 10kOhm)

Ich hoffe es kann mir jemand weiterhelfen. Ich bin mit meinem Latein am 
Ende.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> Verwendet habe ich erfolglos schon folgende Befehle:

Sonst nix zur Initialisierung? Das klappt wohl nicht...

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
HAL_I2C_Master_Transmit ist schon richtig.

Sonst tippe ich wieder auf das Type casting:

Beitrag "Re: STM32 i2c MCP23017 keine Kommunikation"

von Ralph S. (jjflash)


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> I2C Port ist in CubeMX auf Standard und auf Pin PB6 und PB7 eingestellt.
> Pullups sind angelötet (je 10kOhm)

2,2kOhm wären besser wobei ich nicht glaube, dass das dein Problem ist.

Niklas G. schrieb:
> Kevin X. schrieb:
>> Verwendet habe ich erfolglos schon folgende Befehle:
>
> Sonst nix zur Initialisierung? Das klappt wohl nicht...

Man sollte hier schon die komplette Initialisierung sehen...

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
Sind die Clocks für I2C sowie die zugehörigen I/O-Pins aktiviert ?
Wie gesagt eine vollständige Beschreibung der Initialisierung wäre 
hilfreich.

von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
Sorry,
ja anbei mal die Main (abgespeckt):
1
/* Includes ------------------------------------------------------------------*/
2
#include "main.h"
3
#include "stm32f1xx_hal.h"
4
5
/* USER CODE BEGIN Includes */
6
#include "string.h"
7
#include <stdio.h>
8
9
#include <stdarg.h>
10
#include <u8g_arm.h>
11
12
/* USER CODE BEGIN PV */
13
/* Private variables ---------------------------------------------------------*/
14
uint8_t outbuffer[2]={0x40,0xff};
15
16
//Display
17
static u8g_t u8g;
18
19
....
20
21
int main(void)
22
{
23
24
  /* USER CODE BEGIN 1 */
25
26
  /* USER CODE END 1 */
27
28
  /* MCU Configuration----------------------------------------------------------*/
29
30
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
31
  HAL_Init();
32
33
  /* USER CODE BEGIN Init */
34
35
  /* USER CODE END Init */
36
37
  /* Configure the system clock */
38
  SystemClock_Config();
39
40
  /* USER CODE BEGIN SysInit */
41
42
  /* USER CODE END SysInit */
43
44
  /* Initialize all configured peripherals */
45
  MX_GPIO_Init();
46
  MX_ADC1_Init();
47
  MX_I2C1_Init();
48
49
  /* USER CODE BEGIN 2 */
50
  DisplayInit();
51
  /* USER CODE END 2 */
52
53
  /* Infinite loop */
54
  /* USER CODE BEGIN WHILE */
55
  while (1)
56
  {
57
  /* USER CODE END WHILE */
58
59
  /* USER CODE BEGIN 3 */
60
    //SSD1307
61
    //Slave Adress vom Display = 3C
62
    //Display Ansteuerung:
63
64
 HAL_I2C_Master_Transmit(&hi2c1, 0x3C, outbuffer, sizeof(outbuffer), 1);
65
66
   //   u8g_SetFont(&u8g,u8g_font_04b_03b);//set current font
67
   //   u8g_DrawStr(&u8g, 2, 12, "Hallo!");//write string - you set coordinates and string
68
   //   u8g_DrawBox(&u8g, 30, 30, 35, 35);//draw some box
69
70
71
/*        while(HAL_I2C_Master_Transmit(&hi2c1, 0x3C,(uint8_t*) outbuffer, sizeof(outbuffer), (uint32_t)1000)!= HAL_OK)
72
      {
73
                      if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
74
                      {
75
                      //  HAL_printf("i2C Error\n\r");
76
                        GPIOA -> ODR ^= LD2_Pin;
77
                      }
78
      }
79
80
    while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
81
                    {
82
83
                    }
84
*/
85
86
87
 GPIOA -> ODR ^= LD2_Pin;
88
    HAL_Delay(2000);
89
  }
90
  /* USER CODE END 3 */
91
92
}
93
94
/* I2C1 init function */
95
static void MX_I2C1_Init(void)
96
{
97
98
  hi2c1.Instance = I2C1;
99
  hi2c1.Init.ClockSpeed = 100000;
100
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
101
  hi2c1.Init.OwnAddress1 = 0;
102
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
103
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
104
  hi2c1.Init.OwnAddress2 = 0;
105
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
106
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
107
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
108
  {
109
    _Error_Handler(__FILE__, __LINE__);
110
  }
111
112
}

In der stm32f1xx_hal_msp.c steht unter anderem noch:
1
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
2
{
3
4
  GPIO_InitTypeDef GPIO_InitStruct;
5
  if(hi2c->Instance==I2C1)
6
  {
7
  /* USER CODE BEGIN I2C1_MspInit 0 */
8
9
  /* USER CODE END I2C1_MspInit 0 */
10
  
11
    /**I2C1 GPIO Configuration    
12
    PB6     ------> I2C1_SCL
13
    PB7     ------> I2C1_SDA 
14
    */
15
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
16
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
17
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
18
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
19
20
    /* Peripheral clock enable */
21
    __HAL_RCC_I2C1_CLK_ENABLE();
22
    /* I2C1 interrupt Init */
23
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
24
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
25
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
26
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
27
  /* USER CODE BEGIN I2C1_MspInit 1 */
28
29
  /* USER CODE END I2C1_MspInit 1 */
30
  }
31
32
}

@pegel: mit Type casting meinst du, dass ich das falsche Dateiformat in 
den I2C Transmit schreiben will?

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So in etwa.
1
HAL_I2C_Master_Transmit(&hi2c1, 0x3C, outbuffer, sizeof(outbuffer), 1);
wird zu:
1
HAL_I2C_Master_Transmit(&hi2c1,(uint16_t)0x3C,(uint8_t*)outbuffer,sizeof(outbuffer),1);

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
Du hast I2C-Interrupts aktiviert, benutzt aber die polling-Funktion.
Vielleicht kommentierst du einfach mal folgende Zeilen in der 
stm32f1xx_hal_msp.c aus:

//    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
//    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
//    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
//    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);

Wenn Du Interrupts benutzen willst, musst Du mit den dafür geeigneten 
Funktionen arbeiten, z.B. HAL_I2C_Master_Transmit_IT(...) (siehe 
stm32f1xx_hal_i2c.h)

von Kevin X. (odwquad)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Klaus S. schrieb:
> Du hast I2C-Interrupts aktiviert, benutzt aber die polling-Funktion.
> Vielleicht kommentierst du einfach mal folgende Zeilen in der
> stm32f1xx_hal_msp.c aus:
>
> //    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
> //    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
> //    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
> //    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
>
> Wenn Du Interrupts benutzen willst, musst Du mit den dafür geeigneten
> Funktionen arbeiten, z.B. HAL_I2C_Master_Transmit_IT(...) (siehe
> stm32f1xx_hal_i2c.h)

Das habe ich gerade mal gemacht, aber kein Erfolg.

Aus dem Link von pegel habe ich mal den Code ausprobiert:
1
uint8_t I2C_Write_Byte(uint8_t addr, uint8_t data)
2
{
3
  uint8_t buf1[] = {addr, data};
4
  uint8_t d;
5
  while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
6
  d =  HAL_I2C_Master_Transmit(&hi2c1,(uint16_t)SLAVE_ADDRESS,(uint8_t*)buf1,(uint16_t)sizeof(buf),TIMEOUT);
7
 // d = HAL_I2C_Master_Transmit(&hi2c2, SLAVE_ADDRESS, buf, 2, TIMEOUT);
8
  if ( d != HAL_OK) {
9
      return d;
10
  }
11
  return HAL_OK;
12
}

in der Main mit:
1
I2C_Write_Byte(0x12, 0xFF);
 aufgerufen. Ebenfalls ohne Erfolg.

d ist im debug auf 2 anstatt 0.


Anbei noch zwei Screenshots aus dem Debugging.

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
d==2 bedeutet HAL_BUSY. Vermutlich ist der I2C-Bus durch eine nicht 
erfolgreiche vorhergehende Transaktion blockiert.
Was macht denn die Funktion "DisplayInit()" in der main? Falls da 
I2C-Transaktionen stattfinden solltest Du die Funktion auch mal 
auskommentieren.

Welches Display möchtest Du denn ansteuern ?

von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
Klaus S. schrieb:
> d==2 bedeutet HAL_BUSY. Vermutlich ist der I2C-Bus durch eine nicht
> erfolgreiche vorhergehende Transaktion blockiert.
> Was macht denn die Funktion "DisplayInit()" in der main? Falls da
> I2C-Transaktionen stattfinden solltest Du die Funktion auch mal
> auskommentieren.
>
> Welches Display möchtest Du denn ansteuern ?

Ah okay. Das ist schonmal gut zu wissen.
Ja im DisplayInit() wird das Display initialisiert mit der u8g Lib. Das 
habe ich aber auch schon auskommentiert gehabt. bzw. bei dem obrigen 
letzten Test, wo auch die Screenshots aus dem Debuging dabei sind, ist 
das nicht mehr einkommentiert.
Ich will den Fehler eingrenzen und daher hab ich nur die I2C_Write_Byte 
Funktion aktuell aktiv. Aber es geht einfach nicht.

von I2c (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Oft hängen sich die I2C Bausteine auf, wenn sie falsch angesteuert 
werden. Ist mir oft in der Entwicklungsphase mit Temperatursensoren so 
ergangen. Vielleicht trennst du mal die Spannungsversorgung und probiert 
danach nochmal. Ein Logikanalysator am Bus kann vllt auch nicht schaden.

von Klaus S. (skibby)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Mir fallen spontan noch folgende Punkte ein:
- SDA und SCL korrekt verbunden (hatte ich auch schon mal vertauscht)
- Device-Adresse korrekt ?

Ich hänge Dir mal meine u8g-Initialisierungsroutinen für ein 
SSD1306-Display an. Die main.c ist auf die relevanten Teile gekürzt.

von Kevin X. (odwquad)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Klaus S. schrieb:
> Mir fallen spontan noch folgende Punkte ein:
> - SDA und SCL korrekt verbunden (hatte ich auch schon mal vertauscht)
> - Device-Adresse korrekt ?
>
> Ich hänge Dir mal meine u8g-Initialisierungsroutinen für ein
> SSD1306-Display an. Die main.c ist auf die relevanten Teile gekürzt.

Danke für die Dateien, leider funktionieren diese bei mir nicht, da er 
einige weitere Bibliotheken nicht findet bzw. Funktionen welche sich 
wahrscheinlich in irgendwelchen anderen header Datein befindetn.


EDIT: Anbei noch mein komplettes Testprojekt. Vielleicht kann sich das 
ja jemand mal anschauen.

: Bearbeitet durch User
von C. W. (chefkoch)


Bewertung
0 lesenswert
nicht lesenswert
Ganz blöde Frage: Sind die PullUps definitiv auf dem Bus?

von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
C. W. schrieb:
> Ganz blöde Frage: Sind die PullUps definitiv auf dem Bus?

ja sonst hätte ich ja keine 3,3v auf dem bus

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
In der main.c passiert ja gar nichts.
Selbst in den auskommentierten Versuchen hast du das Display nicht 
initialisiert. Wie soll das ein ACK zu Stande kommen?

von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
pegel schrieb:
> In der main.c passiert ja gar nichts.
> Selbst in den auskommentierten Versuchen hast du das Display nicht
> initialisiert. Wie soll das ein ACK zu Stande kommen?

Ich versuche ja erstmal nur irgendwas auf den Bus zu senden. Oder geht 
das so nicht?
Brauch ich immer ein Empfänger? Das mit dem Display soll dann später 
gemacht werden. Aber da das nicht funktioniert hatte, habe ich jetzt 
alles komplett abgespeckt und nur Pullup dran und fertig.

von Pete K. (pete77)


Bewertung
0 lesenswert
nicht lesenswert
Welches I2C Display? Ist das auch für 3V3 spezifiziert? Leitungslänge?

Schaltplan und Aufbau bitte. Und den ganzen Quellcode.

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich empfehle das I2C Protokoll zu studieren.
Und dann die Initialisierung des SSD1307.

Für den Anfang wäre vielleicht ein PCF8574 ein guter Kandidat um eine 
Ein- und Ausgabe zu programmieren.

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Kevin,
habe ich richtig verstanden, Du hast gar nichts am I2C angeschlossen ?
Das geht so nicht, da die Kommunikation nur funktioniert wenn der 
Partner angeschlossen ist !

von Kevin X. (odwquad)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
anbei das komplette Projekt (dieses mal mit Display Einbindung), dann 
der Schaltplan, sowie die Datenblätter vom Display.

von Kevin X. (odwquad)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So ich hab das Display mal dran gehängt und nochmal meine U8g Lib 
aufgespielt.
Jetzt bekom ich auf der SDA Leitung Zyklisch ein Signal (Siehe Anhang).
Auf der SDL Leitung passiert aber nix (durchgehend 3,3V).

Code:
1
void draw(void)
2
{
3
  u8g_SetFont(&u8g,u8g_font_profont10);//set current font
4
  u8g_DrawStr(&u8g, 2, 12, "Hello!");//write string - you set coordinates and string
5
  u8g_DrawBox(&u8g, 30, 30, 35, 35);//draw some box
6
}
7
8
9
/* USER CODE END 0 */
10
11
int main(void)
12
{
13
14
  /* USER CODE BEGIN 1 */
15
16
  /* USER CODE END 1 */
17
18
  /* MCU Configuration----------------------------------------------------------*/
19
20
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
21
  HAL_Init();
22
23
  /* USER CODE BEGIN Init */
24
25
  /* USER CODE END Init */
26
27
  /* Configure the system clock */
28
  SystemClock_Config();
29
30
  /* USER CODE BEGIN SysInit */
31
32
  /* USER CODE END SysInit */
33
34
  /* Initialize all configured peripherals */
35
  MX_GPIO_Init();
36
  MX_ADC1_Init();
37
  MX_I2C1_Init();
38
  MX_RTC_Init();
39
40
  /* USER CODE BEGIN 2 */
41
  u8g_InitComFn(&u8g, &u8g_dev_ssd1306_128x32_i2c, u8g_com_hw_i2c_fn); //here we init our u8glib driver
42
  /* USER CODE END 2 */
43
44
  /* Infinite loop */
45
  /* USER CODE BEGIN WHILE */
46
  while (1)
47
  {
48
  /* USER CODE END WHILE */
49
50
  /* USER CODE BEGIN 3 */
51
    //SSD1307
52
    //Slave Adress vom Display = 3C
53
  
54
    u8g_FirstPage(&u8g);
55
     do
56
     {
57
       draw();
58
       }
59
     while ( u8g_NextPage(&u8g) );
60
       u8g_Delay(10);
61
62
63
 GPIOA -> ODR ^= LD2_Pin;
64
    HAL_Delay(2000);
65
  }
66
  /* USER CODE END 3 */
67
68
}

: Bearbeitet durch User
von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> Jetzt bekom ich auf der SDA Leitung Zyklisch ein Signal

Was soll das sein? Ein Signal?
Ich dachte an ein Profil von einem Abwassergraben.

Ist die u8g eigentlich deine einzige Option, oder würden es auch 
einfache Funktionen tun?

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> I2C Port ist in CubeMX auf Standard und auf Pin PB6 und PB7 eingestellt.

Die .ioc in deiner letzten zip sieht aber anders aus.

PB8 -> I2C1_CLK
PB9 -> I2C2_DAT

Ausserdem kann der SSD1306 auch mit 400kHz umgehen.

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
PB9 -> I2C1_DAT

natürlich.

von Kevin X. (odwquad)


Bewertung
0 lesenswert
nicht lesenswert
pegel schrieb:
> Kevin X. schrieb:
>> I2C Port ist in CubeMX auf Standard und auf Pin PB6 und PB7 eingestellt.
>
> Die .ioc in deiner letzten zip sieht aber anders aus.
>
> PB8 -> I2C1_CLK
> PB9 -> I2C2_DAT
>
> Ausserdem kann der SSD1306 auch mit 400kHz umgehen.

Ja ich hab das mal auf diese Ports geändert, da ich dachte, vielleicht 
ist ein Port kaputt.
Probiere halt alles mögliche aus. Bin schon die ganze Woche an diesem 
I2C dran....

Ich weiß, dass dieses Signal kein I2C Signal ist, aber das kommt nunmal 
raus. Schön alle 2Sekunden, wie mein Delay ist.
Es geht auch ohne Lib, aber da tut sich dann gar nichts. Also wenn ich 
mit den normalen I2C Funktionen was senden möchte...

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
Bei 100kHz I2C-Frequenz solltest Du die Zeitbasis Deines Oszilloskops 
nochmals überdenken :-)

Kevin X. schrieb:
> So ich hab das Display mal dran gehängt und nochmal meine U8g Lib
> aufgespielt.
> Jetzt bekom ich auf der SDA Leitung Zyklisch ein Signal (Siehe Anhang).
> Auf der SDL Leitung passiert aber nix (durchgehend 3,3V).
>

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
folgendes ist mir noch aufgefallen:

in der u8g_arm.c benutzt Du I2C_Handler, in der main.c hi2c1. Das passt 
schin mal nicht zusammen.

In die Funktion u8g_com_hw_i2c_fn würde ich folgendes schreiben:


  case U8G_COM_MSG_WRITE_BYTE:
  {
    hal_status = HAL_I2C_Mem_Write(&hSSD1306_I2C, SSD1306_I2C_ADDRESS, 
control, 1, &arg_val, 1, SSD1306_I2C_TIMEOUT);
  }
  break;

  case U8G_COM_MSG_WRITE_SEQ:
  case U8G_COM_MSG_WRITE_SEQ_P:
  {
    hal_status = HAL_I2C_Mem_Write(&hSSD1306_I2C, SSD1306_I2C_ADDRESS, 
control, 1, arg_ptr, arg_val, SSD1306_I2C_TIMEOUT);
  }

    break;
Funktioniert bei mir wunderbar. Sorry für die Formatierung :-)

von Johnny B. (johnnyb)


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> Ich hoffe es kann mir jemand weiterhelfen. Ich bin mit meinem Latein am
> Ende.

Habe irgendwo gelesen, dass man im vom CubeMX generierten Code in der 
Funktion "HAL_I2C_MspInit" die I2C Clock mit __HAL_RCC_I2C1_CLK_ENABLE() 
bereits aktivieren soll, bevor das HAL_GPIO_Init aufgerufen wird.

von W.S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kevin X. schrieb:
> Ich bin mit meinem Latein am Ende.

gallia est omnis divisa in partes tres...

Und warum versuchst du es dann nicht mal ganz simpel per Software? Ich 
nehme ja mal an, daß du an deinem I2C nur ein Gerät, nämlich das Display 
dran hast. Also könntest du ja (!!!) zu allererst mal versuchen, die 
beiden Portbeine Clk und Data als O.C. GPIO zu schalten und in aller 
Ruhe auszuprobieren, ob du da per Kommando auch wirklich hi und lo sehen 
kannst. Anschließend schreibst du dir ne Mini-Routine um ein Byte 
auszugeben und Ack zu empfangen. Dann noch eine Mini-Routine, mit der du 
alle I2C-Adressen abklapperst und guckst, ob und wo du ein Ack bekommst.

Das alles ist ja nun wirklich nicht schwer - und es hilft dir ungemein, 
erstmal herauszubekommen, ob deine Leitungen zum Display richtig 
verschaltet sind, ob deine I2C-Pins sich rühren, ob dein Display auf den 
erwarteten Adressen auch wirklich sich zeigt - und wenn du schon soweit 
gekommen bist, dann kannst du auf dieser Soft-Basis auch deine gesamte 
Display-Ausgabe in die Gänge kriegen. Den I2C-Peripheriecore dann 
anzuwerfen und dir auf dessen Basis einen passenden Display zu 
schreiben, kannst du dann anschließend erledigen, sobald du wenigstens 
die allerersten Steine aus dem Weg geräumt hast.

Nochwas: in vielen Fällen ist eine reine Softwarelösung gerade beim I2C 
völlig ausreichend - und es ist mit weitem Abstand die simpelste Lösung, 
die schlichtweg überall funktioniert. Das klingt erstmal verwunderlich, 
stimmt aber. Grund ist im Prinzip, daß man ja beim I2C ja sowieso fast 
immer auf das Ende aller einzelnen Übertragungen und das Ack warten muß. 
Das ist ganz anders als z.B. beim UART, wo man sehr schön gepuffert und 
per Interrupt arbeiten kann.

W.S.

von Kevin X. (odwquad)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe jetzt heute früh den Nucleo an der gleichen Schaltung 
gestartet sowie das Oszi eingeschaltet. Und siehe da es kommt mehr als 
am Freitag, obwohl ich nichts an der Programmierung oder Hardware 
gemacht habe.
Anbei hierzu die Screenshots.

Wie man aber sieht, sind es keine sauberen Rechtecksignale.

Ich werde nun noch die in den letzten Beiträgen stehenden Tipps mal 
ausprobieren.

von Kevin X. (odwquad)


Bewertung
-1 lesenswert
nicht lesenswert
so endlich habe ich was auf dem Display. Warum weiß ich aber noch nicht 
so richtig.

Ich habe einmal den Tipp von Klaus umgesetzt und in die u8g_arm.c lib 
den Befehl
1
hal_status = HAL_I2C_Mem_Write(&hi2c1, DEVICE_ADDRESS<<1, control, 1, arg_ptr, arg_val, I2C_TIMEOUT);
 reingeschrieben.
Außerdem die Device_ADDRESS um 1 verringert.

Außerdem bin ich dem Hinweis von Johnny mal nachgegangen und habe in der 
stm32f1xx_hal_msp.c die HAL_I2C_MSPInit angepasst:
1
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
2
{
3
4
  GPIO_InitTypeDef GPIO_InitStruct;
5
  if(hi2c->Instance==I2C1)
6
  {
7
  /* USER CODE BEGIN I2C1_MspInit 0 */
8
9
  /* USER CODE END I2C1_MspInit 0 */
10
  
11
    /**I2C1 GPIO Configuration    
12
    PB6     ------> I2C1_SCL
13
    PB7     ------> I2C1_SDA 
14
    */
15
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
16
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
17
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
18
19
    __HAL_RCC_I2C1_CLK_ENABLE();
20
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
21
22
    /* Peripheral clock enable */
23
   // __HAL_RCC_I2C1_CLK_ENABLE();    //Diesen Befehl vor HAL_GPIO_Init
24
  /* USER CODE BEGIN I2C1_MspInit 1 */
25
26
  /* USER CODE END I2C1_MspInit 1 */
27
  }
28
29
}

Jetzt muss ich das Display noch invertieren, da alles spiegelverkehrt 
dargestellt ist.
Dann werde ich weiter experimentieren.
Ich hoffe, dass es der Fehler war :-)


Ach ja. Das I2C Signal ist jetzt auch sauber Rechteckig wie es sein 
sollte.

: Bearbeitet durch User
von Äxl (geloescht) (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Du kannst doch da nicht einfach nacheinander irgentwas "ausprobieren"...
Schnapp Dir das Datenblatt vom Controller und sieh Dir an, wie die 
Hardware im µC verwendet. Wie willst Du jemals einen Fehler finden, wenn 
mal etwas nicht funtkioniert?!?
Ich finde diese Herangehensweise abenteuerlich, nur mal so.

von nico_2010 (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Hello, Kevin XY

You must shift left for 1 bit the address of your I2C device (no matter 
you write or read) because the value is only on 7 bits expressed (or 0 - 
127).
Left shifting makes room for the last bit wich is R/W bit.
If you study the file stm32fxxx_hal_i2c (.c and .h) of your uC you will 
see that addressing mode is on 7 bits or 10 bits (ex. #define 
I2C_ADDRESSINGMODE_7BIT or #define I2C_ADDRESSINGMODE_10BIT) and nowhere 
the value of this address is shifted one bit left to treat R/W bit.
I discover it on the hard way.

Best regards

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.