1
\$\begingroup\$

I have this microcontroler with this LCD(DEM16216) mounted on it which I cannot initialize.

Only 4 of the pins are connected, thus it runs in a 4 bit mode (I think?). I found the datasheet for it (DEM16216) , which gives an step by step guide on how to do it, but for some reason it does not work for me...

Could someone tell me why this isn't working for me?

This is the datasheet for my LCD.

The one my teacher recommended was this one.

Complete code can be downloaded from [code]http://speedy.sh/vZJby/LCD-init-code.zip[/code]

init is performed outside of a superloop, while command is performed inside a superloop.

Could anyone explain why this isn't working?

screen.c

#include"screen.h"

void nibble_value(INT8U binary_value)
{
    if((binary_value & 0b00001000) == 8)      //DB7
        GPIO_PORTB_DATA_R |= (0b00100000);
    else
        GPIO_PORTB_DATA_R &= ~(0b00100000);

        if((binary_value & 0b00000100) == 4)    //DB6
            GPIO_PORTB_DATA_R |= (0b00010000);
        else
            GPIO_PORTB_DATA_R &= ~(0b00010000);

            if((binary_value & 0b00000010) == 2)    //DB5
                  GPIO_PORTB_DATA_R |= (0b00001000);
            else
                    GPIO_PORTB_DATA_R &= ~(0b00001000);

                if((binary_value & 0b00000001) == 1)    // DB4
                    GPIO_PORTB_DATA_R |= (0b00000100);
                else
                    GPIO_PORTB_DATA_R &= ~(0b00000100);

}
void enable_pin (int a)
{
    if (a)
    {
        GPIO_PORTB_DATA_R |= (0b01000000); //Disables "enable "pin

        redLed(ON); //Debug
    }

    else{
        GPIO_PORTB_DATA_R &= ~(0b01000000); // Enables  "enable" pin

                redLed(OFF); //debug
    }
}


void screen_init( void )
{
     //POwer on
     //MILLISEC(100);
    enable_pin(OFF);
    yellowLed(ON);
    greenLed(OFF);
    redLed(OFF);
    for(i=0; i<10000000; i++);
    yellowLed(OFF);
    redLed(ON);
     // Special case Function set
//----------------------------------------------------------------//

    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00000011);  // DB5 = 1, DB4 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin off
    // MILLISEC(15);                // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00000011);          // DB5 = 1, DB4 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // Enable pin off
    // MILLISEC(15);                // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00000011);          // DB5 = 1, DB4 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin off
    // MILLISEC(5);             // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//-----------------------------------------------------------------//
     //initial Function set
//-----------------------------------------------------------------//
    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00000010);          // 0x02 = 0b00000010 => DB5 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin = off
    // MILLISEC(5);             // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//----------------------------------------------------------------//
     //Function set
//----------------------------------------------------------------//
    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00000010);          // 0x02 = 0b00000010 => DB5 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable  pin = off
    // MILLISEC(5);             // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);             // 1 ms delay
     nibble_value(0b00001000);          // 0x8 = 0b00001000 n = 1 and f = 0 => DB7 = 1
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin = off
    // MILLISEC(5);             // 5 ms delay
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//----------------------------------------------------------------//
     //Display On/Off
//----------------------------------------------------------------//
    // MILLISEC(1);             // delay = 1 ms
     nibble_value(0x00);        // ZERO
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin = off
    // MILLISEC(5);                 // delay 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);                 // delay = 1 ms
     nibble_value(0b00001000);      // DB7  = 1 => display off
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable pin = off
    // MILLISEC(5);                 // delay = 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//---------------------------------------------------------------//
     //Clear Display
//---------------------------------------------------------------//
    // MILLISEC(1);                 // delay = 1 ms
     nibble_value(0b00000000);  // Zero
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // Enable pin = off
    // MILLISEC(5);                 // Delay  = 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);                 // delay = 1 ms
     nibble_value(0b00000001);  // No configurable bits, CLEAR Display
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable = off
    // MILLISEC(5);                 // delay = 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//---------------------------------------------------------------//
     //Entry Mode set
//---------------------------------------------------------------//
    // MILLISEC(1);                 // delay = 1 ms
     nibble_value(0b00000000);  // Zero
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // Enable pin = off
    // MILLISEC(5);                 // Delay  = 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

    // MILLISEC(1);                 // delay = 1 ms
     nibble_value(0b00000110);  // DB6 = 1, DB5 = 1 (increment by 1) , DB4 = 0 (No shift)
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // enable = off
    // MILLISEC(5);                 // delay = 5 ms
        for(i=0; i<10000000; i++);
        GPIO_PORTF_DATA_R ^= 0x01;

//---------------------------------------------------------------//
}

