ILI9341 con problemas STM32 SPI

1

Estoy intentando conectar con una pantalla SPI ILI9341 usando un microcontrolador STM32. Sé que hay muchas cosas que pueden ir mal con estas interfaces, y he pasado mucho tiempo buscando y resolviendo problemas. Pero no sé por qué mi pantalla parece tener éxito en su inicialización, pero se niega a mostrar cualquier color.

Lo que estoy viendo es que las pantallas 'se encienden' a un color gris parpadeante, después de lo cual ignoran los comandos 'establecer ventana de dirección / enviar datos' que deberían dibujar colores en la pantalla.

Aquí están los comandos que estoy enviando: los métodos 'spi_write_ [comando | datos]' simplemente establecen D / C bajo o alto respectivamente y luego envían un byte sobre el periférico, y los comandos / datos son de varios otros. bibliotecas, en su mayoría de Adafruit. Los he revisado varias veces y he intentado ajustar algunos comandos, incluido el tiempo SPI, pero nada parece ayudar.

ILI9341 Comandos de inicialización:

LDR  r1, =0x000000EF
BL   spi_write_command
LDR  r1, =0x00000003
BL   spi_write_data
LDR  r1, =0x00000080
BL   spi_write_data
LDR  r1, =0x00000002
BL   spi_write_data

LDR  r1, =0x000000CF
BL   spi_write_command
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x000000C1
BL   spi_write_data
LDR  r1, =0x00000030
BL   spi_write_data

LDR  r1, =0x000000ED
BL   spi_write_command
LDR  r1, =0x00000064
BL   spi_write_data
LDR  r1, =0x00000003
BL   spi_write_data
LDR  r1, =0x00000012
BL   spi_write_data
LDR  r1, =0x00000081
BL   spi_write_data

LDR  r1, =0x000000E8
BL   spi_write_command
LDR  r1, =0x00000085
BL   spi_write_data
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x00000078
BL   spi_write_data

LDR  r1, =0x000000CB
BL   spi_write_command
LDR  r1, =0x00000039
BL   spi_write_data
LDR  r1, =0x0000002C
BL   spi_write_data
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x00000034
BL   spi_write_data
LDR  r1, =0x00000002
BL   spi_write_data

LDR  r1, =0x000000F7
BL   spi_write_command
LDR  r1, =0x00000020
BL   spi_write_data

LDR  r1, =0x000000EA
BL   spi_write_command
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x00000000
BL   spi_write_data

LDR  r1, =0x000000C0 // (Power control 1)
BL   spi_write_command
LDR  r1, =0x00000023
BL   spi_write_data

LDR  r1, =0x000000C1 // (Power control 2)
BL   spi_write_command
LDR  r1, =0x00000010
BL   spi_write_data

LDR  r1, =0x000000C5 // (VCOM control 1)
BL   spi_write_command
LDR  r1, =0x0000002B
BL   spi_write_data
LDR  r1, =0x0000002B
BL   spi_write_data

LDR  r1, =0x000000C7 // (VCOM offset)
BL   spi_write_command
LDR  r1, =0x000000C0
BL   spi_write_data

LDR  r1, =0x00000036 // (Memory access type)
BL   spi_write_command
LDR  r1, =0x00000048
BL   spi_write_data

LDR  r1, =0x0000003A // (Pixel format)
BL   spi_write_command
LDR  r1, =0x00000055
BL   spi_write_data

LDR  r1, =0x000000B1 // (Framerate control)
BL   spi_write_command
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x0000001B
BL   spi_write_data

LDR  r1, =0x000000B6 // (Display function)
BL   spi_write_command
LDR  r1, =0x00000008
BL   spi_write_data
LDR  r1, =0x00000082
BL   spi_write_data
LDR  r1, =0x00000027
BL   spi_write_data

LDR  r1, =0x000000F2 // (Gamma select)
BL   spi_write_command
LDR  r1, =0x00000000
BL   spi_write_data

LDR  r1, =0x00000026 // (Gamma set)
BL   spi_write_command
LDR  r1, =0x00000001
BL   spi_write_data

LDR  r1, =0x000000E0 // (Gamma curve)
BL   spi_write_command
LDR  r1, =0x0000000F
BL   spi_write_data
LDR  r1, =0x00000031
BL   spi_write_data
LDR  r1, =0x0000002B
BL   spi_write_data
LDR  r1, =0x0000000C
BL   spi_write_data
LDR  r1, =0x0000000E
BL   spi_write_data
LDR  r1, =0x00000008
BL   spi_write_data
LDR  r1, =0x0000004E
BL   spi_write_data
LDR  r1, =0x000000F1
BL   spi_write_data
LDR  r1, =0x00000037
BL   spi_write_data
LDR  r1, =0x00000007
BL   spi_write_data
LDR  r1, =0x00000010
BL   spi_write_data
LDR  r1, =0x00000003
BL   spi_write_data
LDR  r1, =0x0000000E
BL   spi_write_data
LDR  r1, =0x00000009
BL   spi_write_data
LDR  r1, =0x00000000
BL   spi_write_data

LDR  r1, =0x000000E1 // (Gamma curve)
BL   spi_write_command
LDR  r1, =0x00000000
BL   spi_write_data
LDR  r1, =0x0000000E
BL   spi_write_data
LDR  r1, =0x00000014
BL   spi_write_data
LDR  r1, =0x00000003
BL   spi_write_data
LDR  r1, =0x00000011
BL   spi_write_data
LDR  r1, =0x00000007
BL   spi_write_data
LDR  r1, =0x00000031
BL   spi_write_data
LDR  r1, =0x000000C1
BL   spi_write_data
LDR  r1, =0x00000048
BL   spi_write_data
LDR  r1, =0x00000008
BL   spi_write_data
LDR  r1, =0x0000000F
BL   spi_write_data
LDR  r1, =0x0000000C
BL   spi_write_data
LDR  r1, =0x00000031
BL   spi_write_data
LDR  r1, =0x00000036
BL   spi_write_data
LDR  r1, =0x0000000F
BL   spi_write_data

