1.54ReflectiveLCDTest/main/main.c

238 lines
8.1 KiB
C
Raw Normal View History

#include <stdio.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "driver/gpio.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_dev.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_io_spi.h"
#include "esp_lcd_st7305.h"
#define LCD_HOST SPI2_HOST
#define LCD_PIN_SCLK 6
#define LCD_PIN_SDI 7
#define LCD_PIN_RST 5
#define LCD_PIN_DC 4
#define LCD_PIN_CS 3
#define LCD_PIN_TE 2
#define DC_HIGH gpio_set_level(LCD_PIN_DC, 1)
#define DC_LOW gpio_set_level(LCD_PIN_DC, 0)
#define CS_HIGH gpio_set_level(LCD_PIN_CS, 1)
#define CS_LOW gpio_set_level(LCD_PIN_CS, 0)
// 绘制测试图案
// 画两条边缘线和一个中心点
bool is_rotated = 0; // 跟踪旋转状态
uint8_t *buffer = NULL;
void lcd_init(void){
buffer = heap_caps_malloc(ST7305_RESOLUTION_HOR * ST7305_RESOLUTION_VER / 8 +100, MALLOC_CAP_DMA);
assert(buffer);
memset(buffer,0x00,5100);
}
void lcd_draw_bit(int x, int y, bool enabled){
if(x>=200||y>=200) return;
//x += 4;
x = 199 - x;
uint8_t real_x = x / 4;
uint8_t real_y = y / 2;
uint16_t byte_index = real_y * 51 + real_x;
uint8_t y_group_index = y % 2 != 0;
uint8_t x_group_index = x % 4;
uint8_t bit_index = 7 - (x_group_index *2 + y_group_index);
if(enabled)
buffer[byte_index] |= (1 << bit_index);
else
buffer[byte_index] &= ~(1 << bit_index);
}
void lcd_display(esp_lcd_panel_handle_t panel_handle){
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, ST7305_RESOLUTION_HOR, ST7305_RESOLUTION_VER, buffer));
}
// 绘制测试图案函数
void draw_test_pattern(uint8_t *buffer, bool rotated)
{
memset(buffer, 0, ST7305_RESOLUTION_HOR * ST7305_RESOLUTION_VER / 8 +100);
int width = rotated ? ST7305_RESOLUTION_VER : ST7305_RESOLUTION_HOR;
int height = rotated ? ST7305_RESOLUTION_HOR : ST7305_RESOLUTION_VER;
// 画左边竖线
for (int y = 0; y < height; y++)
{
int x = 10; // 距离左边10像素
uint16_t byte_idx = (y >> 3) * width + x;
uint8_t bit_pos = y & 0x07;
if (byte_idx < width * ((height + 7) >> 3))
{
buffer[byte_idx] |= (1 << bit_pos);
}
}
// 画右边竖线
for (int y = 0; y < height; y++)
{
int x = width - 10; // 距离右边10像素
uint16_t byte_idx = (y >> 3) * width + x;
uint8_t bit_pos = y & 0x07;
if (byte_idx < width * ((height + 7) >> 3))
{
buffer[byte_idx] |= (1 << bit_pos);
}
}
// 在中心画一个5x5的方块
int center_x = width / 2;
int center_y = height / 2;
for (int y = center_y - 2; y <= center_y + 2; y++)
{
for (int x = center_x - 2; x <= center_x + 2; x++)
{
uint16_t byte_idx = (y >> 3) * width + x;
uint8_t bit_pos = y & 0x07;
if (byte_idx < width * ((height + 7) >> 3))
{
buffer[byte_idx] |= (1 << bit_pos);
}
}
}
}
// 无返回值参数为LCD屏句柄XY移动+边缘反弹,极简测试写法
void lcd_anim_test(esp_lcd_panel_handle_t panel_handle)
{
lcd_init(); // LCD初始化与原代码一致
int block_x = 50; // 方块左上角X坐标初始居中
int block_y = 95; // 方块左上角Y坐标初始居中
int dir_x = 1; // X方向1=右移,-1=左移
int dir_y = 1; // Y方向1=下移,-1=上移
// 无限循环实现反弹动画
while(1)
{
/******** 1. 清屏200*200全屏置0避免拖尾 ********/
for(int i=0; i<200; i++)
for(int j=0; j<200; j++)
lcd_draw_bit(j, i, 0);
/******** 2. 绘制10*10方块XY均为变量随方向移动 ********/
for(int i=0; i<10; i++)
for(int j=0; j<10; j++)
lcd_draw_bit(block_x+j, block_y+i, 1);
/******** 3. 刷新显示+50ms延时控制动画速度 ********/
lcd_display(panel_handle);
vTaskDelay(pdMS_TO_TICKS(10));
/******** 4. 更新坐标按方向移动步长1像素 ********/
block_x += dir_x;
block_y += dir_y;
/******** 5. 边界判断+反弹:碰到四周边缘反转对应方向 ********/
// X轴反弹左边界x<=0或右边界x+方块宽>200反转X方向
if(block_x <= 0 || block_x + 10 > 200) dir_x = -dir_x;
// Y轴反弹上边界y<=0或下边界y+方块高>200反转Y方向
if(block_y <= 0 || block_y + 10 > 200) dir_y = -dir_y;
}
}
void app_main(void)
{
/*创建SPI总线*/
spi_bus_config_t buscfg = {
.sclk_io_num = LCD_PIN_SCLK,
.mosi_io_num = LCD_PIN_SDI,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 200 * 200 / 8,
};
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); // 启用 DMA
/*从 SPI 总线分配一个 LCD IO 设备句柄*/
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = LCD_PIN_DC,
.cs_gpio_num = LCD_PIN_CS,
.pclk_hz = 40 * 1000 * 1000,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.spi_mode = 0,
.trans_queue_depth = 10,
};
// 将 LCD 连接到 SPI 总线
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = LCD_PIN_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.bits_per_pixel = 1,
};
// 为 ST7305 创建 LCD 面板句柄,并指定 SPI IO 设备句柄
ESP_ERROR_CHECK(esp_lcd_new_panel_st7305(io_handle, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, is_rotated));
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, false));
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, false));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
printf("Display simple pattern");
lcd_anim_test(panel_handle);
/*
lcd_init();
for(int i=0; i<200; i++){
for(int j=0; j<200; j++){
lcd_draw_bit(j,i,1);
}
vTaskDelay(pdMS_TO_TICKS(1000));
lcd_display(panel_handle);
}
*/
/*
// 准备测试数据
uint8_t *test_pattern = heap_caps_malloc(ST7305_RESOLUTION_HOR * ST7305_RESOLUTION_VER / 8 +100, MALLOC_CAP_DMA);
assert(test_pattern);
memset(test_pattern, 0x00, ST7305_RESOLUTION_HOR * ST7305_RESOLUTION_VER / 8 +100);
// 初始填充并显示:累积字节扫描,完成一次后翻转配色并继续扫描
size_t buf_size = ST7305_RESOLUTION_HOR * ST7305_RESOLUTION_VER / 8 +100;
size_t idx = 0;
bool scanned_is_ff = true; // true已扫描字节为 0xFFfalse已扫描字节为 0x00
while (1)
{
if (scanned_is_ff) {
// 已扫描区域为 0xFF未扫描为 0x00
memset(test_pattern, 0x00, buf_size);
memset(test_pattern, 0xFF, idx + 1);
} else {
// 已扫描区域为 0x00未扫描为 0xFF配色相反
memset(test_pattern, 0xFF, buf_size);
memset(test_pattern, 0x00, idx + 1);
}
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, ST7305_RESOLUTION_HOR, ST7305_RESOLUTION_VER, test_pattern));
idx++;
if (idx >= buf_size) {
// 完成一次扫描,重置索引并翻转配色
idx = 0;
scanned_is_ff = !scanned_is_ff;
vTaskDelay(pdMS_TO_TICKS(200)); // 稍作停顿以便观察配色翻转
} else {
vTaskDelay(pdMS_TO_TICKS(50)); // 平常的扫描速度
}
}
// 释放资源
free(test_pattern);*/
}