Problema al conectar la pantalla de NewHaven oled con stm32f4

0

Los últimos dos días he estado intentando conectar una NewHaven Dislpay con mi stm32f4 Tablero de descubrimiento sin resultado.

La hoja de datos proporciona ejemplos escritos incorrectos sobre cómo inicializar esta pantalla y me está costando mucho entender cómo funciona esta pantalla. Actualmente estoy usando SPI y aunque hice las conexiones apropiadas (según la hoja de datos), la pantalla se niega a funcionar.

El stm32f4 está sincronizado a 168MHz

El código de inicialización SPI es el siguiente:

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_1LINE;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;

El código que escribí es el siguiente:

void oled_Data(unsigned char Data) 
{
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);      //Set the D/C Pin
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);    //Lower the CS                                                                                                    
  HAL_SPI_Transmit(&hspi1, &Data, 1, 50);
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);      //Set the CS

}

  void oled_Command(unsigned char address)
 {
   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);   //Reset the D/C pin
   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET); //Lower the CS pin
   HAL_SPI_Transmit(&hspi1, &address, 1, 50);
   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);   //Set the CS pin                    
   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);   //Set the D/C pin

  }

    void Init()
   {
     unsigned int i=0,j,k;
     const unsigned char init_commands[]= {
     0x06, // Display off
     0x00,

    //Osc control
    //Export1 internal clock and OSC operates with external resistor
    0x02,
    0x01,

    // Disable OSC Power Down
    0x04,
    0x03,

    // Set normal driving current
    0x04,
    0x00,

    //Clock div ratio 1: freq setting 120Hz
    0x03,
    0x90,

    //Iref controlled by external resistor
    0x80,
    0x01,

    //Precharge time R
    0x08,
    0x04,
    //Precharge time G
    0x09,
    0x05,
    //Precharge time B
    0x0A,
    0x05,

    //Precharge current R
    0x0B,
    0x9D,
    //Precharge current G
    0x0C,
    0x8C,
    //Precharge current B
    0x0D,
    0x57,

    //Driving current R
    0x10,
    0x56,
    //Driving current G
    0x11,
    0x4D,
    //Driving current B
    0x12,
    0x46,

    //Display mode set
    //RGB,column=0-159, column data display=Normal display
    0x13,
    0x00,

    //External interface mode=MPU
    0x14,
    0x11,

    //Memory write mode
    //6 bits triple transfer, 262K support, Horizontal address counter is increased,
    //vertical address counter is increased. The data is continuously written
    //horizontally
    0x16,
    0x66,

    //Memory address setting range 0x17~0x19 to width x height
    0x17,  //Column start
    0x00,
    0x18,  //Column end

    0x19,  //row start
    0x00,
    0x1A,  //row end


    //Memory start address set to 0x20~0x21
    0x20,  //X
    0x00,
    0x21,  //Y
    0x00,

    //Duty
    0x28,
    0x7F,

    //Display start line
    0x29,
    0x00,

    //DDRAM read address start point 0x2E~0x2F
    0x2E,  //X
    0x00,
    0x2F,  //Y
    0x00,

    //Display screen saver size 0x33~0x36
    0x33,  //Screen saver columns start
    0x00,
    0x34,  //Screen saver columns end
    0x35,  //screen saver row start
    0x00,
    0x36,  //Screen saver row end

    //Display ON
    0x06,
    0x01,

    //Disable Power Save
    0x05,
    0x00,

    //End of commands
    0xFF,
    0xFF
};

//Initialize interface and reset display driver chip

 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET); //Lower the RES pin
 HAL_Delay(500); 
 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);  //Set the RES pin
 HAL_Delay(500);

//Send initialization commands
for (i=0; ;i+=2) 
{
    j=(int)init_commands[i];
    k=(int)init_commands[i+1];
    if ((j==0xFF) && (k==0xFF)) break;

    oled_Command(j);
    oled_Data(k);
  }
}

Tenga en cuenta que soy bastante nuevo en el mundo integrado y que el código que escribí no es el óptimo. Acabo de portar los ejemplos de código (con ligeros cambios) dados para entender cómo inicializar esta pantalla. Tan pronto como obtenga una mejor comprensión, escribiré mi propio controlador.

Para resumir:

Lo que quiero lograr:

Mi objetivo en este momento es simplemente inicializar la pantalla e imprimir algo, por ejemplo, "hola mundo"

Lo que sé

Estoy bastante familiarizado con la Interfaz Periférica Serial (SPI) y DMA, así como con los temporizadores UART y STM.

Lo que pido:

Estoy bastante seguro de que he hecho algo fundamentalmente incorrecto, por lo que mis preguntas son:

  1. ¿Hay algún problema con mi código? Supongo que mis retrasos están completamente apagados, pero no puedo estar seguro.

  2. En el código provisto en la hoja de datos hay una instrucción que me molesta graphic_delay(500000) Esto es algún tipo de retraso pero ¿qué tipo de retraso? ¿Y en qué unidades? ¿Sra? μs?

  3. Si alguien tiene alguna experiencia en la interfaz de esta pantalla en particular y está dispuesto a proporcionarme un resumen básico sobre cómo inicializar la pantalla, le agradecería.

