#define F_CPU 16000000UL // Define the CPU frequency as 16 MHz #include #include // Define pin connections #define RS 1 // PC1 #define E 0 // PC0 #define D4 3 // PC3 #define D5 2 // PC2 #define D6 5 // PC5 #define D7 4 // PC4 // Function Prototypes void LCD_Init(void); void LCD_Command(unsigned char cmd); void LCD_Data(unsigned char data); void LCD_SetContrast(uint8_t contrast); void LCD_EnablePulse(void); void SendNibble(unsigned char nibble); int main(void) { // Set RS, E, D4-D7 as outputs PORTC.DIR |= (1 << RS) | (1 << E) | (1 << D4) | (1 << D5) | (1 << D6) | (1 << D7); // Initialize the LCD LCD_Init(); // Set contrast to a middle value (e.g., 32 out of 63) LCD_SetContrast(32); // Display a test message LCD_Command(0x80); // Set cursor to the first position LCD_Data('H'); LCD_Data('E'); LCD_Data('L'); LCD_Data('L'); LCD_Data('O'); while (1) { // Infinite loop (do nothing) } } void LCD_Init(void) { _delay_ms(20); // Wait for LCD to power up // DOGM162 initialization sequence LCD_Command(0x39); // Function Set: 8-bit, 2-line, instruction set 01 LCD_Command(0x1C); // Bias 1/4, 2-line display LCD_Command(0x52); // Booster off, contrast C5 & C4 LCD_Command(0x69); // Follower Control LCD_Command(0x70); // Contrast C3, C2, C1, & C0 LCD_Command(0x0C); // Display ON, Cursor OFF LCD_Command(0x38); // Function Set: 8-bit, 2-line, instruction set 00 LCD_Command(0x01); // Clear Display _delay_ms(2); // Clear display requires longer delay LCD_Command(0x06); // Cursor AutoIncrement _delay_ms(2); } void LCD_SetContrast(uint8_t contrast) { uint8_t HC, LC; // Extract high and low contrast bits HC = (contrast & 0x30) >> 4; // Contrast C5 & C4 LC = (contrast & 0x0F); // Contrast C3, C2, C1 & C0 // Send commands to adjust contrast LCD_Command(0x39); // Function Set: 8-bit, 2-line, instruction set 01 LCD_Command(0x70 | LC); // Set lower contrast bits (C3-C0) LCD_Command(0x50 | HC); // Set higher contrast bits (C5-C4) LCD_Command(0x38); // Function Set: 8-bit, 2-line, instruction set 00 } void LCD_Command(unsigned char cmd) { PORTC.OUT &= ~(1 << RS); // RS = 0 for command // Send upper nibble SendNibble(cmd >> 4); LCD_EnablePulse(); // Send lower nibble SendNibble(cmd & 0x0F); LCD_EnablePulse(); _delay_us(50); // Short delay for command processing } void LCD_Data(unsigned char data) { PORTC.OUT |= (1 << RS); // RS = 1 for data // Send upper nibble SendNibble(data >> 4); LCD_EnablePulse(); // Send lower nibble SendNibble(data & 0x0F); LCD_EnablePulse(); _delay_us(50); // Short delay for data processing } void SendNibble(unsigned char nibble) { PORTC.OUT &= ~((1 << D4) | (1 << D5) | (1 << D6) | (1 << D7)); // Clear data pins if (nibble & 0x01) PORTC.OUT |= (1 << D4); // Set D4 if (nibble & 0x02) PORTC.OUT |= (1 << D5); // Set D5 if (nibble & 0x04) PORTC.OUT |= (1 << D6); // Set D6 if (nibble & 0x08) PORTC.OUT |= (1 << D7); // Set D7 } void LCD_EnablePulse(void) { PORTC.OUT |= (1 << E); // Set E HIGH _delay_us(1); // Pulse width PORTC.OUT &= ~(1 << E); // Set E LOW _delay_us(100); // Command processing delay }