#include "liquidcrystal_i2c.h" extern I2C_HandleTypeDef hi2c1; uint8_t dpFunction; uint8_t dpControl; uint8_t dpMode; uint8_t dpRows; uint8_t dpBacklight; static void SendCommand(uint8_t); static void SendChar(uint8_t); static void Send(uint8_t, uint8_t); static void Write4Bits(uint8_t); static void ExpanderWrite(uint8_t); static void PulseEnable(uint8_t); static void DelayInit(void); static void DelayUS(uint32_t); uint8_t special1[8] = { 0b00000, 0b11001, 0b11011, 0b00110, 0b01100, 0b11011, 0b10011, 0b00000 }; uint8_t special2[8] = { 0b11000, 0b11000, 0b00110, 0b01001, 0b01000, 0b01001, 0b00110, 0b00000 }; void HD44780_Init(uint8_t rows) { dpRows = rows; dpBacklight = LCD_BACKLIGHT; dpFunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; if (dpRows > 1) { dpFunction |= LCD_2LINE; } else { dpFunction |= LCD_5x10DOTS; } /* Wait for initialization */ DelayInit(); HAL_Delay(50); ExpanderWrite(dpBacklight); HAL_Delay(1000); /* 4bit Mode */ Write4Bits(0x03 << 4); DelayUS(4500); Write4Bits(0x03 << 4); DelayUS(4500); Write4Bits(0x03 << 4); DelayUS(4500); Write4Bits(0x02 << 4); DelayUS(100); /* Display Control */ SendCommand(LCD_FUNCTIONSET | dpFunction); dpControl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; HD44780_Display(); HD44780_Clear(); /* Display Mode */ dpMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; SendCommand(LCD_ENTRYMODESET | dpMode); DelayUS(4500); HD44780_CreateSpecialChar(0, special1); HD44780_CreateSpecialChar(1, special2); HD44780_Home(); } void HD44780_Clear() { SendCommand(LCD_CLEARDISPLAY); DelayUS(2000); } void HD44780_Home() { SendCommand(LCD_RETURNHOME); DelayUS(2000); } void HD44780_SetCursor(uint8_t col, uint8_t row) { int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; if (row >= dpRows) { row = dpRows-1; } SendCommand(LCD_SETDDRAMADDR | (col + row_offsets[row])); } void HD44780_NoDisplay() { dpControl &= ~LCD_DISPLAYON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_Display() { dpControl |= LCD_DISPLAYON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_NoCursor() { dpControl &= ~LCD_CURSORON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_Cursor() { dpControl |= LCD_CURSORON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_NoBlink() { dpControl &= ~LCD_BLINKON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_Blink() { dpControl |= LCD_BLINKON; SendCommand(LCD_DISPLAYCONTROL | dpControl); } void HD44780_ScrollDisplayLeft(void) { SendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); } void HD44780_ScrollDisplayRight(void) { SendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); } void HD44780_LeftToRight(void) { dpMode |= LCD_ENTRYLEFT; SendCommand(LCD_ENTRYMODESET | dpMode); } void HD44780_RightToLeft(void) { dpMode &= ~LCD_ENTRYLEFT; SendCommand(LCD_ENTRYMODESET | dpMode); } void HD44780_AutoScroll(void) { dpMode |= LCD_ENTRYSHIFTINCREMENT; SendCommand(LCD_ENTRYMODESET | dpMode); } void HD44780_NoAutoScroll(void) { dpMode &= ~LCD_ENTRYSHIFTINCREMENT; SendCommand(LCD_ENTRYMODESET | dpMode); } void HD44780_CreateSpecialChar(uint8_t location, uint8_t charmap[]) { location &= 0x7; SendCommand(LCD_SETCGRAMADDR | (location << 3)); for (int i=0; i<8; i++) { SendChar(charmap[i]); } } void HD44780_PrintSpecialChar(uint8_t index) { SendChar(index); } void HD44780_LoadCustomCharacter(uint8_t char_num, uint8_t *rows) { HD44780_CreateSpecialChar(char_num, rows); } void HD44780_PrintStr(const char c[]) { while(*c) SendChar(*c++); } void HD44780_SetBacklight(uint8_t new_val) { if(new_val) HD44780_Backlight(); else HD44780_NoBacklight(); } void HD44780_NoBacklight(void) { dpBacklight=LCD_NOBACKLIGHT; ExpanderWrite(0); } void HD44780_Backlight(void) { dpBacklight=LCD_BACKLIGHT; ExpanderWrite(0); } static void SendCommand(uint8_t cmd) { Send(cmd, 0); } static void SendChar(uint8_t ch) { Send(ch, RS); } static void Send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xF0; uint8_t lownib = (value<<4) & 0xF0; Write4Bits((highnib)|mode); Write4Bits((lownib)|mode); } static void Write4Bits(uint8_t value) { ExpanderWrite(value); PulseEnable(value); } static void ExpanderWrite(uint8_t _data) { uint8_t data = _data | dpBacklight; HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR, (uint8_t*)&data, 1, 10); } static void PulseEnable(uint8_t _data) { ExpanderWrite(_data | ENABLE); DelayUS(20); ExpanderWrite(_data & ~ENABLE); DelayUS(20); } static void DelayInit(void) { CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001; DWT->CYCCNT = 0; /* 3 NO OPERATION instructions */ __ASM volatile ("NOP"); __ASM volatile ("NOP"); __ASM volatile ("NOP"); } static void DelayUS(uint32_t us) { uint32_t cycles = (SystemCoreClock/1000000L)*us; uint32_t start = DWT->CYCCNT; volatile uint32_t cnt; do { cnt = DWT->CYCCNT - start; } while(cnt < cycles); }