EDIT Olvidé publicar la hoja de datos para Mostrar controlador y controlador

EDITAR no2 Eliminé el HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET); como sugerí amablemente Flanker. También impliqué adecuadamente los retrasos.

El problema persiste. Ahora volveré a conectar el analizador lógico para garantizar que mis comandos de inicialización se envíen correctamente.

    
pregunta NikSotir

1 respuesta

1

Entonces, el problema parecía ser (aparte de mi error de reiniciar el dispositivo cada vez que se enviaba un comando) mi configuración de SPI. Después de mirar la hoja de datos durante bastante tiempo, me di cuenta de que tenía que cambiar la polaridad del reloj de hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; a hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;

Además, cambié hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; a hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;

Esos dos cambios parecen resolver el problema y actualmente puedo llenar mi pantalla, por ejemplo, con píxeles rojos.

Para futuras referencias, publicaré el código (el que está en funcionamiento) para que cualquier persona que quiera interactuar con esta pantalla (o una con el mismo controlador) pueda portar este código.

SPI init:

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;

Inicialización de pantalla: (simplifiqué esta sección de código a propósito)

 void OLED_Init(void) 
{
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);
  HAL_Delay(500);
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
  HAL_Delay(500);


  oled_Command(0x04);                       
  oled_Data(0x03);                                                //Set Normal Driving Current          
  HAL_Delay(2);                                                                        

  oled_Command(0x04);
  oled_Data(0x00);                                          //Enable Power Save Mode, Set normal driving current
  HAL_Delay(2);

 oled_Command(0x02);
 oled_Data(0x01);                                         // Set EXPORT1 Pin at Internal Clock

 oled_Command(0x03);                                      
 oled_Data(0x90);                                         // Set Frame Rate to 120Hz

 oled_Command(0x80);
 oled_Data(0x01);                                        // Set Reference Voltage Controlled by External Register

 oled_Command(0x08);                                     //Set Pre-charge Time of Red
 oled_Data(0x04);
 oled_Command(0x09);                                     //Set Pre-charge Time of Green
 oled_Data(0x05);
 oled_Command(0x0A);                                     //Set Pre-Charge Time of Blue
 oled_Data(0x05);
 oled_Command(0x0b);                                     //Set Pre-Charge Current of Red
 oled_Data(0x9d);
 oled_Command(0x0C);                                     //Set Pre-Charge Current of Green
 oled_Data(0x8C);       
 oled_Command(0x0D);                                     //Set Pre-Charge Current of Blue
 oled_Data(0x57);   
 oled_Command(0x10);                                     //Set Driving Current of Red
 oled_Data(0x56);
 oled_Command(0x11);                                     //Set Driving Current of Green
 oled_Data(0x4D);
 oled_Command(0x12);                                     //Set Driving Current of Blue
 oled_Data(0x46);

 oled_Command(0x13);
 oled_Data(0xa0);                                        //Set Color Sequence
 oled_Command(0x14);
 oled_Data(0x01);                                        //Set MCU Interface
 oled_Command(0x16);
 oled_Data(0x76);
 oled_Command(0x20);
 oled_Data(0x00);                                          // Shift Mapping RAM Counter
 oled_Command(0x21);
 oled_Data(0x00);                                          // Shift Mapping RAM Counter
 oled_Command(0x28);
 oled_Data(0x7F);                                          // 1/128 Duty (0x0F~0x7F)
 oled_Command(0x29);
 oled_Data(0x00);                                          // Set Mapping RAM Display Start Line (0x00~0x7F)
 oled_Command(0x06);
 oled_Data(0x01);                                          // Display On (0x00/0x01)
 oled_Command(0x05);                                       // Disable Power Save Mode
 oled_Data(0x00);                                          // Set All Internal Register Value as Normal Mode
 oled_Command(0x15);
 oled_Data(0x00);                                           // Set RGB Interface Polarity as Active Low
 HAL_Delay(10);
}

Una vez que se inicializa la pantalla, puede llenar la pantalla con un color determinado como este:

void fillScreen(void)
{   
   //Set Column Address 
    oled_Command(0x17);
    oled_Data(0x00);       //x_start
    oled_Command(0x18);
    oled_Data(0x9F);       //x_end

    //Set Row Address
    oled_Command(0x19);
    oled_Data(0x00);       //y_start
    oled_Command(0x1A);
    oled_Data(0x7F);       //y_end

    oled_Command(0x22);    //write to RAM command

   for (int i=0;i<20480;i++)         //for each 24-bit pixel...160*128=20480
 {
    oled_Data(blue); 
    oled_Data(green);
    oled_Data(red);
 }

¡Las funciones oled_Command y oled_Data siguen siendo las mismas!

P.S

Creo que alguien más sugirió que debería cambiar la polaridad del reloj (un usuario sin suficiente reputación para dejar un comentario) pero parece que su respuesta se eliminó por algún motivo.

    
respondido por el NikSotir

Lea otras preguntas en las etiquetas