Daß 2 Nibbles unterwegs sind, sagt man ihm im ersten Befehl:
Im meinen Code kannst du die Stellen zwischen

#ifdef VFD_INTERFACE_8BIT_PARALLEL
...
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

überlesen, weil du das Display ja in 4 Bit-Modus betreiben willst.

Der erste Befehl den ich sende (in vfd_reset()) ist ein
Code:
// CLR () setzt das entsprechende Port-Pin auf 0
// SET () setzt das entsprechende Port-Pin auf 1
CLR (POTR_RS);

//  FUNCTION_SET_DATA4>>4 ist gleich 0x2
vfd_send_byte_or_nibble (FUNCTION_SET_DATA4>>4);
Die wichtigsten Funktionen später sind (#ifdef hab ich schon aufgelöst)
Code:
void vfd_send0 (byte b)
{
   CLR_FLAG (FLAG_VFD_RS);
   vfd_send_byte_or_nibble (b>>4);
   vfd_send_byte_or_nibble (b);
}

void vfd_send1 (byte b)
{
   SET_FLAG (FLAG_VFD_RS);
   vfd_send_byte_or_nibble (b>>4);
   vfd_send_byte_or_nibble (b);
}
Aus diesen Funktionen ist später der ganze Kommande/Datenstrom aufgebaut. In FLAG_VFD_RS merke ich mir wie der PORT_RS im moment der Ausgabe zu stehen hat. Wie ich das genu umgesetzt habe ist egal, nur zum Verständnis.

Das ist nun die vfd_send_byte, wieder hab ich das Zeug rausgeworfen,
das nur 8-Bit-parallel-Modus verwendet wird.
Da bei dir die Ports nebeneinander liegen, kannst du das besser machen als ich in meinem Code. Wie, brauch ich dir ja nicht mehr zu erklären Bild  
Code:
void vfd_send_byte_or_nibble (byte b)
{
   CLR (PORT_E);
   
    // Alle Datenports als Ausgang
   MAKE_OUT (PORT_DB0);
   MAKE_OUT (PORT_DB1);
   MAKE_OUT (PORT_DB2);
   MAKE_OUT (PORT_DB3);

   CLR (PORT_RW);

   // Setzt PORT_RS wie im Flag gemerkt   
   CLR (PORT_RS);
   if (IS_FLAG (FLAG_VFD_RS))
      SET (PORT_RS);

   // Alle Datenports auf 0      
   CLR (PORT_DB0);
   CLR (PORT_DB1);
   CLR (PORT_DB2);
   CLR (PORT_DB3);

   // Das Nibble ausgeben.
   // Bei mir ist das etwas komplizierter, weil die Ports nicht nebenein
   // ander liegen müssen. Wo PORT_DBx liegt wird zentral verwaltet,
   // der genaue Wert ist hier egal.
   if (b & (1<<0))    SET (PORT_DB0);
   if (b & (1<<1))    SET (PORT_DB1);
   if (b & (1<<2))    SET (PORT_DB2);
   if (b & (1<<3))    SET (PORT_DB3);

   // Daten raushauen
   SET (PORT_E);
   LOOP (100);
   CLR (PORT_E);

   // Wieder alle Daten-Ports als Eingang
   // Das brauch ich nur um Kollisionen auf dem Bus zu vermeiden
   MAKE_IN (PORT_DB0);
   MAKE_IN (PORT_DB1);
   MAKE_IN (PORT_DB2);
   MAKE_IN (PORT_DB3);
}
Das wichtigste ist, daß du beim Initialisieren für den 4bit-Modus nicht 2 Nibbles schickst, sonder nur eines!

Mit den Erläuterungen kannst du auch den Rest meines Codes gut verstehen.