├── README.md ├── lcd.h └── lcd.c /README.md: -------------------------------------------------------------------------------- 1 | # avr-hd44780 2 | 3 | ## Description 4 | 5 | This is an avr-gcc library for the HD44780 character LCD display. 6 | 7 | After buying the SC1602BS LCD module, I couldn't find an avr-gcc library that drives the display correctly. Arduino's LiquidCrystal library was the only library that worked so this is a simple avr-gcc version of that library. 8 | 9 | Tested with the Teensy++ 2.0 development board. 10 | 11 | ## Usage 12 | 13 | See `lcd.h` for the usable methods. You need to edit it with the pins you're using. 14 | 15 | ## License 16 | 17 | Licensed under the GNU General Public License, Version 2.0. 18 | 19 | You may find a copy of the license at 20 | 21 | ``` 22 | http://www.gnu.org/licenses/gpl-2.0.html 23 | ``` 24 | 25 | ## References 26 | 27 | - [SC1602BS Character Display Module](http://akizukidenshi.com/catalog/g/gP-00040/) 28 | - [Arduino's LiquidCrystal library source](https://code.google.com/p/arduino/source/browse/trunk/libraries/LiquidCrystal) 29 | -------------------------------------------------------------------------------- /lcd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #if ( !defined LCD_DDR || !defined LCD_PORT ) 6 | #warning "Please define LCD_DDR and LCD_PORT" 7 | #define LCD_DDR DDRB 8 | #define LCD_PORT PORTB 9 | #endif 10 | 11 | #ifndef LCD_RS 12 | #warning "LCD Using default pin" 13 | #define LCD_RS 0 14 | #define LCD_RW 1 15 | #define LCD_EN 2 16 | #define LCD_D0 4 17 | #define LCD_D1 5 18 | #define LCD_D2 6 19 | #define LCD_D3 7 20 | #endif 21 | 22 | #define LCD_COL_COUNT 16 23 | #define LCD_ROW_COUNT 2 24 | 25 | // The rest should be left alone 26 | #define LCD_CLEARDISPLAY 0x01 27 | #define LCD_RETURNHOME 0x02 28 | #define LCD_ENTRYMODESET 0x04 29 | #define LCD_DISPLAYCONTROL 0x08 30 | #define LCD_CURSORSHIFT 0x10 31 | #define LCD_FUNCTIONSET 0x20 32 | #define LCD_SETCGRAMADDR 0x40 33 | #define LCD_SETDDRAMADDR 0x80 34 | 35 | #define LCD_ENTRYRIGHT 0x00 36 | #define LCD_ENTRYLEFT 0x02 37 | #define LCD_ENTRYSHIFTINCREMENT 0x01 38 | #define LCD_ENTRYSHIFTDECREMENT 0x00 39 | 40 | #define LCD_DISPLAYON 0x04 41 | #define LCD_DISPLAYOFF 0x00 42 | #define LCD_CURSORON 0x02 43 | #define LCD_CURSOROFF 0x00 44 | #define LCD_BLINKON 0x01 45 | #define LCD_BLINKOFF 0x00 46 | 47 | #define LCD_DISPLAYMOVE 0x08 48 | #define LCD_CURSORMOVE 0x00 49 | #define LCD_MOVERIGHT 0x04 50 | #define LCD_MOVELEFT 0x00 51 | 52 | #define LCD_8BITMODE 0x10 53 | #define LCD_4BITMODE 0x00 54 | #define LCD_2LINE 0x08 55 | #define LCD_1LINE 0x00 56 | #define LCD_5x10DOTS 0x04 57 | #define LCD_5x8DOTS 0x00 58 | 59 | void lcd_init(void); 60 | 61 | void lcd_command(uint8_t command); 62 | void lcd_write(uint8_t value); 63 | 64 | void lcd_on(void); 65 | void lcd_off(void); 66 | 67 | void lcd_clear(void); 68 | void lcd_return_home(void); 69 | 70 | void lcd_enable_blinking(void); 71 | void lcd_disable_blinking(void); 72 | 73 | void lcd_enable_cursor(void); 74 | void lcd_disable_cursor(void); 75 | 76 | void lcd_scroll_left(void); 77 | void lcd_scroll_right(void); 78 | 79 | void lcd_set_left_to_right(void); 80 | void lcd_set_right_to_left(void); 81 | 82 | void lcd_enable_autoscroll(void); 83 | void lcd_disable_autoscroll(void); 84 | 85 | void lcd_create_char(uint8_t location, uint8_t *charmap); 86 | 87 | void lcd_set_cursor(uint8_t col, uint8_t row); 88 | 89 | void lcd_puts(char *string); 90 | void lcd_printf(char *format, ...); 91 | -------------------------------------------------------------------------------- /lcd.c: -------------------------------------------------------------------------------- 1 | #include "lcd.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void lcd_send(uint8_t value, uint8_t mode); 8 | void lcd_write_nibble(uint8_t nibble); 9 | 10 | static uint8_t lcd_displayparams; 11 | static char lcd_buffer[LCD_COL_COUNT + 1]; 12 | 13 | void lcd_command(uint8_t command) { 14 | lcd_send(command, 0); 15 | } 16 | 17 | void lcd_write(uint8_t value) { 18 | lcd_send(value, 1); 19 | } 20 | 21 | void lcd_send(uint8_t value, uint8_t mode) { 22 | if (mode) { 23 | LCD_PORT = LCD_PORT | (1 << LCD_RS); 24 | } else { 25 | LCD_PORT = LCD_PORT & ~(1 << LCD_RS); 26 | } 27 | 28 | LCD_PORT = LCD_PORT & ~(1 << LCD_RW); 29 | 30 | lcd_write_nibble(value >> 4); 31 | lcd_write_nibble(value); 32 | } 33 | 34 | void lcd_write_nibble(uint8_t nibble) { 35 | LCD_PORT = (LCD_PORT & 0xff & ~(0x0f << LCD_D0)) | ((nibble & 0x0f) << LCD_D0); 36 | 37 | LCD_PORT = LCD_PORT & ~(1 << LCD_EN); 38 | LCD_PORT = LCD_PORT | (1 << LCD_EN); 39 | LCD_PORT = LCD_PORT & ~(1 << LCD_EN); 40 | _delay_ms(0.3); // If delay less than this value, the data is not correctly displayed 41 | } 42 | 43 | void lcd_init(void) { 44 | // Configure pins as output 45 | LCD_DDR = LCD_DDR 46 | | (1 << LCD_RS) 47 | | (1 << LCD_RW) 48 | | (1 << LCD_EN) 49 | | (1 << LCD_D0) 50 | | (1 << LCD_D1) 51 | | (1 << LCD_D2) 52 | | (1 << LCD_D3); 53 | 54 | // Wait for LCD to become ready (docs say 15ms+) 55 | _delay_ms(15); 56 | 57 | LCD_PORT = LCD_PORT 58 | & ~(1 << LCD_EN) 59 | & ~(1 << LCD_RS) 60 | & ~(1 << LCD_RW); 61 | 62 | _delay_ms(4.1); 63 | 64 | lcd_write_nibble(0x03); // Switch to 4 bit mode 65 | _delay_ms(4.1); 66 | 67 | lcd_write_nibble(0x03); // 2nd time 68 | _delay_ms(4.1); 69 | 70 | lcd_write_nibble(0x03); // 3rd time 71 | _delay_ms(4.1); 72 | 73 | lcd_write_nibble(0x02); // Set 8-bit mode (?) 74 | 75 | lcd_command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS); 76 | 77 | lcd_displayparams = LCD_CURSOROFF | LCD_BLINKOFF; 78 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 79 | } 80 | 81 | void lcd_on(void) { 82 | lcd_displayparams |= LCD_DISPLAYON; 83 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 84 | } 85 | 86 | void lcd_off(void) { 87 | lcd_displayparams &= ~LCD_DISPLAYON; 88 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 89 | } 90 | 91 | void lcd_clear(void) { 92 | lcd_command(LCD_CLEARDISPLAY); 93 | _delay_ms(2); 94 | } 95 | 96 | void lcd_return_home(void) { 97 | lcd_command(LCD_RETURNHOME); 98 | _delay_ms(2); 99 | } 100 | 101 | void lcd_enable_blinking(void) { 102 | lcd_displayparams |= LCD_BLINKON; 103 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 104 | } 105 | 106 | void lcd_disable_blinking(void) { 107 | lcd_displayparams &= ~LCD_BLINKON; 108 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 109 | } 110 | 111 | void lcd_enable_cursor(void) { 112 | lcd_displayparams |= LCD_CURSORON; 113 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 114 | } 115 | 116 | void lcd_disable_cursor(void) { 117 | lcd_displayparams &= ~LCD_CURSORON; 118 | lcd_command(LCD_DISPLAYCONTROL | lcd_displayparams); 119 | } 120 | 121 | void lcd_scroll_left(void) { 122 | lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 123 | } 124 | 125 | void lcd_scroll_right(void) { 126 | lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 127 | } 128 | 129 | void lcd_set_left_to_right(void) { 130 | lcd_displayparams |= LCD_ENTRYLEFT; 131 | lcd_command(LCD_ENTRYMODESET | lcd_displayparams); 132 | } 133 | 134 | void lcd_set_right_to_left(void) { 135 | lcd_displayparams &= ~LCD_ENTRYLEFT; 136 | lcd_command(LCD_ENTRYMODESET | lcd_displayparams); 137 | } 138 | 139 | void lcd_enable_autoscroll(void) { 140 | lcd_displayparams |= LCD_ENTRYSHIFTINCREMENT; 141 | lcd_command(LCD_ENTRYMODESET | lcd_displayparams); 142 | } 143 | 144 | void lcd_disable_autoscroll(void) { 145 | lcd_displayparams &= ~LCD_ENTRYSHIFTINCREMENT; 146 | lcd_command(LCD_ENTRYMODESET | lcd_displayparams); 147 | } 148 | 149 | void lcd_create_char(uint8_t location, uint8_t *charmap) { 150 | lcd_command(LCD_SETCGRAMADDR | ((location & 0x7) << 3)); 151 | for (int i = 0; i < 8; i++) { 152 | lcd_write(charmap[i]); 153 | } 154 | lcd_command(LCD_SETDDRAMADDR); 155 | } 156 | 157 | void lcd_set_cursor(uint8_t col, uint8_t row) { 158 | static uint8_t offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 159 | 160 | lcd_command(LCD_SETDDRAMADDR | (col + offsets[row])); 161 | } 162 | 163 | void lcd_puts(char *string) { 164 | for (char *it = string; *it; it++) { 165 | lcd_write(*it); 166 | } 167 | } 168 | 169 | void lcd_printf(char *format, ...) { 170 | va_list args; 171 | 172 | va_start(args, format); 173 | vsnprintf(lcd_buffer, LCD_COL_COUNT + 1, format, args); 174 | va_end(args); 175 | 176 | lcd_puts(lcd_buffer); 177 | } 178 | --------------------------------------------------------------------------------