#define F_CPU 16000000UL // Define the CPU frequency as 16 MHz #include #include // Define LCD pins #define LCD_E PIN0_bm // Enable (PC0) #define LCD_RS PIN1_bm // Register Select (PC1) #define LCD_D4 PIN3_bm // Data Bit 4 (PC3) #define LCD_D5 PIN2_bm // Data Bit 5 (PC2) #define LCD_D6 PIN5_bm // Data Bit 6 (PC5) #define LCD_D7 PIN4_bm // Data Bit 7 (PC4) // Helper macros #define LCD_E_HIGH() (PORTC.OUTSET = LCD_E) #define LCD_E_LOW() (PORTC.OUTCLR = LCD_E) #define LCD_RS_HIGH() (PORTC.OUTSET = LCD_RS) #define LCD_RS_LOW() (PORTC.OUTCLR = LCD_RS) // Function Prototypes void lcd_send_nibble(uint8_t nibble); void lcd_send_byte(uint8_t data, uint8_t is_command); void lcd_init(); void lcd_print(const char *str); // Send a nibble (4 bits) to the LCD void lcd_send_nibble(uint8_t nibble) { PORTC.OUTCLR = LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7; // Clear D4-D7 if (nibble & 0x01) PORTC.OUTSET = LCD_D4; if (nibble & 0x02) PORTC.OUTSET = LCD_D5; if (nibble & 0x04) PORTC.OUTSET = LCD_D6; if (nibble & 0x08) PORTC.OUTSET = LCD_D7; LCD_E_HIGH(); _delay_us(1); // Pulse duration LCD_E_LOW(); _delay_us(100); // Command latch time } // Send a byte (8 bits) to the LCD void lcd_send_byte(uint8_t data, uint8_t is_command) { if (is_command) { LCD_RS_LOW(); // Command mode } else { LCD_RS_HIGH(); // Data mode } lcd_send_nibble(data >> 4); // Send high nibble lcd_send_nibble(data & 0x0F); // Send low nibble _delay_us(50); // Command execution time } // Initialize the LCD void lcd_init() { // Set LCD pins as outputs PORTC.DIRSET = LCD_E | LCD_RS | LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7; _delay_ms(40); // Wait for power-up // Force 4-bit mode initialization lcd_send_nibble(0x03); _delay_ms(5); lcd_send_nibble(0x03); _delay_us(200); lcd_send_nibble(0x03); _delay_us(200); lcd_send_nibble(0x02); // Set to 4-bit mode // Initialization sequence as per datasheet lcd_send_byte(0x39, 1); // Function Set: 4-bit, 2-line, instruction table 1 lcd_send_byte(0x14, 1); // Bias Set: 1/5 lcd_send_byte(0x55, 1); // Power Control: booster on, contrast C5, C4 lcd_send_byte(0x6D, 1); // Follower Control: voltage follower and gain lcd_send_byte(0x74, 1); // Contrast Set: C3, C2, C1 lcd_send_byte(0x38, 1); // Function Set: switch back to normal mode lcd_send_byte(0x0C, 1); // Display ON: Display ON, cursor OFF, blink OFF lcd_send_byte(0x01, 1); // Clear Display _delay_ms(2); // Allow clear display to complete lcd_send_byte(0x06, 1); // Entry Mode Set: Increment cursor, no display shift } // Print a string to the LCD void lcd_print(const char *str) { while (*str) { lcd_send_byte(*str++, 0); // Send characters in data mode } } int main() { lcd_init(); // Initialize the LCD while (1) { lcd_send_byte(0x01, 1); // Clear Display _delay_ms(2); lcd_print("EA DOGM162W-A"); // Display text _delay_ms(2000); lcd_send_byte(0x01, 1); // Clear Display _delay_ms(2); lcd_print("Hello, World!"); // Display text _delay_ms(2000); } }