0
\$\begingroup\$

The last two days I've been trying to interface a NewHaven Dislpay with my stm32f4 discovery board with no result.

The datasheet gives poor written examples as to how to initialize this display and I'm having a really hard time figuring how this display works. I'm currently using SPI and while I made the appropriate connections (according to the datasheet) the display refuses to work.

The stm32f4 is clocked at 168MHz

The SPI initialization code is the following:

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;

The code I wrote is the following:

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);
  }
}

Note that I'm fairly new to the embedded world and the code I wrote is not the optimal. I just ported the code examples (with slight changes) given in order to understand how to initialize this display. As soon as gain a better understanding I will write my own driver.

To sum up:

What I want to achieve:

My goal at the moment is simply to initialize the display and print something e.g "hello world"

What I know

I'm fairly familiar with the Serial Peripheral Interface (SPI) and DMA as well as UART and STM timers.

What I ask:

I'm pretty sure that I've done something fundamentally wrong so my questions are:

  1. Is there something wrong with my code? My guess is that my delays are completely off but I can't be sure.

  2. In the code provided in the datasheet there is an instruction that bugs me graphic_delay(500000) This is some kind of delay but what kind of delay? And in what units? ms? μs?

  3. If someone has any experience at interfacing this particular display and is willing to provide me with a basic outline about how to initialize the display I would be grateful.

EDIT I forgot to post the datasheet for the Display Driver and Controller

EDIT no2 I removed the HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET); as kindly suggested by Flanker. I also implemted properly the delays.

The problem persists. I will now connect once more time the logic analyzer to ensure that my initialization commands are being sent correctly.

\$\endgroup\$
  • \$\begingroup\$ Did you check the SPI lines and GPIOs with a logic analyzer or oscilloscope, if they are working correctly? \$\endgroup\$ – Bence Kaulics Nov 22 '16 at 15:12
  • \$\begingroup\$ @BenceKaulics Yes I did.I checked them many times with my logic analyzer and they are working just fine. \$\endgroup\$ – NikSotir Nov 22 '16 at 15:16
  • \$\begingroup\$ And you are using 6800-interface (selected with GPIOE, pin3)? Please add a schematic, there are a lot of pins all of their state matters. I assume that you tied to GND the R/W, E, and Data pins. 470 uF capacitor is added as well? \$\endgroup\$ – Bence Kaulics Nov 22 '16 at 15:17
  • \$\begingroup\$ Adding to @BenceKaulics comment, some new haven displays use only serial, but the other can do serial and parallel data transfer. You need to know exactly what way of communication you are using. Also, I would suggest to start with filling the screen with a specific color. More advanced would be the "hello world" output. \$\endgroup\$ – Nazar Nov 22 '16 at 15:22
  • \$\begingroup\$ @BenceKaulics According to the datasheet, when using 4-wire SPI the CPU pin (Pin 20) is grounded (page 5 in datasheet) so I'm guessing that I'm using 8080 interface. Also pin 3 in my code is the chip select pin. \$\endgroup\$ – NikSotir Nov 22 '16 at 15:24
1
\$\begingroup\$

So the problem seemed to be (apart from my mistake of reseting the device every time a command was sent) my SPI settings. After looking the datasheet for quite some time I realized that I had to change Clock Polarity fromhspi1.Init.CLKPolarity = SPI_POLARITY_LOW; to hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;

Furthermore I changed hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; to hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;

Those two changes seem to solve the problem and I am currently able to fill my screen with e.g red pixels.

For future reference I will post the code (the working one) so anyone who wants to interface this display (or one with the same driver) can port this code.

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;

Display Init: (I simplified this section of code on purpose)

 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);
}

After the display is initialized you can fill the screen with a certain colour like this:

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);
 }

The oled_Command and oled_Data functions remain the same!

P.S

I think someone else suggested that I should change the clock polarity (a user without enough rep to leave a comment) but it seems that his answer was deleted for some reason.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.