void command (void)
{
    //Command
//---------------------------------------------------------------//
     nibble_value(0b00000000);  // Zero
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // Enable pin off
    for(i=0; i<100; i++);

//--------------------------------------------------------------//
        //Command
//---------------------------------------------------------------//
     nibble_value(0b00001111);  // D  = 1, C = 1 , B = 1  => display on, cursor  on and blinking on..
     enable_pin(ON);            // enable pin on
     enable_pin(OFF);           // Enable pin off
    for(i=0; i<100; i++);

//--------------------------------------------------------------//
}

Main.c

#include "lm3s6965.h"
#include "systick.h"
#include "gpio.h"
#include "emp_type.h"
#include "swtimers.h"
#include "LED.h"
#include "screen.h"
int main(void)
{
     disable_global_int();
     init_clk_system();
     init_gpio();
     systick_init();
     enable_global_int();
     screen_init();
     INT16S alive_timer = MILLISEC(500);


    while(1)
    {
        redLed(ON);
        yellowLed(ON);
        greenLed(ON);
        while( !klik );
        klik--;
            if( ! --timer )
            {
                timer = MILLISEC( 500 );
                GPIO_PORTF_DATA_R ^= 0x01;
            }


    }
}
\$\endgroup\$
15
  • \$\begingroup\$ It would help the readability a lot if you used #defines in your c code rather than a bunch of binary numbers. \$\endgroup\$
    – Napthali
    Commented Mar 22, 2014 at 19:04
  • \$\begingroup\$ Which 4 pins are connected? \$\endgroup\$
    – Napthali
    Commented Mar 22, 2014 at 19:11
  • \$\begingroup\$ RW(PA6),RS(PA7),D4(PB2),D5(PB3),D6(PB4),D7(PB5),E(PB6) \$\endgroup\$ Commented Mar 22, 2014 at 19:18
  • \$\begingroup\$ Are you sending the Function Set command to the instruction register? That is what controls the 4bit vs 8bit bus width. \$\endgroup\$
    – Napthali
    Commented Mar 22, 2014 at 19:23
  • 3
    \$\begingroup\$ Just as a side note regarding good pratice and code readability: Prevent commenting on a per line basis WHAT the line does like "enable_pin(ON); // enable pin = on". THat should be (and is) self explanatory from the variable/function names in most cases. Instead, comment on things that are less obvious and one may ask WHY you did what you did. Like "Process init sequence" followed by the sequence of init commands. \$\endgroup\$
    – Rev
    Commented Mar 22, 2014 at 21:37

1 Answer 1

1
\$\begingroup\$
  1. are you setting the RS pin to the correct value?

  2. You seem to think that you can use insert_value( x ) to write 8 bits to the LCD, but this must be done in two steps, like (assuming the 4 bits written by wrire4 are connected to the D7..D4 of your LCD):

    write4( b >> 4 );
    write4( b );
    
  3. You must follow the 4-bit initalization as is shown in the initialization sequence as show in the datasheet EXACTLY, and note that each row in that initialization can imply two write4 commands.

Your insert_value command uses 2 bits of the value you pass to it for the RS and RW bits. Personally I prefer to keep RW on W all the time, and I pass RS as a separate argument. In your version it is very difficult to see what data you are passing to the LCD. But it is clear that you are writing 3 nibbles, where the datasheet specifies 4. This is my sequence:

      write4( 0x03 );
      timing::wait(  15 * timing::ms );
      write4( 0x03 );
      timing::wait(  100 * timing::us );
      write4( 0x03 );
      write4( 0x02 );     // 4 bit mode

A general note on debugging: when you have more than one problem, you can no longer reason "I changed this to to that and it did not work, hence that was not the good idea". It will only work when you have solved ALL problems.

\$\endgroup\$
37
  • \$\begingroup\$ When you send your nibble how do distiguish between high or low, or does it not matter?? To be honest, I don't see where I am going wrong with my codepiece.. \$\endgroup\$ Commented Mar 22, 2014 at 22:39
  • \$\begingroup\$ @user38544 There are two things to think about there. The 4 bits are connected to 4 pins on the mcu and 4 pins on the lcd. Make sure that what you are calling d7-d4 flows to the LCD appropriately in hardware. The second thing is that you are sending one nibble and then the second. The order is determined by the datasheet. \$\endgroup\$
    – Napthali
    Commented Mar 23, 2014 at 0:34
  • \$\begingroup\$ @user35844 in your code you send 3 nibbles in the initialization (before on/off), the datasheet specifies 4. That might not be the only problem, but it sure is A problem. \$\endgroup\$ Commented Mar 23, 2014 at 8:57
  • \$\begingroup\$ But which one should i use the one i found, or the one my teacher gave..?? \$\endgroup\$ Commented Mar 23, 2014 at 9:39
  • \$\begingroup\$ Up to you, if you choose wrong it is your problem :) What I show is what the datasheet specifies, and that works for me (it is also theoretically sound). You could browse the web for a few other 4-bit HD44780 libraries and check what they do. \$\endgroup\$ Commented Mar 23, 2014 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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