169 lines
4.7 KiB
C
169 lines
4.7 KiB
C
#include "lcd.h"
|
||
#include "lcd_font.h"
|
||
|
||
|
||
// 写命令
|
||
static void LCD_WriteCommand(uint8_t cmd) {
|
||
LCD_DC_LOW();
|
||
LCD_CS_LOW();
|
||
HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);
|
||
LCD_CS_HIGH();
|
||
}
|
||
|
||
// 写数据
|
||
static void LCD_WriteData(uint8_t data) {
|
||
LCD_DC_HIGH();
|
||
LCD_CS_LOW();
|
||
HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
|
||
LCD_CS_HIGH();
|
||
}
|
||
|
||
// 写16位数据
|
||
static void LCD_WriteData16(uint16_t data) {
|
||
uint8_t buf[2] = {data >> 8, data & 0xFF};
|
||
LCD_DC_HIGH();
|
||
LCD_CS_LOW();
|
||
HAL_SPI_Transmit(&hspi1, buf, 2, HAL_MAX_DELAY);
|
||
LCD_CS_HIGH();
|
||
}
|
||
|
||
// 初始化LCD
|
||
void LCD_Init(void) {
|
||
// 复位屏幕
|
||
LCD_RST_LOW();
|
||
HAL_Delay(10);
|
||
LCD_RST_HIGH();
|
||
HAL_Delay(10);
|
||
|
||
// 初始化命令序列(以ST7789为例)
|
||
LCD_WriteCommand(0x36); // Memory Data Access Control
|
||
LCD_WriteData(0xC0); // RGB Color Order
|
||
|
||
LCD_WriteCommand(0x3A); // Interface Pixel Format
|
||
LCD_WriteData(0x05); // 16-bit/pixel
|
||
|
||
LCD_WriteCommand(0xB2); // Porch Setting
|
||
LCD_WriteData(0x0C);
|
||
LCD_WriteData(0x0C);
|
||
LCD_WriteData(0x00);
|
||
LCD_WriteData(0x33);
|
||
LCD_WriteData(0x33);
|
||
|
||
LCD_WriteCommand(0xB7); // Gate Control
|
||
LCD_WriteData(0x35);
|
||
|
||
LCD_WriteCommand(0xBB); // VCOM Setting
|
||
LCD_WriteData(0x19);
|
||
|
||
LCD_WriteCommand(0xC0); // LCM Control
|
||
LCD_WriteData(0x2C);
|
||
|
||
LCD_WriteCommand(0xC2); // VDV and VRH Command Enable
|
||
LCD_WriteData(0x01);
|
||
LCD_WriteCommand(0xC3); // VRH Set
|
||
LCD_WriteData(0x12);
|
||
LCD_WriteCommand(0xC4); // VDV Set
|
||
LCD_WriteData(0x20);
|
||
|
||
LCD_WriteCommand(0xC6); // Frame Rate Control
|
||
LCD_WriteData(0x0F);
|
||
|
||
LCD_WriteCommand(0xD0); // Power Control 1
|
||
LCD_WriteData(0xA4);
|
||
LCD_WriteData(0xA1);
|
||
|
||
LCD_WriteCommand(0xE0); // Positive Voltage Gamma Control
|
||
LCD_WriteData(0xD0);
|
||
LCD_WriteData(0x04);
|
||
LCD_WriteData(0x0D);
|
||
LCD_WriteData(0x11);
|
||
LCD_WriteData(0x13);
|
||
LCD_WriteData(0x2B);
|
||
LCD_WriteData(0x3F);
|
||
LCD_WriteData(0x54);
|
||
LCD_WriteData(0x4C);
|
||
LCD_WriteData(0x18);
|
||
LCD_WriteData(0x0D);
|
||
LCD_WriteData(0x0B);
|
||
LCD_WriteData(0x1F);
|
||
LCD_WriteData(0x23);
|
||
|
||
LCD_WriteCommand(0xE1); // Negative Voltage Gamma Control
|
||
LCD_WriteData(0xD0);
|
||
LCD_WriteData(0x04);
|
||
LCD_WriteData(0x0C);
|
||
LCD_WriteData(0x11);
|
||
LCD_WriteData(0x13);
|
||
LCD_WriteData(0x2C);
|
||
LCD_WriteData(0x3F);
|
||
LCD_WriteData(0x44);
|
||
LCD_WriteData(0x51);
|
||
LCD_WriteData(0x2F);
|
||
LCD_WriteData(0x1F);
|
||
LCD_WriteData(0x1F);
|
||
LCD_WriteData(0x20);
|
||
LCD_WriteData(0x23);
|
||
|
||
LCD_WriteCommand(0x21); // Inversion On
|
||
LCD_WriteCommand(0x11); // Sleep Out
|
||
HAL_Delay(120);
|
||
LCD_WriteCommand(0x29); // Display On
|
||
}
|
||
|
||
// 清屏
|
||
void LCD_Clear(uint16_t color) {
|
||
LCD_WriteCommand(0x2A); // Column Address Set
|
||
LCD_WriteData16(X_OFFSET); // 起始列地址
|
||
LCD_WriteData16(X_OFFSET + LCD_WIDTH - 1); // 结束列地址
|
||
|
||
LCD_WriteCommand(0x2B); // Row Address Set
|
||
LCD_WriteData16(Y_OFFSET); // 起始行地址
|
||
LCD_WriteData16(Y_OFFSET + LCD_HEIGHT - 1); // 结束行地址
|
||
|
||
LCD_WriteCommand(0x2C); // Memory Write
|
||
for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) {
|
||
LCD_WriteData16(color);
|
||
}
|
||
}
|
||
|
||
// 绘制单个像素
|
||
void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
|
||
if (x >= LCD_WIDTH || y >= LCD_HEIGHT) return; // 超出屏幕范围则返回
|
||
|
||
LCD_WriteCommand(0x2A); // 设置列地址
|
||
LCD_WriteData16(X_OFFSET + x);
|
||
LCD_WriteData16(X_OFFSET + x);
|
||
|
||
LCD_WriteCommand(0x2B); // 设置行地址
|
||
LCD_WriteData16(Y_OFFSET + y);
|
||
LCD_WriteData16(Y_OFFSET + y);
|
||
|
||
LCD_WriteCommand(0x2C); // 写入内存
|
||
LCD_WriteData16(color);
|
||
}
|
||
|
||
// 在指定位置显示一个字符
|
||
void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) {
|
||
if (ch < 32 || ch > 126) return; // 字符范围检查 (ASCII 32-126)
|
||
|
||
const uint8_t *charData = ascii_1206[ch - 32]; // 获取字符点阵数据
|
||
for (uint8_t i = 0; i < FONT_HEIGHT; i++) { // 遍历字符的高度
|
||
uint8_t line = charData[i]; // 获取字符的每一行数据
|
||
for (uint8_t j = 0; j < FONT_WIDTH; j++) { // 遍历字符的宽度
|
||
if (line & (1 << j)) { // 判断当前像素是否为1
|
||
LCD_DrawPixel(x + j, y + i, color); // 绘制前景色
|
||
} else {
|
||
LCD_DrawPixel(x + j, y + i, bgColor); // 绘制背景色
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 在指定位置显示字符串
|
||
void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) {
|
||
while (*str) {
|
||
LCD_DrawChar(x, y, *str, color, bgColor); // 显示单个字符
|
||
x += FONT_WIDTH; // 移动到下一个字符位置
|
||
str++;
|
||
}
|
||
} |