146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
|
#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++);
|
||
|
}
|