.. Da ich das erst richtig verarbeiten muss, erbitte ich mir etwas Zeit, bis ich wieder Rückmeldung gebe ..
Ich grins mich eins - mir gehts da wie Dir und dem LCD: wir brauchen alle mal ein paar waits wenns kompliziert wird *gg*.
Spass beiseite. Ich habe zwar keine Assemblerlösung. Aber in Assembler werden ja ähnliche Routinen nötig wie in C - und da kann ich ein bisschen was zu den Waits beitragen. Im folgenden Code sind die "waits" - heissen dort
......_delay_us (parameter)
rot hervorgehoben. Die Delays habe ich vor Jahren angepasst für 20 MHz Controllertakt (ist ja aber in µs angegeben) - und diese Routinen laufen bei mir so auf irgendwelchen, möglichst günstigen 2x16-LCDisplays. Vielleicht hilft Dir das ein bisschen weiter?
Code:
// Erweiterte Fassung mit Routine für selbst definierte Zeichen
// Stand = Erweiterung von lcd-routines.h und lcd-routines.c
// vom 11. Apr. 2012
// 28 Nov 2012 16:24 Leichte Korrekturen
// 27 Juni 2015, 19:27 Datenausgabe PC0..PC3, Steuerport PD
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
#include <avr/io.h>
//#include "lcd-routines.h"
#include "lcd_162_xt_ALCo.h"
#include <util/delay.h>
#include <avr/eeprom.h>
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// sendet ein Datenbyte an das LCD
void lcd_data(unsigned char temp1)
{
LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
lcd_send(temp1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// sendet einen Befehl an das LCD
void lcd_command(unsigned char temp1)
{
LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
lcd_send(temp1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Eigentliche LCD-Zugriffs-Funktion; 4-Bit-Modus
void lcd_send(unsigned char data) {
// oberes Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | ((data >> 4) & 0x0F);
_delay_us(15);
lcd_enable();
// unteres Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | (data & 0x0F);
_delay_us (15);
lcd_enable();
_delay_us (60);
LCD_PORT &= 0xF0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
_delay_us (20); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Initialisierung:
// Muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init(void)
{
LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN1); // Port auf Ausgang schalten
// muss 3mal hintereinander gesendet werden zur Initialisierung
_delay_us (40);
LCD_PORT = (LCD_PORT & 0xF0 & ~(1<<LCD_RS)) | 0x03;
lcd_enable();
_delay_us (15);
lcd_enable();
_delay_us (11);
lcd_enable();
_delay_us (11);
LCD_PORT = (LCD_PORT & 0xF0 & ~(1<<LCD_RS)) | 0x02;
_delay_us (11);
lcd_enable();
_delay_us (11);
// 4Bit / 2 Zeilen / 5x7
lcd_command(CMD_SetIFOptions | 0x08);
// Display ein / Cursor aus / kein Blinken
lcd_command(CMD_SetDisplayAndCursor | 0x04);
// inkrement / kein Scrollen
lcd_command(CMD_SetEntryMode | 0x02);
lcd_clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Sendet den Befehl zur Löschung des Displays
void lcd_clear(void)
{
lcd_command(CLEAR_DISPLAY);
_delay_us (15);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Schreibt einen String auf das LCD
void lcd_string(char *data)
{
while(*data) {
lcd_data(*data);
data++;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//String aus EEPROM laden und an LCD senden
void lcd_eep_string(const unsigned char *data)
{ //
unsigned char c;
while(1) //
{ //
c = eeprom_read_byte(data); //
if(c==0) return; //
lcd_data(c); //
data++; //
}
} // Ende void lcd_eep_string(const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im RAM
void lcd_generatechar(uint8_t code, const uint8_t *data)
{ //
lcd_command(LCD_SET_CGADR|(code<<3)); // Startposition des Zeichens einstellen
for (uint8_t i=0; i<8; i++) // Bitmuster übertragen
{ //
lcd_data(data[i]); //
} //
} // Ende void lcd_generatechar(uint8_t code,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lesezeichen