Mini_croe_Sick/User/device/lcd.c
2025-04-12 21:32:00 +08:00

207 lines
6.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "lcd.h"
#include "lcd_font.h"
#include <stdlib.h> // 添加标准库以使用 malloc 和 free
#include "lv_port_disp.h"
// 写命令到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();
}
// 使用 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 row_size = LCD_WIDTH * 2; // 每行像素占用 2 字节
uint8_t *row_buffer = (uint8_t *)malloc(row_size);
if (row_buffer == NULL) return; // 分配失败,直接返回
// 填充缓冲区为目标颜色
for (uint32_t i = 0; i < row_size; i += 2) {
row_buffer[i] = color_data[0];
row_buffer[i + 1] = color_data[1];
}
// 按行传输数据,覆盖整个屏幕
for (uint32_t y = 0; y < LCD_HEIGHT; y++) {
LCD_WriteDataBuffer_DMA(row_buffer, row_size);
}
free(row_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_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
// 旋转 90° 的坐标映射
uint16_t new_x = y;
uint16_t new_y = LCD_HEIGHT - 1 - x;
LCD_SetAddressWindow(new_x, new_y, 1, 1);
uint8_t color_data[] = {color >> 8, color & 0xFF};
LCD_WriteDataBuffer(color_data, 2);
}
// void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) {
// const unsigned char *font = ascii_1206[ch - ' '];
// uint8_t char_buffer[FONT_WIDTH * FONT_HEIGHT * 2]; // 每个像素 2 字节
// uint32_t index = 0;
// // 将字符数据按列存储到缓冲区(逆时针旋转 90 度 + 左右镜像)
// for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度(列)
// for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度(行)
// // 左右镜像:将列索引从 FONT_WIDTH - 1 - i 开始
// if (font[j] & (1 << (FONT_WIDTH - 1 - i))) { // 判断像素是否为前景色
// char_buffer[index++] = color >> 8;
// char_buffer[index++] = color & 0xFF;
// } else { // 背景色
// char_buffer[index++] = bgColor >> 8;
// char_buffer[index++] = bgColor & 0xFF;
// }
// }
// }
// // 设置显示窗口(注意旋转后宽高互换)
// LCD_SetAddressWindow(x, y, FONT_HEIGHT, FONT_WIDTH);
// // 使用 DMA 传输字符像素数据
// LCD_WriteDataBuffer_DMA(char_buffer, sizeof(char_buffer));
// }
// 绘制字符串沿y轴绘制
// void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) {
// y = LCD_HEIGHT-7 -y;
// while (*str) {
// LCD_DrawChar(x, y, *str, color, bgColor);
// y -= FONT_WIDTH; // 每个字符向下移动一个字符宽度
// str++;
// }
// }