Forum: Mikrocontroller und Digitale Elektronik STM32F407, I2C LCD, Initialisierung


von Al3ko -. (al3ko)



Lesenswert?

Hi,

Ich versuche gerade, ein I2C LCD mittels STM32F407 zum Laufen zu 
bringen. Nach Anstecken des LCDs sehe ich zwei Balken. Nach der 
Initialisierung bekomme ich aber lediglich in der ersten Reihe einen 
Balken anstatt einen blinkenden Cursor oder was auch immer. Was ich 
festellen kann:

- Delays und I2C Schnittstelle funktionieren.
- Adresse des LCDs wird auch mit einem ACK beantwortet. Die Adresse ist 
also die Richtige.

IO Expander ist der PCF8574. Schaltplan befindet sich im Anhang und 
wurde von folgender Seite kopiert:
https://alselectro.wordpress.com/2016/05/12/serial-lcd-i2c-module-pcf8574/

Bilder vom Logik Analyzer sind ebenfalls im Anhang; sowohl die gesamte 
Initialisierung als auch zu jedem einzelnem Kommando der Initialiserung. 
Der Datenaustausch sieht richtig für mich aus? Ich verwendet konstant 
5ms Pause nach jedem Kommando, und 25us für den Enable Puls.

Meine I2C Kommunikation ist so eingestellt, dass ich nach jeder 
Instruktion (z.B. LCD_cmd(0x28)) nachdem die Daten gesendet wurden das 
Stoppbit in der I2C setze. Mache ich bei der Initialisierung etwas 
grundlegend falsch?

Die LCD Init Funktionen sowie die I2C Funktion sind hier:
1
void LCD_init()
2
{
3
  GPIO_init();
4
  I2C_init();
5
  delay_init();
6
7
  // Boot up
8
  delay_25us(200);  // 25us*200=5ms
9
  delay_25us(200);  // 25us*200=5ms
10
  delay_25us(200);  // 25us*200=5ms
11
12
  LCD_cmd(0x30);  // LCD soft reset
13
  delay_25us(200);  // 25us*200=5ms
14
15
  LCD_cmd(0x00);  // LCD enable
16
  delay_25us(200);  // 25us*200=5ms
17
18
  LCD_cmd(0x00);  // LCD enable
19
  delay_25us(200);  // 25us*200=5ms
20
21
22
  LCD_cmd(0x28);  // 4bit mode + Set function + 2 line
23
  delay_25us(200);  // 25us*200=5ms
24
25
  LCD_cmd(0x06);  // increment automatically
26
  delay_25us(200);  // 25us*200=5ms
27
28
  LCD_cmd(0x0F);  // Turn display on, cursor on, blinking on
29
  delay_25us(200);  // 25us*200=5ms
30
31
  LCD_cmd(0x01);  // Clear display
32
  delay_25us(200);  // 25us*200=5ms
33
34
  LCD_cmd(0x02);  // Cursor home
35
  delay_25us(200);  // 25us*200=5ms
36
}
1
void LCD_cmd(uint8_t data)
2
{
3
  I2C_send(data, 0);
4
}
1
void I2C_send(uint8_t data, uint8_t instruction)
2
{
3
  // Sending data
4
  // Generate start condition
5
  I2C1->CR1 |= (1<<I2C_CR1_START_Pos);  // Generate repeated start condition
6
  while(!(I2C1->SR1 & I2C_SR1_SB));    // Wait until Start bit is set
7
  uint8_t tempAddress = 0;
8
  uint8_t slaveAddress = 39;        // 0x27 = 39dec = 0b0010 0111
9
  tempAddress = (slaveAddress<<1);    // Make space on the 0th bit for R/W
10
  tempAddress &= ~(1<<0);          // Clear 0th bit for write
11
  I2C1->DR = tempAddress;          // Sends slave address
12
13
  while(!(I2C1->SR1 & I2C_SR1_ADDR));    // Wait until address is sent and acknowledged
14
  uint32_t temp1 = 0;
15
  temp1 = I2C1->SR1;
16
  temp1 = I2C1->SR2;
17
  (void)temp1;
18
19
  while(!(I2C1->SR1 & I2C_SR1_TXE));    // Wait for transmit ready
20
21
22
  uint8_t command = 0x00;
23
//  uint8_t command = 0x00;          // 0b00000000. Sets RS=0, RW=0, EN=0, Backlight=Off
24
  if(instruction == 0)
25
  {
26
    command = 0x08;            // 0b00001000. Sets RS=0, RW=0, EN=0, Backlight=On
27
  }
28
  else if(instruction == 1)
29
  {
30
    command = 0x09;            // 0b00001001. Sets RS=1, RW=0, EN=0, Backlight=On
31
  }
32
  else
33
  {
34
    // Error
35
  }
36
  uint8_t Nibble_H = 0;
37
  uint8_t Nibble_L = 0;
38
  Nibble_H = data & 0xF0;
39
  Nibble_L = data & 0x0F;
40
41
  I2C1->DR = Nibble_H | command;      // Sends high Nibble together with command
42
43
  while(!(I2C1->SR1 & I2C_SR1_TXE));
44
45
  while(!(I2C1->SR1 & I2C_SR1_BTF));
46
47
  I2C1->DR = (Nibble_L << 4) | command;  // Sends low Nibble
48
49
  while(!(I2C1->SR1 & I2C_SR1_TXE));
50
51
  while(!(I2C1->SR1 & I2C_SR1_BTF));
52
53
  I2C1->DR |= (1<<2);            // Enables pulse to secure command
54
55
  while(!(I2C1->SR1 & I2C_SR1_TXE));
56
57
  while(!(I2C1->SR1 & I2C_SR1_BTF));
58
59
  delay_25us(1);              // Waits 25us
60
61
  I2C1->DR &= ~(1<<2);          // Disables pulse again
62
63
  while(!(I2C1->SR1 & I2C_SR1_TXE));
64
65
  while(!(I2C1->SR1 & I2C_SR1_BTF));
66
67
  I2C1->CR1 |= (1<<I2C_CR1_STOP_Pos);    // Generate stop condition
68
69
  //    I2C1->CR1 &= ~(1<<I2C_CR1_PE_Pos);    // Turn off I2C1
70
71
}

