Forum: Mikrocontroller und Digitale Elektronik STM32: Über SPI ein TFT ansteuern (R61505U)


von Lasse S. (cowz) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hi,

ich habe hier ein TFT mit einem R61505U-Controller.

Dieser lässt sich über SPI ansteuern. Das klappt mit einem AVR auch ohne 
Probleme.

Nun möchte ich den AVR-Code (avr.c) auf einen STM32F103RB auf dem 
Olimex-H103 portieren.

Dabei funktioniert das Display nicht, bzw. es reagiert gar nicht erst.

Im Anhang findet ihr meinen AVR-Code (avr.c), unten die SPI-Funktionen 
für den STM.

Ich kann mir eigentlich nur vorstellen, dass der Fehler irgendwo in der 
SPI-Initialisierung oder den Funktionen spi_write und spi_wait liegt. 
Auch denkbar wären Compilersachen, die der AVR-GCC anders übersetzt als 
der CodeSourcery für meinen Cortex-M3.

Ich hoffe, ihr könnt mir helfen, bin mittlerweile etwas ratlos ;)

Gruß
Lasse

1
void DISPLAY_init(void) {
2
3
  SPI_InitTypeDef SPI_InitStructure;
4
  GPIO_InitTypeDef GPIO_InitStructure;
5
6
  // Clock enable
7
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
8
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
9
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
10
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
11
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
12
13
  // GPIO Init (SPI1)
14
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
15
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
17
  GPIO_Init(GPIOA, &GPIO_InitStructure);
18
19
  // GPIO Init RST
20
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
21
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
22
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
23
  GPIO_Init(GPIOB, &GPIO_InitStructure);
24
  LCD_RST_DISABLE();
25
26
  // GPIO Init CS
27
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;
28
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
29
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
30
  GPIO_Init(GPIOC, &GPIO_InitStructure);
31
  LCD_CS_DISABLE();
32
33
34
  // SPI Init
35
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
36
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
37
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8b
38
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // high
39
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 2 Edge
40
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
41
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //TODO: Geschwindkeiten testen
42
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // MSB
43
  SPI_InitStructure.SPI_CRCPolynomial = 7;
44
  SPI_Init(SPI1, &SPI_InitStructure);
45
  SPI_Cmd(SPI1, ENABLE);
46
}
1
void spi_write(uint8_t data) {
2
  SPI_I2S_SendData(SPI1, (uint16_t)data);
3
  spi_wait();
4
}
5
void spi_wait(void) {
6
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
7
}

von STM32-User (Gast)


Lesenswert?

Hallo!

Habe den Quelltext und das Datenblatt des TFT-Controllers zwar nur 
"kurz" überflogen, aber hast du nicht vergessen beim Code für den Cortex 
die Chip Select Leitungen zu setzen bzw. rücksetzen in spi_write() ??

Habe zwar kein adäquates Beispiel mit einer Ansteuerung für ein TFT über 
SPI, aber mit einem OLED. Bei mir sieht der Code folgendermaßen aus, 
bitte mit der Beachtung, dass ich die alte Firmware Library des STM32 
verwende(Version 1.0):

Vermute bei dir ebenfalls den Fehler in spi_write() und vor allem in 
spi_wait()
1
static void
2
write_oled( uint32_t byte_packet )
3
{
4
  uint16_t spi_rx_dummy = 0;
5
  // Enable chip select
6
  _CS_CLR;
7
  // Do a dummy read
8
  spi_rx_dummy = SPI_ReceiveData(SPI1);
9
  // Loop while DR register is not empty
10
  while (SPI_GetFlagStatus( SPI1, SPI_FLAG_TXE  ) == 0);
11
  SPI_SendData(SPI1, (uint16_t) byte_packet);
12
  // Wait to receive one byte
13
  while(!SPI_GetFlagStatus( SPI1, SPI_FLAG_RXNE ) == 0);
14
  spi_rx_dummy = SPI_ReceiveData(SPI1);
15
}

MfG

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Hi,

das mit CS ist nicht das Problem, dass funktioniert bei der AVR-Version 
auch ohne.

Unten nochmal die SPI-Funktionen auf dem AVR.

Eigentlich müsste das SPI auf dem STM doch genauso initialisiert sein, 
wie das auf dem AVR, oder?

Gruß
Lasse
1
void spi_init(void) {  
2
  
3
  // Set pinout
4
  PORTB |= (1<<SS);
5
  PORT_SPI |= (1<<MISO);
6
  PORT_SPI &= ~(1<<SCK);
7
  DDR_SPI |= (1<<SS) | (1<<SCK) | (1<<MOSI);
8
  
9
  // Set SPI  
10
  SPCR = (1<<SPE)    // SPI enable
11
     | (1<<MSTR);  // master mode
12
13
  // Fast Speed
14
  SPCR &= ~((1<< SPR1) | (1<<SPR0));
15
  SPSR |= (1<<SPI2X);
16
  // Slow Speed
17
  //SPCR |= (1<< SPR1) | (1<<SPR0);
18
  //SPSR &= ~(1<<SPI2X);
19
}
20
21
/* 
22
 * Sends byte over spi
23
 */
24
void spi_write(uint8_t data) {
25
  SPDR = data;
26
  
27
  while(!(SPSR & (1<<SPIF))) {
28
    asm volatile ("nop");
29
  }
30
}
31
32
33
void spi_wait(void) {
34
  while(!(SPSR & (1<<SPIF))) {
35
    asm volatile ("nop");
36
  }
37
}

von STM32-User (Gast)


Lesenswert?

Hallo!

Klar, die Initialisierung auf dem AVR und dem Cortex sollte gleich sein. 
Ob das wirklich so ist, ist eine andere Frage...
Hast du CPOL und CPHA korrekt konfiguriert und überprüft? Werden 
überhaupt Daten gesendet(messen)? Ich weiß, dass ich damals auch 
Startschwierigkeiten damit hatte, deshalb würde ich dir empfehlen, die 
Register wirklich GENAU zu kontrollieren und sicherzustellen, ob alles 
richtig ist, gegebenfalls das Reference Manual nochmals genau lesen, vor 
allem zu CPOL, CPHA und NSS.
Eventuell könnte es Probleme mit der Geschwindigkeit geben. Du 
verwendest "nur" einen Prescaler von 2, ist das nicht etwas zu schnell, 
bei ich denke mal 72MHz MCU-Speed?

Schönen Abend noch...

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Hallo!

Krass. Also erstmal: Danke schön! Ich stelle immer wieder fest, dass 
dieses Forum seeehr hilfreich ist!


Faszinierend: Ich hatte die gleiche Idee wie du... Nur habe ich es mit 
zwei Extremwerten ausprobiert, es funktioniert, sobald ich einen 
Prescaler von 16 einstelle!

Vielen Dank!

Gruß
Lasse

von Lasse S. (cowz) Benutzerseite


Lesenswert?

(edit nicht mehr erlaubt)

Mich wundert jetzt nur noch, dass es nur funktioniert, wenn der 
Prescaler zwischen 4 und 16 liegt. Dass das ganze nicht mehr 
funktioniert, wenn das SPI zu schnell ist (Prescaler=2) kann ich ja 
verstehen. Aber warum funktioniert das bei Prescaler=32 nicht mehr?

Gruß
Lasse

PS: In der Praxis isses mir egal, weil ich mich darüber freue, dass es 
funktioniert, und je schneller desto besser. Aber in der Theorie 
interessiert es mich. Zumal es beim AVR mit maximaler und minimaler 
Frequenz funktioniert hat.

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.