NHD-0220DZW-AB5 ignores RS line?!

Comments

2 comments

  • Ted M.
    NHD Staff

    Hi Stephen,

    The OLED displays require more delay time than our LCD character displays.
    Some instructions have a max execution time of up to 600us, while the write cycle has a minimum of 500ns.

    Reference this example code written for an Arduino MEGA.

    // Define
    #define E_Pin   32
    #define R_W     31
    #define R_S     30

    // Constant Strings
    char const text1[] = ("  Newhaven Display  ");
    char const text2[] = ("Character OLED BLUE ");
    char const text3[] = ("  NHD-0220DZW-AB5   ");
    char const text4[] = ("Blue Character OLED ");
    char const text5[] = ("   Display Shift    ");
    char const text6[] = ("Custom Character RAM");
    //Write Functions + INITIALIZATION
    void command(char i){ //Write Command
      PORTA = i;
      digitalWrite(R_S, LOW);
      digitalWrite(R_W, LOW);
      digitalWrite(E_Pin, HIGH);
      delay(1);
      digitalWrite(E_Pin, LOW);
    }
    void data(char i){ //Write Data
      PORTA = i;
      digitalWrite(R_S, HIGH);
      digitalWrite(R_W, LOW);
      digitalWrite(E_Pin, HIGH);
      delay(1);
      digitalWrite(E_Pin, LOW);
    }
    void init1(){ // initialize the display
      digitalWrite(E_Pin, LOW);
      delay(5);
      command(0x30); // Wake up 1
      delay(100);
      command(0x30); // Wake up 2
      delay (10);
      command(0x30); // Wake up 3
      delay (10);
      command(0x39); // Function 8bit, 2 line, 5x8 text, Western European Font Table
      delay(5);
      command(0x08); // Display Off
      delay(5);
      command(0x01); // Clear Display
      delay(5);
      command(0x06); // Entry Mode
      delay(5);
      command(0x02); // Home
      delay(5);
      command(0x0C); // Display & Cursor ON
      delay(5);
     
     
    }
    void clear_screen(){ // clear display
     command(0x01);
     }
    void ret_home(){ // Return to home position
     command(0x02);
    }
    // SPECIAL FUNCTIONS
    void sftr(){  // Shift Display
      for(int i = 0; i<20 ; i++){
      command(0x1C);
      delay(75);
      }
    }
    void char1(){ // Custom Character Creation
        command(0x40);
      data(0x1F);
      data(0x15);
      data(0x15);
      data(0x04);
      data(0x04);
      data(0x15);
      data(0x15); 
      data(0x1F);

      data(0x01);
      data(0x02);
      data(0x04);
      data(0x09);
      data(0x12);
      data(0x04);
      data(0x08);
      data(0x10);

      data(0x0E);
      data(0x0A);
      data(0x1F);
      data(0x0A);
      data(0x0A);
      data(0x1F);
      data(0x0A);
      data(0x0E);

      data(0x0A);
      data(0x04);
      data(0x0a);
      data(0x11);
      data(0x0A);
      data(0x04);
      data(0x0A);
      data(0x11);

      data(0x04);
      data(0x0a);
      data(0x11);
      data(0x0a);
      data(0x04);
      data(0x0a);
      data(0x11);
      data(0x0A);

      data(0x15);
      data(0x0A);
      data(0x0A);
      data(0x15);
      data(0x15);
      data(0x0A);
      data(0x0A);
      data(0x15);

      data(0x1F);
      data(0x1B);
      data(0x15);
      data(0x1B);
      data(0x1B);
      data(0x15);
      data(0x1B);
      data(0x1F);
    }



    // DISPLAY FUNCTIONS
    void disp1(){
      clear_screen();
      delay(2);
      ret_home();
      delay(2);
      for( int i = 0; i< 20; i++){
        data(text1[i]);
      }
      command(0xc0); // Second Line
      for (int i = 0; i<20; i++){
        data(text2[i]);
      }
      ret_home();
    }
    void disp2(){
     clear_screen();
      delay(2);
      ret_home();
      delay(2);
      for( int i = 0; i< 20; i++){
        data(text3[i]);
      }
      command(0xc0); // Second Line
      for (int i = 0; i<20; i++){
        data(text4[i]);
      }
      ret_home();
    }
    void disp3(){
      clear_screen();
      delay(2);
      ret_home();
      delay(2);
      for( int i = 0; i< 20; i++){
        data(text1[i]);
      }
      command(0xc0); // Second Line
      for (int i = 0; i<20; i++){
        data(text5[i]);
      }
      ret_home();
    }
    void disp4(){
      for( int i = 0; i< 20; i++){
        data(text6[i]);
      }
      command(0xc0); // Second Line
      for(int i = 0; i < 7 ; i++){
        data(0x20);
      }
      delay(1);
      data(0x00);
      data(0x01);
      data(0x02);
      data(0x03);
      data(0x04);
      data(0x05);
      data(0x06);
      ret_home();
    }
    void setup() {
       
      DDRA = 0xFF; // PORT A as output
      DDRC = 0xFF; // Port C as output
      init1();
    }

    void loop() {

      disp1();      // Show Text 1   
      delay(5000);
      disp2();      // Show Text 2
      delay(5000);
      disp3();      // Show Text 3
      delay(1000);
      sftr();       // Shift display off screen, clear display
      delay(200);
      char1();    // call custom character creation
      delay(10);
      clear_screen();
      delay(5);
      ret_home(););
      delay(5);
      disp4(); // show custom characters
      delay(5000);
      clear_screen();

    }

    Best Regards,

    0
  • stevopedia

    I'm aware of the timing requirements. My process for writing to the display is:

    • Set RS and R/W# as needed
    • Load the byte to be written onto the GPIO port
    • Pull the E line low
    • Set the GPIO port to input
    • Drive RS low and and R/W# high: command the display to output its status byte
    • Delay loop: wait for about 10 μs
    • GPIO read loop: wait for bit 7 (BUSY flag) to go low
    • Set E and RS high; pull R/W# low (default state)
    • Set GPIO port back to output


    Here's my actual code. It's Motorola/Freescale/NXP HCS12 assembly. PORTD is connected to the data lines. PT0 is E, PT1 is R/W#, and PT2 is RS.

    WriteDisplayCmd:           
    ; Assumes the command to be written is in A.       
                MOVB    #$01, PTT       ; Set display controller to be written a command
                STAA    PORTD           ; Load the command onto the data lines
                BCLR    PTT, #$01       ; Pull E line low -- latch in the command
                NOP                     ; for timing safety
                CLR     DDRD            ; Set PORTD to input
                BSET    PTT, #$03       ; Set display controller to be read. PTT = $03
                JSR     DelayLoop
                JSR     BusyFlagWait    ; Wait for the busy flag to be cleared
                MOVB    #$05, PTT       ; Set display controller to be written data
                MOVB    #$FF, DDRD      ; Set PORTD back to output
                RTS

    WriteDisplayData:           
    ; Assumes the character to be displayed is in A.       
                MOVB    #$05, PTT       ; Set display controller to receive display data
                STAA    PORTD           ; Load the command onto the data lines
                BCLR    PTT, #$01       ; Pull E line low -- latch in the command
                JSR     DelayLoop       ; for timing safety
                CLR     DDRD            ; Set PORTD to input
                MOVB    #$02, PTT       ; Set display controller to read status byte
                JSR     DelayLoop       ; Allow time for the controller to set its outputs
                BSET    PTT, #$01       ; E going high -> controller outputs data
                JSR     DelayLoop
                JSR     BusyFlagWait    ; Wait for the busy flag to be cleared
                MOVB    #$05, PTT       ; Set display controller to be written data
                MOVB    #$FF, DDRD      ; Set PORTD back to output
                RTS

    BusyFlagWait:
                BRSET   PORTD, $80, BusyFlagWait
                RTS

    DelayLoop:
                PSHB
                LDAB    #20
            DelayLoopLoop:
                DECB
                BNE     DelayLoopLoop
                PULB
                RTS

    I've measured my cycle time between most commands (i.e. the time between falling edges on the E line) as just over 18 μs. The display clear command 0x01 takes a bit over 630 μs to complete, measured from the falling edge on the E line to when the BUSY flag clears. Scope captures are available on request.

    Every command proper that I've sent to the display works perfectly. But I've never, ever gotten a display character to work.

    0

Please sign in to leave a comment.