von Thema Verfehlung (Gast)


Lesenswert?

Al3ko -. schrieb:
> Die LCD Init Funktionen sowie die I2C Funktion sind hier:

Mannomann ...
Längeren (als etwa eine Bildschirmseite) Source Code als Anhang!

von Al3ko -. (al3ko)


Angehängte Dateien:

Lesenswert?

Thema Verfehlung schrieb:
> Al3ko -. schrieb:
>> Die LCD Init Funktionen sowie die I2C Funktion sind hier:
>
> Mannomann ...
> Längeren (als etwa eine Bildschirmseite) Source Code als Anhang!

Sorry... :)

Anbei die Funktionen als Anhang.

SORRY.

Gruß,

von Harry L. (mysth)


Lesenswert?


von aiaiai (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe vor einer Weile mal angefangen und wollte für das Wiki hier 
PCF8574-HD44780 Infos eintragen. Den Code habe ich schon geschrieben und 
ausprobiert.

Ist zwar für AVR, aber durch die Fleury I2C Lib sehr gut abstrahiert und 
problemlos auf andere Controller übertragbar. Auf STM32 auch schon 
ausprobiert, nur finde ich da die Dateien nicht mehr.

Ich habe den Code von U. Radig für meine Zwecke angepasst/erweitert.

Hiermit hast du auf jeden Fall schonmal ein funktionierendes Beispiel.

von Al3ko -. (al3ko)


Angehängte Dateien:

Lesenswert?

Super - vielen Dank :)

Habe gleich mehrere Flüchtigkeitsfehler entdecken können.

Jetzt läuft es.

Gruß,

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.