Mini_croe_Sick/User/device/lcd.c
2025-04-10 19:35:47 +08:00

199 lines
6.3 KiB
C
Raw 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
// 写命令到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++;
}
}