No jak byś znał zasadę działania zwykłego wyświetlacza hd44780 to byłoby Ci łatwiej zrozumieć że z tym Twoim to wszystko jest niepotrzebne ahahahahaha.
Normalny wyświetlacz ma piny RS,EN i D0, D1, D2 ..do D7.
Jest też pin RW, ale użytkowo jest opcjonalny więc go pominę.
Pin RS słuzy do wyboru czy przesyłane dane to komenda czy znaki.
Pin EN służy do zatwierdzania przesłanych danych.
Natomiast osiem pinów to jakby port na którym mozesz wpisać wartość 0-255.
Osiem pinów to jednak dużo dla mikrokontrolera więc wymyślono ze można dane przesyłać tylko czterema pinami danych D4-D7. Czyli wyświetlacz moze pracować w trybie ośmio lub czterobitowym. Trzeba go jednak o tym poinformować przy inicjalizacji. Potem każdy bajt danych trzeba dzielić na pół i wysyłać dwa razy na jeden bajt.
Ciebie jednak te wszystkie zabawy z przestawianiem na tryb czterobitowy, dzielenie bajtów i machanie pinem EN nie powinny interesować ponieważ przesyłasz dane interfejsem szeregowym a nie równoległym.
Mógłbym przerobić ten Twój kod ale on nie jest dobrym kandydatem a nie lubie robić czegoś dwa razy bo za pierwszym razem bez sensu.
Kandydatem jest złym bo nie ma tu funkcji ustawiania kursora na pozycji ani czyszczenia wyświetlacza.
Tutaj trzeba przerobić lcd_cmd, lcd_dwr (pewnie od data write) i lcd_init. Tylko od razu skorzystałbym z funkcji poprzednich i2c_master bo tam w I2c_start już masz wybieranie adresu i sprawdzanie ack.
Poszukaj jakiegoś lepszego kandydata

ahahahaha
[EDIT 1] Popatrz jakie to powinno być proste z ta biblioteką I2c_master
Zaloguj się, aby zobaczyć kod
Teraz Init to wysłanie czterech komend w sekwencji czasowej z diagramu z szóstego postu.
To taki teoretyczny kod który pisałem tu w edytorze na forum. Do niego warto by dodać cos mądrzejszego wykorzystującego bit kontynuacji. Czyli po ustawieniu kursora wysyłasz cały ciąg i dopiero przy ostatnim znaku kasujesz kontynuację.