#include "lcd.h" #include "i2c.h" /* Ihr I²C-Master-Treiber */ #include /* für __delay_cycles() */ #include /* --- Interne Helfer: sendet eine 4-Bit-Halbnibble plus Control-Bits --- */ static void lcd_write_nibble(uint8_t nibble, uint8_t control) { char buf[1]; /* High-Nibble in die oberen 4 Bits */ buf[0] = (nibble << 4) | control | LCD_BACKLIGHT; /* EN=1 */ I2C_write(LCD_I2C_ADDR, buf, 1); buf[0] |= LCD_ENABLE; I2C_write(LCD_I2C_ADDR, buf, 1); __delay_cycles(500); /* ca. 50 µs @ 1 MHz */ /* EN=0 */ buf[0] &= ~LCD_ENABLE; I2C_write(LCD_I2C_ADDR, buf, 1); __delay_cycles(500); } /* Sendet ein volles Byte (2×4-Bit) als Befehl (RS=0) */ static void lcd_send_cmd(uint8_t cmd) { lcd_write_nibble(cmd >> 4, 0x00); lcd_write_nibble(cmd & 0x0F, 0x00); } /* Sendet ein volles Byte als Daten (RS=1) */ static void lcd_send_data(uint8_t data) { lcd_write_nibble(data >> 4, LCD_RS); lcd_write_nibble(data & 0x0F, LCD_RS); } void lcd_init(void) { /* Wartezeit nach Power-Up */ __delay_cycles(50000); /* ca. 50 ms */ /* Initial­sequenz 8-Bit-Befehle (3×) */ lcd_write_nibble(0x03, 0x00); __delay_cycles(20000); lcd_write_nibble(0x03, 0x00); __delay_cycles(5000); lcd_write_nibble(0x03, 0x00); __delay_cycles(2000); /* In 4-Bit-Modus schalten */ lcd_write_nibble(0x02, 0x00); __delay_cycles(2000); /* Funktion: 4-Bit, 2 Zeilen, 5×8 Punkte */ lcd_send_cmd(0x28); /* Display off */ lcd_send_cmd(0x08); /* Clear */ lcd_send_cmd(0x01); __delay_cycles(2000); /* Entry mode: Cursor++ */ lcd_send_cmd(0x06); /* Display on, Cursor off, Blink off */ lcd_send_cmd(0x0C); } void lcd_clear(void) { lcd_send_cmd(0x01); __delay_cycles(2000); } void lcd_set_cursor(uint8_t row, uint8_t col) { uint8_t addr = (row == 0 ? 0x00 : 0x40) + (col & 0x0F); lcd_send_cmd(0x80 | addr); } void lcd_print(const char *str) { while (*str) { lcd_send_data((uint8_t)*str++); } }