#include "lcd.h" #include "lcd_font.h" #include // 添加标准库以使用 malloc 和 free // 写命令到LCD 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(); } // 写数据到LCD 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(); } // // 写多个数据到LCD // static void LCD_WriteDataBuffer(uint8_t *data, uint16_t size) { // LCD_DC_HIGH(); // LCD_CS_LOW(); // HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); // LCD_CS_HIGH(); // } // 使用 DMA 写多个数据到 LCD static void LCD_WriteDataBuffer_DMA(uint8_t *data, uint16_t size) { LCD_DC_HIGH(); LCD_CS_LOW(); HAL_SPI_Transmit_DMA(&hspi1, data, size); // 使用 DMA 传输 while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); // 等待传输完成 LCD_CS_HIGH(); } // 修改原来的 LCD_WriteDataBuffer,增加 DMA 支持 static void LCD_WriteDataBuffer(uint8_t *data, uint16_t size) { if (size > 64) { // 如果数据量较大,使用 DMA LCD_WriteDataBuffer_DMA(data, size); } else { // 否则使用普通传输 LCD_DC_HIGH(); LCD_CS_LOW(); HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); LCD_CS_HIGH(); } } // 初始化LCD void LCD_Init(void) { LCD_RST_LOW(); HAL_Delay(50); LCD_RST_HIGH(); HAL_Delay(50); LCD_WriteCommand(0x36); // Memory Data Access Control LCD_WriteData(0x60); // 横屏模式,向右旋转90度 LCD_WriteCommand(0x3A); // Interface Pixel Format LCD_WriteData(0x05); // 16位色 LCD_WriteCommand(0xB2); // Porch Setting uint8_t porch[] = {0x0C, 0x0C, 0x00, 0x33, 0x33}; LCD_WriteDataBuffer(porch, sizeof(porch)); 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 uint8_t gamma_pos[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}; LCD_WriteDataBuffer(gamma_pos, sizeof(gamma_pos)); LCD_WriteCommand(0xE1); // Negative Voltage Gamma Control uint8_t gamma_neg[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}; LCD_WriteDataBuffer(gamma_neg, sizeof(gamma_neg)); LCD_WriteCommand(0x21); // Display Inversion On LCD_WriteCommand(0x11); // Sleep Out HAL_Delay(120); LCD_WriteCommand(0x29); // Display On } // 设置显示窗口 static void LCD_SetAddressWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { uint16_t x_start = x + X_OFFSET; uint16_t x_end = x_start + w - 1; uint16_t y_start = y + Y_OFFSET; uint16_t y_end = y_start + h - 1; LCD_WriteCommand(0x2A); // Column Address Set uint8_t data_x[] = {x_start >> 8, x_start & 0xFF, x_end >> 8, x_end & 0xFF}; LCD_WriteDataBuffer(data_x, sizeof(data_x)); LCD_WriteCommand(0x2B); // Row Address Set uint8_t data_y[] = {y_start >> 8, y_start & 0xFF, y_end >> 8, y_end & 0xFF}; LCD_WriteDataBuffer(data_y, sizeof(data_y)); LCD_WriteCommand(0x2C); // Memory Write } // 清屏 // void LCD_Clear(uint16_t color) { // uint8_t color_data[] = {color >> 8, color & 0xFF}; // LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); // for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) { // LCD_WriteDataBuffer(color_data, 2); // } // } void LCD_Clear(uint16_t color) { uint8_t color_data[] = {color >> 8, color & 0xFF}; LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); // 创建一个缓冲区,用于存储整屏颜色数据 uint32_t buffer_size = LCD_WIDTH * LCD_HEIGHT * 2; // 每个像素 2 字节 uint8_t *buffer = malloc(buffer_size); if (buffer == NULL) return; // 分配失败,直接返回 for (uint32_t i = 0; i < buffer_size; i += 2) { buffer[i] = color_data[0]; buffer[i + 1] = color_data[1]; } // 使用 DMA 传输整个缓冲区 LCD_WriteDataBuffer_DMA(buffer, buffer_size); free(buffer); // 释放缓冲区 } // 绘制像素 void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) { LCD_SetAddressWindow(x, y, 1, 1); uint8_t color_data[] = {color >> 8, color & 0xFF}; LCD_WriteDataBuffer(color_data, 2); } // // 绘制字符(旋转90度) // void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) { // const unsigned char *font = ascii_1206[ch - ' ']; // for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度 // for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度 // if (font[j] & (1 << i)) { // 行列交换,旋转90度 // LCD_DrawPixel(x + i, y + j, color); // } else { // LCD_DrawPixel(x + i, y + j, bgColor); // } // } // } // } // 绘制字符(逆时针旋转90度) void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) { const unsigned char *font = ascii_1206[ch - ' ']; for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度 for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度 if (font[j] & (1 << i)) { // 行列交换,逆时针旋转90度 LCD_DrawPixel(x + j, y - i, color); // 注意坐标变换 } else { LCD_DrawPixel(x + j, y - i, bgColor); } } } } // 绘制字符串(沿y轴绘制) void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) { y = LCD_HEIGHT-1 -y; while (*str) { LCD_DrawChar(x, y, *str, color, bgColor); y -= FONT_WIDTH; // 每个字符向下移动一个字符宽度 str++; } }