#include "lcd.h" #include "ch32v20x.h" void lcd_begin(lcd_t *lcd); void lcd_expander_write(lcd_t *lcd, uint8_t data); void lcd_write4bits(lcd_t *lcd, uint8_t value); void lcd_command(lcd_t *lcd, uint8_t cmd); void lcd_init(lcd_t *lcd, u8 address) { lcd->address = address; lcd->backlight = 0; // Enable I2C1 and GPIOB RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); // Set up GPIO on port B GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // SCL - PB8 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOB, &GPIO_InitStructure); // SDA - PB9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_DeInit(I2C1); I2C_InitTypeDef I2C_InitStructure; I2C_StructInit(&I2C_InitStructure); I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); lcd_begin(lcd); } void lcd_begin(lcd_t *lcd) { lcd->backlight = LCD_BACKLIGHT; Delay_Ms(50); lcd_expander_write(lcd, 0); Delay_Ms(1000); lcd_write4bits(lcd, 0x03 << 4); Delay_Us(4500); lcd_write4bits(lcd, 0x03 << 4); Delay_Us(4500); lcd_write4bits(lcd, 0x03 << 4); Delay_Us(150); lcd_write4bits(lcd, 0x02 << 4); lcd->function = LCD_4BITMODE | LCD_2LINE; lcd_command(lcd, LCD_FUNCTIONSET | lcd->function); lcd->dispctrl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; lcd_command(lcd, LCD_DISPLAYCONTROL | lcd->dispctrl); lcd->entrymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDEC; lcd_command(lcd, LCD_ENTRYMODESET | lcd->entrymode); lcd_clear(lcd); lcd_home(lcd); } void lcd_backlight(lcd_t *lcd) { lcd->backlight = LCD_BACKLIGHT; lcd_expander_write(lcd, 0); } void lcd_no_backlight(lcd_t *lcd) { lcd->backlight = LCD_NOBACKLIGHT; lcd_expander_write(lcd, 0); } void lcd_clear(lcd_t *lcd) { lcd_command(lcd, LCD_CLEARDISPLAY); Delay_Us(2000); } void lcd_home(lcd_t *lcd) { lcd_command(lcd, LCD_RETURNHOME); Delay_Us(2000); } void lcd_cursor(lcd_t *lcd, uint8_t col, uint8_t row) { uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54}; lcd_command(lcd, LCD_SETDDRAMADDR | (col + row_offsets[row])); } void lcd_expander_write(lcd_t *lcd, uint8_t data) { while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET); I2C_GenerateSTART(I2C1, ENABLE); // Delay_Ms(1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // I2C_Send7bitAddress(I2C1, 0x4E, I2C_Direction_Receiver); I2C_SendData(I2C1, lcd->address << 1); // Delay_Ms(1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // I2C_SendData(I2C1, 0x27); // while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_SendData(I2C1, data | lcd->backlight); // Delay_Ms(1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); // Delay_Ms(1); } void lcd_write4bits(lcd_t *lcd, uint8_t value) { lcd_expander_write(lcd, value); lcd_expander_write(lcd, value | LCD_EN); Delay_Us(1); lcd_expander_write(lcd, value & ~LCD_EN); Delay_Us(50); } void lcd_command(lcd_t *lcd, uint8_t cmd) { lcd_write4bits(lcd, cmd & 0xF0); lcd_write4bits(lcd, cmd << 4); } void lcd_write(lcd_t *lcd, char c) { lcd_write4bits(lcd, (c & 0xF0) | LCD_RS); lcd_write4bits(lcd, (c << 4) | LCD_RS); } void lcd_puts(lcd_t *lcd, char *str) { while(*str) lcd_write(lcd, *str++); }