LDR  r1, =0x00000020 // No display inversion.
BL   spi_write_command
// (Delay >=120ms)
MOVS r3, #120
BL   delay_ms
LDR  r1, =0x00000011 // Exit sleep mode
BL   spi_write_command
// (Delay >=120ms)
MOVS r3, #120
BL   delay_ms
LDR  r1, =0x00000029 // Display on
BL   spi_write_command

Llenar pantalla con color: esto simplemente establece la 'ventana de dirección' en toda la pantalla y luego escribe un solo color 240 * 320 veces:

// Set address window; r4-r7 hold x/y values, for whole screen:
// X = [0:239], Y = [0:319]
// Set the 'display addressing' window to the whole screen.
MOVS r4, #0
MOVS r5, #239
MOVS r6, #0
LDR  r7, =0x0000013F // (319)
LDR  r2, =0x000000FF
// Column-set
LDR  r1, =0x0000002A
BL   spi_write_command
// Min-X
MOVS r1, r4
LSRS r1, r1, #8
BL   spi_write_data
MOVS r1, r4
ANDS r1, r1, r2
BL   spi_write_data
// Max-X
MOVS r1, r5
LSRS r1, r1, #8
BL   spi_write_data
MOVS r1, r5
ANDS r1, r1, r2
BL   spi_write_data
// Row-set
LDR  r1, =0x0000002B
BL   spi_write_command
// Min-Y
MOVS r1, r6
LSRS r1, r1, #8
BL   spi_write_data
MOVS r1, r6
ANDS r1, r1, r2
BL   spi_write_data
// Max-Y
MOVS r1, r7
LSRS r1, r1, #8
BL   spi_write_data
MOVS r1, r7
ANDS r1, r1, r2
BL   spi_write_data
// RAM-Write command.
LDR  r1, =0x0000002C
BL   spi_write_command
// Write the given color (16-bit) 240*320 times, 1 for each pixel.
LDR  r7, =0x00000140
MOVS r4, #240
MULS r4, r4, r7
MOVS r5, r3
LDR  r6, =0x000000FF
ANDS r5, r5, r6
MOVS r6, r3
LSRS r6, r6, #8
ili9341_fill_screen_write_px:
    MOVS r1, r6
    BL   spi_write_data
    MOVS r1, r5
    BL   spi_write_data
    SUBS r4, r4, #1
    BNE  ili9341_fill_screen_write_px

Gracias por cualquier ayuda! He comprobado que las señales de cada pin están llegando a las pantallas con un osciloscopio, incluso los pines Data / Command y CS, por lo que no tengo ninguna idea de lo que podría estar mal.

    
pregunta Will

1 respuesta

0

De acuerdo, no me tomó mucho tiempo abandonar la idea de usar lenguaje ensamblador para presentar a las personas a los microcontroladores, y finalmente lo resolví.

La pantalla gris parpadeante que observé parece que es un estado normal de "inicio" para la pantalla cuando se realiza un reinicio del hardware tirando del pin de reinicio hacia abajo y luego hacia arriba.

Pero el periférico SPI del STM32 envía el contenido completo de su "Registro de datos" de 16 bits a menos que use algunas convenciones específicas. Es más fácil convertir el registro en un puntero a un entero de 8 bits.

Configuración de SPI (usando los archivos de encabezado del dispositivo ST):

void hspi_init(SPI_TypeDef *SPIx) {
  // Ensure that the peripheral is disabled, and reset it.
  SPIx->CR1 &= ~(SPI_CR1_SPE);
  if (SPIx == SPI1) {
    RCC->APB2RSTR |=  (RCC_APB2RSTR_SPI1RST);
    RCC->APB2RSTR &= ~(RCC_APB2RSTR_SPI1RST);
  }
  // Set clock polarity/phase to 0/0 or 1/1.
  SPIx->CR1 |=  (SPI_CR1_CPOL |
                 SPI_CR1_CPHA);
  // Set the STM32 to act as a host device.
  SPIx->CR1 |=  (SPI_CR1_MSTR);
  // Set software 'Chip Select' signal.
  SPIx->CR1 |=  (SPI_CR1_SSM);
  // Set the internal 'Chip Select' signal.
  SPIx->CR1 |=  (SPI_CR1_SSI);
  // Use MSB-first format.
  SPIx->CR1 &= ~(SPI_CR1_LSBFIRST);
  // Set the Baud rate prescaler.
  SPIx->CR1 &= ~(SPI_CR1_BR);
  // Start slow? SPI_clock = Core_clock / (2 ^ (BR))
  // So, a value of 4 should slow things down by a factor of 16.
  //SPIx->CR1 |=  (0x4 << SPI_CR1_BR_Pos);
  // Enable the peripheral.
  SPIx->CR1 |=  (SPI_CR1_SPE);
}

Función 'Escribir byte':

inline void hspi_w8(SPI_TypeDef *SPIx, uint8_t dat) {
  // Wait for TXE.
  while (!(SPIx->SR & SPI_SR_TXE)) {};
  // Send the byte.
  *(uint8_t*)&(SPIx->DR) = dat;
}

Con esas configuraciones, parece funcionar.

    
respondido por el Will

Lea otras preguntas en las etiquetas