ILI9341 TFT液晶显示驱动芯片深度解析与实践指南

摘要

本文全面深入探讨了ILI9341显示驱动芯片的技术细节、工作原理、接口方式以及实际应用。内容涵盖硬件接口、通信协议、初始化配置、图形绘制算法、性能优化等核心主题,提供了丰富的代码示例和实践经验。无论您是嵌入式开发新手还是经验丰富的工程师,本文都将为您提供全面的ILI9341应用指南。

第一章:ILI9341芯片概述

1.1 ILI9341简介

ILI9341是ILITEK公司生产的一款广泛应用于嵌入式系统的TFT液晶显示驱动芯片。该芯片支持高达240x320像素的RGB 18位色显示,内置显存(GRAM),可以通过多种接口与主控制器通信,包括SPI、8位/16位8080并行接口和RGB接口。

1.2 主要特性与技术参数

1.2.1 显示特性
  • 分辨率:支持240×320像素(QVGA)
  • 色彩深度:支持262K色(RGB 6-6-6格式,18位)
  • 显存容量:172,800字节(240×320×18/8)
  • 刷新率:最高60Hz
1.2.2 接口特性
  • 8位/9位/16位/18位并行接口(8080/6800模式)
  • 3线/4线串行外设接口(SPI)
  • 6位/16位/18位RGB接口(需外部帧缓存)
1.2.3 电源要求
  • 逻辑电压(VDD):2.5V - 3.3V
  • 模拟电压(AVDD):2.5V - 3.3V
  • LED背光电压(VLED):通常3.0V - 20V

1.3 应用领域

ILI9341广泛应用于:

  • 工业控制HMI界面
  • 消费电子产品
  • 医疗设备显示
  • 物联网设备
  • 教育开发板(如STM32、ESP32、Arduino等)

第二章:硬件接口与电路设计

2.1 引脚功能详解

2.1.1 电源与背光引脚
// 电源引脚定义
#define VCC      3.3V     // 逻辑电源
#define VDDIO    3.3V     // I/O电源
#define AVDD     3.3V     // 模拟电路电源
#define VCOM     可变     // 公共电压
#define VGH      可变     // 栅极高电压
#define VGL      可变     // 栅极低电压
2.1.2 控制信号引脚
// 控制引脚说明
/*
CS#    : 片选信号,低电平有效
RESET# : 硬件复位,低电平复位
DC/RS  : 数据/命令选择(SPI)或寄存器选择(8080)
WR#    : 写使能(8080模式)
RD#    : 读使能(8080模式)
TE     : 撕裂效果输出(可选)
IM[3:0]: 接口模式选择
*/

2.2 接口模式配置

2.2.1 接口模式选择表
IM3 IM2 IM1 IM0 接口模式 数据宽度
1 1 0 0 8位8080并行 8位
1 1 0 1 16位8080并行 16位
1 1 1 1 3线/4线SPI 8位
0 1 0 1 RGB 6-6-6 18位

2.3 典型电路设计

2.3.1 电源电路设计
// 电源电路设计要点
/*
1. VCC和VDDIO应连接到同一3.3V电源
2. AVDD需要稳定,建议加10μF和0.1μF去耦电容
3. VCOM、VGH、VGL通常由电荷泵产生
4. LED背光需要限流电阻:R = (VCC - Vf_LED) / I_LED
*/
2.3.2 复位电路设计
// 推荐复位电路
/*
          VCC
           |
          10kΩ
           |
RESET ----|---- GPIO
           |
          100nF
           |
          GND
*/

第三章:通信协议详解

3.1 SPI接口协议

3.1.1 4线SPI通信时序
// SPI通信时序示例代码
void ili9341_spi_write_command(uint8_t cmd) {
    // 拉低DC引脚表示命令
    GPIO_WriteLow(DC_PIN);
    
    // 拉低CS引脚选择设备
    GPIO_WriteLow(CS_PIN);
    
    // 发送命令字节
    spi_transfer(cmd);
    
    // 释放CS引脚
    GPIO_WriteHigh(CS_PIN);
}

void ili9341_spi_write_data(uint8_t data) {
    // 拉高DC引脚表示数据
    GPIO_WriteHigh(DC_PIN);
    
    // 拉低CS引脚选择设备
    GPIO_WriteLow(CS_PIN);
    
    // 发送数据字节
    spi_transfer(data);
    
    // 释放CS引脚
    GPIO_WriteHigh(CS_PIN);
}

// 批量数据传输优化
void ili9341_spi_write_data_bulk(uint8_t *data, uint32_t len) {
    GPIO_WriteHigh(DC_PIN);
    GPIO_WriteLow(CS_PIN);
    
    // 使用DMA或快速SPI传输
    spi_transfer_bulk(data, len);
    
    GPIO_WriteHigh(CS_PIN);
}
3.1.2 SPI模式与时钟配置
// SPI配置参数
typedef struct {
    uint32_t baudrate;     // 通信波特率
    uint8_t data_size;     // 数据位宽:8位
    uint8_t mode;          // CPOL=0, CPHA=0 或 CPOL=1, CPHA=1
    uint8_t bit_order;     // MSB first
} SPI_Config;

// 推荐的SPI配置
SPI_Config ili9341_spi_config = {
    .baudrate = 40000000,  // 最高40MHz
    .data_size = 8,
    .mode = 0,             // 模式0
    .bit_order = SPI_MSB_FIRST
};

3.2 8080并行接口协议

3.2.1 8位并行接口实现
// 8位8080接口写操作
void ili9341_8080_write_8bit(uint8_t data, uint8_t is_data) {
    // 设置数据/命令选择
    if (is_data) {
        GPIO_WriteHigh(DC_PIN);
    } else {
        GPIO_WriteLow(DC_PIN);
    }
    
    // 设置数据总线
    set_data_bus_8bit(data);
    
    // 产生写脉冲
    GPIO_WriteLow(WR_PIN);
    delay_ns(10);           // tWRW > 15ns
    GPIO_WriteHigh(WR_PIN);
    delay_ns(10);           // tWRH > 15ns
}

// 16位并行接口写操作
void ili9341_8080_write_16bit(uint16_t data, uint8_t is_data) {
    // 设置数据/命令选择
    if (is_data) {
        GPIO_WriteHigh(DC_PIN);
    } else {
        GPIO_WriteLow(DC_PIN);
    }
    
    // 设置数据总线
    set_data_bus_16bit(data);
    
    // 产生写脉冲
    GPIO_WriteLow(WR_PIN);
    delay_ns(10);
    GPIO_WriteHigh(WR_PIN);
    delay_ns(10);
}
3.2.2 读操作实现
// 8080接口读操作
uint8_t ili9341_8080_read_8bit(uint8_t is_data) {
    uint8_t data;
    
    // 设置数据/命令选择
    if (is_data) {
        GPIO_WriteHigh(DC_PIN);
    } else {
        GPIO_WriteLow(DC_PIN);
    }
    
    // 配置数据总线为输入
    configure_data_bus_as_input();
    
    // 产生读脉冲
    GPIO_WriteLow(RD_PIN);
    delay_ns(50);           // tRL > 40ns
    data = read_data_bus_8bit();
    GPIO_WriteHigh(RD_PIN);
    delay_ns(50);           // tRH > 40ns
    
    // 恢复数据总线为输出
    configure_data_bus_as_output();
    
    return data;
}

3.3 RGB接口配置

3.3.1 RGB接口时序
// RGB接口时序参数
typedef struct {
    uint16_t hsync_width;      // 行同步脉冲宽度
    uint16_t hsync_back_porch; // 行后沿
    uint16_t hsync_front_porch;// 行前沿
    uint16_t vsync_width;      // 场同步脉冲宽度
    uint16_t vsync_back_porch; // 场后沿
    uint16_t vsync_front_porch;// 场前沿
    uint16_t width;            // 有效显示宽度
    uint16_t height;           // 有效显示高度
    uint8_t  clock_polarity;   // 时钟极性
    uint8_t  hsync_polarity;   // 行同步极性
    uint8_t  vsync_polarity;   // 场同步极性
} RGB_Timing;

// 典型RGB时序配置
RGB_Timing ili9341_rgb_timing = {
    .hsync_width = 10,
    .hsync_back_porch = 20,
    .hsync_front_porch = 10,
    .vsync_width = 2,
    .vsync_back_porch = 2,
    .vsync_front_porch = 2,
    .width = 240,
    .height = 320,
    .clock_polarity = 0,    // 下降沿采样
    .hsync_polarity = 0,    // 低电平有效
    .vsync_polarity = 0     // 低电平有效
};

第四章:初始化与配置

4.1 硬件初始化序列

4.1.1 完整初始化流程
// ILI9341初始化函数
void ili9341_init(void) {
    // 1. 硬件复位
    ili9341_hardware_reset();
    
    // 2. 等待电源稳定
    delay_ms(120);
    
    // 3. 发送初始化命令序列
    ili9341_send_init_commands();
    
    // 4. 配置显示方向
    ili9341_set_rotation(ROTATION_0);
    
    // 5. 清屏
    ili9341_fill_screen(COLOR_BLACK);
    
    // 6. 开启显示
    ili9341_display_on();
}

// 硬件复位函数
void ili9341_hardware_reset(void) {
    // 拉低复位引脚
    GPIO_WriteLow(RESET_PIN);
    delay_ms(10);
    
    // 释放复位引脚
    GPIO_WriteHigh(RESET_PIN);
    delay_ms(120);  // 等待复位完成
}
4.1.2 初始化命令序列
// 初始化命令表
static const uint8_t ili9341_init_cmds[] = {
    // 电源控制命令
    0xCF, 3, 0x00, 0xC1, 0x30,           // Power control B
    0xED, 4, 0x64, 0x03, 0x12, 0x81,     // Power on sequence control
    0xE8, 3, 0x85, 0x00, 0x78,           // Driver timing control A
    0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, // Power control A
    0xF7, 1, 0x20,                       // Pump ratio control
    0xEA, 2, 0x00, 0x00,                 // Driver timing control B
    
    // 电源电压控制
    0xC0, 1, 0x23,                       // Power control 1
    0xC1, 1, 0x10,                       // Power control 2
    0xC5, 2, 0x3E, 0x28,                 // VCOM control 1
    0xC7, 1, 0x86,                       // VCOM control 2
    
    // 内存访问控制
    0x36, 1, 0x48,                       // Memory Access Control
    0x3A, 1, 0x55,                       // Pixel Format Set (16-bit/pixel)
    
    // 帧率控制
    0xB1, 2, 0x00, 0x18,                 // Frame Rate Control (normal mode)
    0xB6, 4, 0x08, 0x82, 0x27, 0x00,     // Display Function Control
    
    // Gamma校正
    0xF2, 1, 0x00,                       // 3Gamma Function Disable
    0x26, 1, 0x01,                       // Gamma Set
    
    // 正伽马校正
    0xE0, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08,
             0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03,
             0x0E, 0x09, 0x00,
    
    // 负伽马校正
    0xE1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07,
             0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C,
             0x31, 0x36, 0x0F,
    
    // 退出睡眠模式
    0x11, 0,                             // Sleep Out
    0x00                                 // 结束标记
};

// 发送初始化命令序列
void ili9341_send_init_commands(void) {
    const uint8_t *cmd = ili9341_init_cmds;
    
    while (*cmd) {
        uint8_t command = *cmd++;
        uint8_t num_args = *cmd++;
        
        // 发送命令
        ili9341_write_command(command);
        
        // 发送参数
        for (uint8_t i = 0; i < num_args; i++) {
            ili9341_write_data(*cmd++);
        }
        
        // 特殊命令延时
        if (command == 0x11) {  // Sleep Out命令
            delay_ms(120);
        }
    }
}

4.2 显示方向配置

4.2.1 显示方向寄存器详解
// 内存访问控制寄存器(0x36)位定义
typedef union {
    struct {
        uint8_t my : 1;  // 行地址顺序
        uint8_t mx : 1;  // 列地址顺序
        uint8_t mv : 1;  // 行列交换
        uint8_t ml : 1;  // 垂直刷新顺序
        uint8_t bgr : 1; // BGR顺序
        uint8_t mh : 1;  // 水平刷新顺序
        uint8_t : 2;     // 保留
    } bits;
    uint8_t value;
} ili9341_mac_t;

// 显示方向设置
typedef enum {
    ROTATION_0   = 0x48,   // 正常方向
    ROTATION_90  = 0x28,   // 顺时针90度
    ROTATION_180 = 0x88,   // 180度
    ROTATION_270 = 0xE8    // 顺时针270度
} DisplayRotation;

// 设置显示方向
void ili9341_set_rotation(DisplayRotation rotation) {
    ili9341_write_command(0x36);      // MADCTL
    ili9341_write_data(rotation);
    
    // 更新显示尺寸
    switch (rotation) {
        case ROTATION_0:
        case ROTATION_180:
            display_width = 240;
            display_height = 320;
            break;
        case ROTATION_90:
        case ROTATION_270:
            display_width = 320;
            display_height = 240;
            break;
    }
}

4.3 像素格式配置

4.3.1 像素格式寄存器(0x3A)
// COLMOD - Interface Pixel Format
typedef enum {
    PIXEL_FORMAT_12BIT = 0x03,  // 12位/像素,RGB 4-4-4
    PIXEL_FORMAT_16BIT = 0x05,  // 16位/像素,RGB 5-6-5
    PIXEL_FORMAT_18BIT = 0x06,  // 18位/像素,RGB 6-6-6
    PIXEL_FORMAT_24BIT = 0x07   // 24位/像素,RGB 8-8-8
} PixelFormat;

// 设置像素格式
void ili9341_set_pixel_format(PixelFormat format) {
    ili9341_write_command(0x3A);      // COLMOD
    ili9341_write_data(format);
    
    // 根据像素格式设置颜色转换函数
    current_pixel_format = format;
}

// 16位颜色处理函数
uint16_t rgb888_to_rgb565(uint32_t rgb888) {
    uint8_t r = (rgb888 >> 16) & 0xFF;
    uint8_t g = (rgb888 >> 8) & 0xFF;
    uint8_t b = rgb888 & 0xFF;
    
    return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

// 18位颜色处理函数
uint32_t rgb888_to_rgb666(uint32_t rgb888) {
    uint8_t r = (rgb888 >> 16) & 0xFF;
    uint8_t g = (rgb888 >> 8) & 0xFF;
    uint8_t b = rgb888 & 0xFF;
    
    return ((r & 0xFC) << 10) | ((g & 0xFC) << 4) | (b >> 2);
}

第五章:图形绘制基础

5.1 基本绘图操作

5.1.1 设置显示窗口
// 设置显示窗口
void ili9341_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    // 设置列地址
    ili9341_write_command(0x2A);      // CASET
    ili9341_write_data(x0 >> 8);
    ili9341_write_data(x0 & 0xFF);
    ili9341_write_data(x1 >> 8);
    ili9341_write_data(x1 & 0xFF);
    
    // 设置行地址
    ili9341_write_command(0x2B);      // RASET
    ili9341_write_data(y0 >> 8);
    ili9341_write_data(y0 & 0xFF);
    ili9341_write_data(y1 >> 8);
    ili9341_write_data(y1 & 0xFF);
    
    // 准备写入GRAM
    ili9341_write_command(0x2C);      // RAMWR
}

// 快速设置窗口(优化版本)
void ili9341_set_window_fast(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    uint8_t buffer[8];
    
    // 准备CASET命令数据
    buffer[0] = x0 >> 8;
    buffer[1] = x0 & 0xFF;
    buffer[2] = x1 >> 8;
    buffer[3] = x1 & 0xFF;
    
    // 准备RASET命令数据
    buffer[4] = y0 >> 8;
    buffer[5] = y0 & 0xFF;
    buffer[6] = y1 >> 8;
    buffer[7] = y1 & 0xFF;
    
    // 一次性发送所有命令
    ili9341_write_command(0x2A);
    ili9341_write_data_bulk(buffer, 4);
    
    ili9341_write_command(0x2B);
    ili9341_write_data_bulk(buffer + 4, 4);
    
    ili9341_write_command(0x2C);
}
5.1.2 清屏函数
// 清屏函数
void ili9341_fill_screen(uint16_t color) {
    // 设置全屏窗口
    ili9341_set_window(0, 0, display_width - 1, display_height - 1);
    
    // 计算像素数量
    uint32_t pixel_count = display_width * display_height;
    
    // 快速填充
    if (current_interface == INTERFACE_SPI) {
        // SPI接口快速填充
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        // 准备颜色数据
        uint8_t color_high = color >> 8;
        uint8_t color_low = color & 0xFF;
        
        // 批量发送
        for (uint32_t i = 0; i < pixel_count; i++) {
            spi_transfer(color_high);
            spi_transfer(color_low);
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        // 8080接口快速填充
        GPIO_WriteHigh(DC_PIN);
        
        for (uint32_t i = 0; i < pixel_count; i++) {
            ili9341_write_data_16bit(color);
        }
    }
}

// 区域填充
void ili9341_fill_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    // 边界检查
    if (x >= display_width || y >= display_height) return;
    
    // 计算实际填充区域
    uint16_t x1 = x + w - 1;
    uint16_t y1 = y + h - 1;
    
    if (x1 >= display_width) x1 = display_width - 1;
    if (y1 >= display_height) y1 = display_height - 1;
    
    // 设置窗口
    ili9341_set_window(x, y, x1, y1);
    
    // 计算像素数量
    uint32_t pixel_count = (x1 - x + 1) * (y1 - y + 1);
    
    // 填充颜色
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        uint8_t color_high = color >> 8;
        uint8_t color_low = color & 0xFF;
        
        for (uint32_t i = 0; i < pixel_count; i++) {
            spi_transfer(color_high);
            spi_transfer(color_low);
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint32_t i = 0; i < pixel_count; i++) {
            set_data_bus_16bit(color);
            
            GPIO_WriteLow(WR_PIN);
            asm("nop");  // 短延时
            GPIO_WriteHigh(WR_PIN);
        }
    }
}
5.1.3 绘制像素点
// 绘制单个像素
void ili9341_draw_pixel(uint16_t x, uint16_t y, uint16_t color) {
    // 边界检查
    if (x >= display_width || y >= display_height) return;
    
    // 设置窗口为单个像素
    ili9341_set_window(x, y, x, y);
    
    // 写入像素颜色
    if (current_interface == INTERFACE_SPI) {
        ili9341_write_data_16bit(color);
    } else {
        GPIO_WriteHigh(DC_PIN);
        ili9341_write_data_16bit(color);
    }
}

// 批量绘制像素(优化版本)
void ili9341_draw_pixels(uint16_t x, uint16_t y, uint16_t *colors, uint32_t count) {
    if (x >= display_width || y >= display_height) return;
    
    // 计算行结束位置
    uint16_t x_end = x + count - 1;
    if (x_end >= display_width) {
        x_end = display_width - 1;
        count = x_end - x + 1;
    }
    
    // 设置窗口
    ili9341_set_window(x, y, x_end, y);
    
    // 批量写入像素
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint32_t i = 0; i < count; i++) {
            spi_transfer(colors[i] >> 8);
            spi_transfer(colors[i] & 0xFF);
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint32_t i = 0; i < count; i++) {
            set_data_bus_16bit(colors[i]);
            
            GPIO_WriteLow(WR_PIN);
            asm("nop");
            GPIO_WriteHigh(WR_PIN);
        }
    }
}

5.2 几何图形绘制

5.2.1 绘制直线
// Bresenham直线算法
void ili9341_draw_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) {
    int16_t dx = abs(x1 - x0);
    int16_t dy = abs(y1 - y0);
    int16_t sx = (x0 < x1) ? 1 : -1;
    int16_t sy = (y0 < y1) ? 1 : -1;
    int16_t err = dx - dy;
    int16_t e2;
    
    while (1) {
        ili9341_draw_pixel(x0, y0, color);
        
        if (x0 == x1 && y0 == y1) break;
        
        e2 = 2 * err;
        
        if (e2 > -dy) {
            err -= dy;
            x0 += sx;
        }
        
        if (e2 < dx) {
            err += dx;
            y0 += sy;
        }
    }
}

// 绘制水平线(优化版本)
void ili9341_draw_hline(uint16_t x, uint16_t y, uint16_t w, uint16_t color) {
    // 边界检查
    if (y >= display_height) return;
    
    // 计算实际绘制区域
    uint16_t x_end = x + w - 1;
    if (x_end >= display_width) x_end = display_width - 1;
    if (x >= display_width) return;
    
    // 使用矩形填充实现水平线
    ili9341_fill_rect(x, y, x_end - x + 1, 1, color);
}

// 绘制垂直线(优化版本)
void ili9341_draw_vline(uint16_t x, uint16_t y, uint16_t h, uint16_t color) {
    // 边界检查
    if (x >= display_width) return;
    
    // 计算实际绘制区域
    uint16_t y_end = y + h - 1;
    if (y_end >= display_height) y_end = display_height - 1;
    if (y >= display_height) return;
    
    // 使用矩形填充实现垂直线
    ili9341_fill_rect(x, y, 1, y_end - y + 1, color);
}
5.2.2 绘制矩形
// 绘制空心矩形
void ili9341_draw_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    // 上边
    ili9341_draw_hline(x, y, w, color);
    
    // 下边
    ili9341_draw_hline(x, y + h - 1, w, color);
    
    // 左边
    ili9341_draw_vline(x, y, h, color);
    
    // 右边
    ili9341_draw_vline(x + w - 1, y, h, color);
}

// 绘制圆角矩形
void ili9341_draw_rounded_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, 
                              uint16_t r, uint16_t color) {
    // 绘制四个角
    ili9341_draw_circle_helper(x + r, y + r, r, 1, color);       // 左上角
    ili9341_draw_circle_helper(x + w - r - 1, y + r, r, 2, color); // 右上角
    ili9341_draw_circle_helper(x + w - r - 1, y + h - r - 1, r, 4, color); // 右下角
    ili9341_draw_circle_helper(x + r, y + h - r - 1, r, 8, color); // 左下角
    
    // 绘制四条边
    ili9341_draw_hline(x + r, y, w - 2 * r, color);             // 上边
    ili9341_draw_hline(x + r, y + h - 1, w - 2 * r, color);     // 下边
    ili9341_draw_vline(x, y + r, h - 2 * r, color);             // 左边
    ili9341_draw_vline(x + w - 1, y + r, h - 2 * r, color);     // 右边
}
5.2.3 绘制圆形
// Bresenham圆形算法
void ili9341_draw_circle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) {
    int16_t f = 1 - r;
    int16_t ddF_x = 1;
    int16_t ddF_y = -2 * r;
    int16_t x = 0;
    int16_t y = r;
    
    // 绘制8个对称点
    ili9341_draw_pixel(x0, y0 + r, color);
    ili9341_draw_pixel(x0, y0 - r, color);
    ili9341_draw_pixel(x0 + r, y0, color);
    ili9341_draw_pixel(x0 - r, y0, color);
    
    while (x < y) {
        if (f >= 0) {
            y--;
            ddF_y += 2;
            f += ddF_y;
        }
        
        x++;
        ddF_x += 2;
        f += ddF_x;
        
        // 绘制8个对称点
        ili9341_draw_pixel(x0 + x, y0 + y, color);
        ili9341_draw_pixel(x0 - x, y0 + y, color);
        ili9341_draw_pixel(x0 + x, y0 - y, color);
        ili9341_draw_pixel(x0 - x, y0 - y, color);
        ili9341_draw_pixel(x0 + y, y0 + x, color);
        ili9341_draw_pixel(x0 - y, y0 + x, color);
        ili9341_draw_pixel(x0 + y, y0 - x, color);
        ili9341_draw_pixel(x0 - y, y0 - x, color);
    }
}

// 绘制填充圆形
void ili9341_fill_circle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) {
    ili9341_draw_vline(x0, y0 - r, 2 * r + 1, color);
    ili9341_fill_circle_helper(x0, y0, r, 3, 0, color);
}

// 圆形辅助函数
void ili9341_draw_circle_helper(uint16_t x0, uint16_t y0, uint16_t r, 
                               uint8_t cornername, uint16_t color) {
    int16_t f = 1 - r;
    int16_t ddF_x = 1;
    int16_t ddF_y = -2 * r;
    int16_t x = 0;
    int16_t y = r;
    
    while (x < y) {
        if (f >= 0) {
            y--;
            ddF_y += 2;
            f += ddF_y;
        }
        
        x++;
        ddF_x += 2;
        f += ddF_x;
        
        if (cornername & 0x4) {
            ili9341_draw_pixel(x0 + x, y0 + y, color);
            ili9341_draw_pixel(x0 + y, y0 + x, color);
        }
        
        if (cornername & 0x2) {
            ili9341_draw_pixel(x0 + x, y0 - y, color);
            ili9341_draw_pixel(x0 + y, y0 - x, color);
        }
        
        if (cornername & 0x8) {
            ili9341_draw_pixel(x0 - y, y0 + x, color);
            ili9341_draw_pixel(x0 - x, y0 + y, color);
        }
        
        if (cornername & 0x1) {
            ili9341_draw_pixel(x0 - y, y0 - x, color);
            ili9341_draw_pixel(x0 - x, y0 - y, color);
        }
    }
}

void ili9341_fill_circle_helper(uint16_t x0, uint16_t y0, uint16_t r, 
                               uint8_t cornername, int16_t delta, uint16_t color) {
    int16_t f = 1 - r;
    int16_t ddF_x = 1;
    int16_t ddF_y = -2 * r;
    int16_t x = 0;
    int16_t y = r;
    
    while (x < y) {
        if (f >= 0) {
            y--;
            ddF_y += 2;
            f += ddF_y;
        }
        
        x++;
        ddF_x += 2;
        f += ddF_x;
        
        if (cornername & 0x1) {
            ili9341_draw_vline(x0 + x, y0 - y, 2 * y + 1 + delta, color);
            ili9341_draw_vline(x0 + y, y0 - x, 2 * x + 1 + delta, color);
        }
        
        if (cornername & 0x2) {
            ili9341_draw_vline(x0 - x, y0 - y, 2 * y + 1 + delta, color);
            ili9341_draw_vline(x0 - y, y0 - x, 2 * x + 1 + delta, color);
        }
    }
}
5.2.4 绘制三角形
// 绘制三角形
void ili9341_draw_triangle(uint16_t x0, uint16_t y0, 
                          uint16_t x1, uint16_t y1,
                          uint16_t x2, uint16_t y2, 
                          uint16_t color) {
    ili9341_draw_line(x0, y0, x1, y1, color);
    ili9341_draw_line(x1, y1, x2, y2, color);
    ili9341_draw_line(x2, y2, x0, y0, color);
}

// 绘制填充三角形
void ili9341_fill_triangle(uint16_t x0, uint16_t y0,
                          uint16_t x1, uint16_t y1,
                          uint16_t x2, uint16_t y2,
                          uint16_t color) {
    int16_t a, b, y, last;
    
    // 按y坐标排序顶点
    if (y0 > y1) {
        swap(y0, y1); swap(x0, x1);
    }
    if (y1 > y2) {
        swap(y2, y1); swap(x2, x1);
    }
    if (y0 > y1) {
        swap(y0, y1); swap(x0, x1);
    }
    
    // 处理退化三角形
    if (y0 == y2) {
        a = b = x0;
        if (x1 < a) a = x1;
        else if (x1 > b) b = x1;
        if (x2 < a) a = x2;
        else if (x2 > b) b = x2;
        
        ili9341_draw_hline(a, y0, b - a + 1, color);
        return;
    }
    
    int16_t dx01 = x1 - x0;
    int16_t dy01 = y1 - y0;
    int16_t dx02 = x2 - x0;
    int16_t dy02 = y2 - y0;
    int16_t dx12 = x2 - x1;
    int16_t dy12 = y2 - y1;
    int32_t sa = 0;
    int32_t sb = 0;
    
    // 处理上半部分
    if (y1 == y2) last = y1;
    else last = y1 - 1;
    
    for (y = y0; y <= last; y++) {
        a = x0 + sa / dy01;
        b = x0 + sb / dy02;
        sa += dx01;
        sb += dx02;
        
        if (a > b) swap(a, b);
        ili9341_draw_hline(a, y, b - a + 1, color);
    }
    
    // 处理下半部分
    sa = (int32_t)dx12 * (y - y1);
    sb = (int32_t)dx02 * (y - y0);
    
    for (; y <= y2; y++) {
        a = x1 + sa / dy12;
        b = x0 + sb / dy02;
        sa += dx12;
        sb += dx02;
        
        if (a > b) swap(a, b);
        ili9341_draw_hline(a, y, b - a + 1, color);
    }
}

第六章:文本显示与字体处理

6.1 字符编码与字体

6.1.1 ASCII字符显示
// 简单ASCII字体(8x16像素)
const uint8_t ascii_font_8x16[95][16] = {
    // 空格 (ASCII 32)
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    
    // ! (ASCII 33)
    {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18,
     0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
    
    // ... 其他字符定义
};

// 显示ASCII字符
void ili9341_draw_char_8x16(uint16_t x, uint16_t y, char c, 
                           uint16_t color, uint16_t bg_color) {
    // 边界检查
    if (x >= display_width || y >= display_height) return;
    if (c < 32 || c > 126) c = '?';
    
    // 获取字体数据
    const uint8_t *font_data = ascii_font_8x16[c - 32];
    
    // 设置显示窗口
    ili9341_set_window(x, y, x + 7, y + 15);
    
    // 绘制字符
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint8_t row = 0; row < 16; row++) {
            uint8_t row_data = font_data[row];
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (row_data & (0x80 >> col)) ? color : bg_color;
                spi_transfer(pixel_color >> 8);
                spi_transfer(pixel_color & 0xFF);
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint8_t row = 0; row < 16; row++) {
            uint8_t row_data = font_data[row];
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (row_data & (0x80 >> col)) ? color : bg_color;
                set_data_bus_16bit(pixel_color);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
        }
    }
}

// 显示字符串
void ili9341_draw_string_8x16(uint16_t x, uint16_t y, const char *str,
                             uint16_t color, uint16_t bg_color) {
    uint16_t cursor_x = x;
    uint16_t cursor_y = y;
    
    while (*str) {
        // 处理换行
        if (*str == '\n') {
            cursor_x = x;
            cursor_y += 16;
            str++;
            continue;
        }
        
        // 处理回车
        if (*str == '\r') {
            cursor_x = x;
            str++;
            continue;
        }
        
        // 检查边界
        if (cursor_x + 8 > display_width) {
            cursor_x = x;
            cursor_y += 16;
        }
        
        if (cursor_y + 16 > display_height) {
            break;  // 超出屏幕
        }
        
        // 绘制字符
        ili9341_draw_char_8x16(cursor_x, cursor_y, *str, color, bg_color);
        
        // 移动光标
        cursor_x += 8;
        str++;
    }
}
6.1.2 中文字符显示
// 16x16点阵汉字字模结构
typedef struct {
    uint16_t unicode;           // Unicode编码
    uint8_t bitmap[32];         // 16x16点阵数据(32字节)
} ChineseFont16x16;

// 简单汉字字库(示例)
const ChineseFont16x16 chinese_font[] = {
    {0x4E2D, {  // "中"
        0x00, 0x00, 0x3F, 0xF8, 0x20, 0x08, 0x20, 0x08,
        0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x3F, 0xF8,
        0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08,
        0x20, 0x08, 0x20, 0x08, 0x3F, 0xF8, 0x00, 0x00
    }},
    {0x6587, {  // "文"
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
        0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x7F, 0xFC,
        0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
        0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
    }},
    // ... 更多汉字
};

// 显示16x16汉字
void ili9341_draw_chinese_16x16(uint16_t x, uint16_t y, uint16_t unicode,
                               uint16_t color, uint16_t bg_color) {
    // 查找字模
    const uint8_t *bitmap = NULL;
    for (uint32_t i = 0; i < sizeof(chinese_font)/sizeof(ChineseFont16x16); i++) {
        if (chinese_font[i].unicode == unicode) {
            bitmap = chinese_font[i].bitmap;
            break;
        }
    }
    
    if (!bitmap) {
        // 未找到字模,显示方框
        ili9341_draw_rect(x, y, 16, 16, color);
        return;
    }
    
    // 设置显示窗口
    ili9341_set_window(x, y, x + 15, y + 15);
    
    // 绘制汉字
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint8_t row = 0; row < 16; row++) {
            uint8_t high_byte = bitmap[row * 2];
            uint8_t low_byte = bitmap[row * 2 + 1];
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (high_byte & (0x80 >> col)) ? color : bg_color;
                spi_transfer(pixel_color >> 8);
                spi_transfer(pixel_color & 0xFF);
            }
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (low_byte & (0x80 >> col)) ? color : bg_color;
                spi_transfer(pixel_color >> 8);
                spi_transfer(pixel_color & 0xFF);
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint8_t row = 0; row < 16; row++) {
            uint8_t high_byte = bitmap[row * 2];
            uint8_t low_byte = bitmap[row * 2 + 1];
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (high_byte & (0x80 >> col)) ? color : bg_color;
                set_data_bus_16bit(pixel_color);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
            
            for (uint8_t col = 0; col < 8; col++) {
                uint16_t pixel_color = (low_byte & (0x80 >> col)) ? color : bg_color;
                set_data_bus_16bit(pixel_color);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
        }
    }
}

6.2 字体引擎设计

6.2.1 字体数据结构
// 字体描述结构
typedef struct {
    uint8_t width;           // 字符宽度
    uint8_t height;          // 字符高度
    uint8_t first_char;      // 第一个字符编码
    uint8_t last_char;       // 最后一个字符编码
    const uint8_t *bitmaps;  // 位图数据
    const uint16_t *offsets; // 字符偏移表
} FontDef;

// 8x16字体示例
const uint8_t font_8x16_bitmaps[] = {
    // 字符位图数据
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 空格
    
    0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18,
    0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // !
    
    // ... 更多字符
};

const uint16_t font_8x16_offsets[] = {
    0,   // 空格
    16,  // !
    // ... 更多偏移
};

FontDef font_8x16 = {
    .width = 8,
    .height = 16,
    .first_char = 32,
    .last_char = 126,
    .bitmaps = font_8x16_bitmaps,
    .offsets = font_8x16_offsets
};

// 通用字符显示函数
void ili9341_draw_char(uint16_t x, uint16_t y, char c, 
                      FontDef *font, uint16_t color, uint16_t bg_color) {
    // 边界检查
    if (c < font->first_char || c > font->last_char) {
        c = '?';  // 显示问号
    }
    
    // 计算位图偏移
    uint32_t char_index = c - font->first_char;
    uint32_t bitmap_offset = font->offsets[char_index];
    const uint8_t *char_bitmap = &font->bitmaps[bitmap_offset];
    
    // 计算每行字节数
    uint8_t bytes_per_row = (font->width + 7) / 8;
    
    // 设置显示窗口
    ili9341_set_window(x, y, x + font->width - 1, y + font->height - 1);
    
    // 绘制字符
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint8_t row = 0; row < font->height; row++) {
            for (uint8_t col_byte = 0; col_byte < bytes_per_row; col_byte++) {
                uint8_t byte_data = char_bitmap[row * bytes_per_row + col_byte];
                
                for (uint8_t bit = 0; bit < 8; bit++) {
                    if (col_byte * 8 + bit >= font->width) break;
                    
                    uint16_t pixel_color = (byte_data & (0x80 >> bit)) ? color : bg_color;
                    spi_transfer(pixel_color >> 8);
                    spi_transfer(pixel_color & 0xFF);
                }
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint8_t row = 0; row < font->height; row++) {
            for (uint8_t col_byte = 0; col_byte < bytes_per_row; col_byte++) {
                uint8_t byte_data = char_bitmap[row * bytes_per_row + col_byte];
                
                for (uint8_t bit = 0; bit < 8; bit++) {
                    if (col_byte * 8 + bit >= font->width) break;
                    
                    uint16_t pixel_color = (byte_data & (0x80 >> bit)) ? color : bg_color;
                    set_data_bus_16bit(pixel_color);
                    
                    GPIO_WriteLow(WR_PIN);
                    asm("nop");
                    GPIO_WriteHigh(WR_PIN);
                }
            }
        }
    }
}

// 通用字符串显示函数
void ili9341_draw_string(uint16_t x, uint16_t y, const char *str,
                        FontDef *font, uint16_t color, uint16_t bg_color) {
    uint16_t cursor_x = x;
    uint16_t cursor_y = y;
    uint16_t line_height = font->height + 2;  // 行高,包含2像素行间距
    
    while (*str) {
        // 处理换行
        if (*str == '\n') {
            cursor_x = x;
            cursor_y += line_height;
            str++;
            continue;
        }
        
        // 处理回车
        if (*str == '\r') {
            cursor_x = x;
            str++;
            continue;
        }
        
        // 检查边界
        if (cursor_x + font->width > display_width) {
            cursor_x = x;
            cursor_y += line_height;
        }
        
        if (cursor_y + font->height > display_height) {
            break;  // 超出屏幕
        }
        
        // 绘制字符
        ili9341_draw_char(cursor_x, cursor_y, *str, font, color, bg_color);
        
        // 移动光标
        cursor_x += font->width + 1;  // 字符宽度+1像素字间距
        str++;
    }
}
6.2.2 字体文件解析
// BDF字体文件解析
typedef struct {
    uint8_t *bitmap;          // 位图数据
    uint16_t encoding;        // 字符编码
    uint8_t width;           // 字符宽度
    uint8_t height;          // 字符高度
    int8_t x_offset;         // X偏移
    int8_t y_offset;         // Y偏移
    int8_t x_advance;        // X前进宽度
} BDF_Char;

// 解析BDF字体文件
uint8_t parse_bdf_font(const char *filename, BDF_Char *chars, uint32_t max_chars) {
    FILE *file = fopen(filename, "r");
    if (!file) return 0;
    
    char line[256];
    BDF_Char *current_char = NULL;
    uint32_t char_count = 0;
    uint8_t in_bitmap = 0;
    uint8_t bitmap_row = 0;
    
    while (fgets(line, sizeof(line), file)) {
        // 解析ENCODING行
        if (strncmp(line, "ENCODING ", 9) == 0) {
            uint16_t encoding = atoi(line + 9);
            
            if (char_count < max_chars) {
                current_char = &chars[char_count];
                memset(current_char, 0, sizeof(BDF_Char));
                current_char->encoding = encoding;
                char_count++;
            }
        }
        // 解析BBX行
        else if (strncmp(line, "BBX ", 4) == 0) {
            if (current_char) {
                sscanf(line + 4, "%hhu %hhu %hhd %hhd", 
                       &current_char->width,
                       &current_char->height,
                       &current_char->x_offset,
                       &current_char->y_offset);
                
                // 分配位图内存
                uint32_t bitmap_size = ((current_char->width + 7) / 8) * current_char->height;
                current_char->bitmap = (uint8_t *)malloc(bitmap_size);
                memset(current_char->bitmap, 0, bitmap_size);
            }
        }
        // 解析DWIDTH行
        else if (strncmp(line, "DWIDTH ", 7) == 0) {
            if (current_char) {
                int8_t x_advance, y_advance;
                sscanf(line + 7, "%hhd %hhd", &x_advance, &y_advance);
                current_char->x_advance = x_advance;
            }
        }
        // 解析BITMAP开始
        else if (strcmp(line, "BITMAP\n") == 0) {
            in_bitmap = 1;
            bitmap_row = 0;
        }
        // 解析BITMAP结束
        else if (strcmp(line, "ENDCHAR\n") == 0) {
            in_bitmap = 0;
            current_char = NULL;
        }
        // 解析位图数据
        else if (in_bitmap && current_char && current_char->bitmap) {
            if (bitmap_row < current_char->height) {
                uint32_t bytes_per_row = (current_char->width + 7) / 8;
                char *hex_str = strtok(line, " \n");
                
                for (uint32_t i = 0; i < bytes_per_row && hex_str; i++) {
                    uint8_t byte = (uint8_t)strtol(hex_str, NULL, 16);
                    current_char->bitmap[bitmap_row * bytes_per_row + i] = byte;
                    hex_str = strtok(NULL, " \n");
                }
                
                bitmap_row++;
            }
        }
    }
    
    fclose(file);
    return 1;
}

// 使用BDF字体显示字符
void ili9341_draw_bdf_char(uint16_t x, uint16_t y, BDF_Char *ch,
                          uint16_t color, uint16_t bg_color) {
    if (!ch || !ch->bitmap) return;
    
    // 调整坐标(考虑偏移)
    uint16_t draw_x = x + ch->x_offset;
    uint16_t draw_y = y + ch->y_offset;
    
    // 计算每行字节数
    uint8_t bytes_per_row = (ch->width + 7) / 8;
    
    // 设置显示窗口
    ili9341_set_window(draw_x, draw_y, 
                      draw_x + ch->width - 1, 
                      draw_y + ch->height - 1);
    
    // 绘制字符
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint8_t row = 0; row < ch->height; row++) {
            for (uint8_t col_byte = 0; col_byte < bytes_per_row; col_byte++) {
                uint8_t byte_data = ch->bitmap[row * bytes_per_row + col_byte];
                
                for (uint8_t bit = 0; bit < 8; bit++) {
                    if (col_byte * 8 + bit >= ch->width) break;
                    
                    uint16_t pixel_color = (byte_data & (0x80 >> bit)) ? color : bg_color;
                    spi_transfer(pixel_color >> 8);
                    spi_transfer(pixel_color & 0xFF);
                }
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint8_t row = 0; row < ch->height; row++) {
            for (uint8_t col_byte = 0; col_byte < bytes_per_row; col_byte++) {
                uint8_t byte_data = ch->bitmap[row * bytes_per_row + col_byte];
                
                for (uint8_t bit = 0; bit < 8; bit++) {
                    if (col_byte * 8 + bit >= ch->width) break;
                    
                    uint16_t pixel_color = (byte_data & (0x80 >> bit)) ? color : bg_color;
                    set_data_bus_16bit(pixel_color);
                    
                    GPIO_WriteLow(WR_PIN);
                    asm("nop");
                    GPIO_WriteHigh(WR_PIN);
                }
            }
        }
    }
}

第七章:图像显示与处理

7.1 图像数据格式

7.1.1 常见图像格式
// 图像格式定义
typedef enum {
    IMAGE_FORMAT_RAW_565,     // RGB565原始数据
    IMAGE_FORMAT_RAW_888,     // RGB888原始数据
    IMAGE_FORMAT_BMP,         // BMP文件格式
    IMAGE_FORMAT_JPEG,        // JPEG文件格式
    IMAGE_FORMAT_PNG          // PNG文件格式
} ImageFormat;

// 图像信息结构
typedef struct {
    uint16_t width;           // 图像宽度
    uint16_t height;          // 图像高度
    uint16_t x_offset;        // X偏移
    uint16_t y_offset;        // Y偏移
    ImageFormat format;       // 图像格式
    uint32_t data_size;       // 数据大小
    const uint8_t *data;      // 图像数据指针
} ImageInfo;

// RGB565图像显示
void ili9341_draw_image_rgb565(uint16_t x, uint16_t y, 
                              uint16_t width, uint16_t height,
                              const uint16_t *image_data) {
    // 边界检查
    if (x >= display_width || y >= display_height) return;
    
    // 计算实际显示区域
    uint16_t x_end = x + width - 1;
    uint16_t y_end = y + height - 1;
    
    if (x_end >= display_width) x_end = display_width - 1;
    if (y_end >= display_height) y_end = display_height - 1;
    
    // 计算实际显示尺寸
    uint16_t display_width_actual = x_end - x + 1;
    uint16_t display_height_actual = y_end - y + 1;
    
    // 设置显示窗口
    ili9341_set_window(x, y, x_end, y_end);
    
    // 显示图像
    uint32_t pixel_count = display_width_actual * display_height_actual;
    
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        // 逐行显示,支持部分显示
        for (uint16_t row = 0; row < display_height_actual; row++) {
            const uint16_t *row_data = &image_data[row * width];
            
            for (uint16_t col = 0; col < display_width_actual; col++) {
                uint16_t pixel = row_data[col];
                spi_transfer(pixel >> 8);
                spi_transfer(pixel & 0xFF);
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint16_t row = 0; row < display_height_actual; row++) {
            const uint16_t *row_data = &image_data[row * width];
            
            for (uint16_t col = 0; col < display_width_actual; col++) {
                set_data_bus_16bit(row_data[col]);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
        }
    }
}

// RGB888图像显示(转换为RGB565)
void ili9341_draw_image_rgb888(uint16_t x, uint16_t y,
                              uint16_t width, uint16_t height,
                              const uint8_t *image_data) {
    // 边界检查
    if (x >= display_width || y >= display_height) return;
    
    // 计算实际显示区域
    uint16_t x_end = x + width - 1;
    uint16_t y_end = y + height - 1;
    
    if (x_end >= display_width) x_end = display_width - 1;
    if (y_end >= display_height) y_end = display_height - 1;
    
    // 计算实际显示尺寸
    uint16_t display_width_actual = x_end - x + 1;
    uint16_t display_height_actual = y_end - y + 1;
    
    // 设置显示窗口
    ili9341_set_window(x, y, x_end, y_end);
    
    // 显示图像
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint16_t row = 0; row < display_height_actual; row++) {
            const uint8_t *row_data = &image_data[row * width * 3];
            
            for (uint16_t col = 0; col < display_width_actual; col++) {
                uint8_t r = row_data[col * 3];
                uint8_t g = row_data[col * 3 + 1];
                uint8_t b = row_data[col * 3 + 2];
                
                // 转换为RGB565
                uint16_t pixel = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
                
                spi_transfer(pixel >> 8);
                spi_transfer(pixel & 0xFF);
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint16_t row = 0; row < display_height_actual; row++) {
            const uint8_t *row_data = &image_data[row * width * 3];
            
            for (uint16_t col = 0; col < display_width_actual; col++) {
                uint8_t r = row_data[col * 3];
                uint8_t g = row_data[col * 3 + 1];
                uint8_t b = row_data[col * 3 + 2];
                
                // 转换为RGB565
                uint16_t pixel = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
                
                set_data_bus_16bit(pixel);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
        }
    }
}
7.1.2 BMP文件解析
// BMP文件头结构
#pragma pack(push, 1)
typedef struct {
    uint16_t type;              // 文件类型,"BM"
    uint32_t size;              // 文件大小
    uint16_t reserved1;         // 保留
    uint16_t reserved2;         // 保留
    uint32_t offset;            // 像素数据偏移
} BMPFileHeader;

typedef struct {
    uint32_t size;              // 信息头大小
    int32_t width;              // 图像宽度
    int32_t height;             // 图像高度
    uint16_t planes;            // 位面数,必须为1
    uint16_t bits_per_pixel;    // 每像素位数
    uint32_t compression;       // 压缩类型
    uint32_t image_size;        // 图像数据大小
    int32_t x_pixels_per_meter; // 水平分辨率
    int32_t y_pixels_per_meter; // 垂直分辨率
    uint32_t colors_used;       // 使用的颜色数
    uint32_t colors_important;  // 重要颜色数
} BMPInfoHeader;
#pragma pack(pop)

// 显示BMP图像
uint8_t ili9341_draw_bmp(uint16_t x, uint16_t y, const uint8_t *bmp_data) {
    const BMPFileHeader *file_header = (const BMPFileHeader *)bmp_data;
    const BMPInfoHeader *info_header = (const BMPInfoHeader *)(bmp_data + sizeof(BMPFileHeader));
    
    // 检查BMP文件格式
    if (file_header->type != 0x4D42) {  // "BM"
        return 0;  // 不是有效的BMP文件
    }
    
    // 检查位深度
    if (info_header->bits_per_pixel != 24 && info_header->bits_per_pixel != 16) {
        return 0;  // 不支持的位深度
    }
    
    // 获取像素数据指针
    const uint8_t *pixel_data = bmp_data + file_header->offset;
    
    // 计算每行字节数(包含填充)
    uint32_t row_size = ((info_header->width * info_header->bits_per_pixel + 31) / 32) * 4;
    
    // 显示图像
    if (info_header->bits_per_pixel == 24) {
        // 24位BMP
        for (int32_t row = 0; row < info_header->height; row++) {
            // BMP是倒置存储的,从最后一行开始
            int32_t src_row = info_header->height - 1 - row;
            const uint8_t *src = pixel_data + src_row * row_size;
            
            for (int32_t col = 0; col < info_header->width; col++) {
                uint8_t b = src[col * 3];
                uint8_t g = src[col * 3 + 1];
                uint8_t r = src[col * 3 + 2];
                
                // 绘制像素
                uint16_t color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
                ili9341_draw_pixel(x + col, y + row, color);
            }
        }
    } else if (info_header->bits_per_pixel == 16) {
        // 16位BMP(通常为RGB565)
        for (int32_t row = 0; row < info_header->height; row++) {
            int32_t src_row = info_header->height - 1 - row;
            const uint16_t *src = (const uint16_t *)(pixel_data + src_row * row_size);
            
            for (int32_t col = 0; col < info_header->width; col++) {
                ili9341_draw_pixel(x + col, y + row, src[col]);
            }
        }
    }
    
    return 1;
}

7.2 图像处理算法

7.2.1 图像缩放
// 最近邻插值缩放
void ili9341_scale_image_nearest(uint16_t src_width, uint16_t src_height,
                                const uint16_t *src_data,
                                uint16_t dst_width, uint16_t dst_height,
                                uint16_t *dst_data) {
    float x_ratio = (float)src_width / dst_width;
    float y_ratio = (float)src_height / dst_height;
    
    for (uint16_t y = 0; y < dst_height; y++) {
        uint16_t src_y = (uint16_t)(y * y_ratio);
        
        for (uint16_t x = 0; x < dst_width; x++) {
            uint16_t src_x = (uint16_t)(x * x_ratio);
            
            dst_data[y * dst_width + x] = src_data[src_y * src_width + src_x];
        }
    }
}

// 双线性插值缩放
void ili9341_scale_image_bilinear(uint16_t src_width, uint16_t src_height,
                                 const uint16_t *src_data,
                                 uint16_t dst_width, uint16_t dst_height,
                                 uint16_t *dst_data) {
    float x_ratio = ((float)(src_width - 1)) / dst_width;
    float y_ratio = ((float)(src_height - 1)) / dst_height;
    
    for (uint16_t y = 0; y < dst_height; y++) {
        float src_y = y * y_ratio;
        uint16_t y1 = (uint16_t)src_y;
        uint16_t y2 = (y1 == src_height - 1) ? y1 : y1 + 1;
        float dy = src_y - y1;
        
        for (uint16_t x = 0; x < dst_width; x++) {
            float src_x = x * x_ratio;
            uint16_t x1 = (uint16_t)src_x;
            uint16_t x2 = (x1 == src_width - 1) ? x1 : x1 + 1;
            float dx = src_x - x1;
            
            // 获取四个相邻像素
            uint16_t c11 = src_data[y1 * src_width + x1];
            uint16_t c12 = src_data[y1 * src_width + x2];
            uint16_t c21 = src_data[y2 * src_width + x1];
            uint16_t c22 = src_data[y2 * src_width + x2];
            
            // 提取RGB分量
            uint8_t r11 = (c11 >> 11) & 0x1F;
            uint8_t g11 = (c11 >> 5) & 0x3F;
            uint8_t b11 = c11 & 0x1F;
            
            uint8_t r12 = (c12 >> 11) & 0x1F;
            uint8_t g12 = (c12 >> 5) & 0x3F;
            uint8_t b12 = c12 & 0x1F;
            
            uint8_t r21 = (c21 >> 11) & 0x1F;
            uint8_t g21 = (c21 >> 5) & 0x3F;
            uint8_t b21 = c21 & 0x1F;
            
            uint8_t r22 = (c22 >> 11) & 0x1F;
            uint8_t g22 = (c22 >> 5) & 0x3F;
            uint8_t b22 = c22 & 0x1F;
            
            // 双线性插值
            float r = (1 - dx) * (1 - dy) * r11 + dx * (1 - dy) * r12 +
                     (1 - dx) * dy * r21 + dx * dy * r22;
            
            float g = (1 - dx) * (1 - dy) * g11 + dx * (1 - dy) * g12 +
                     (1 - dx) * dy * g21 + dx * dy * g22;
            
            float b = (1 - dx) * (1 - dy) * b11 + dx * (1 - dy) * b12 +
                     (1 - dx) * dy * b21 + dx * dy * b22;
            
            // 组合为RGB565
            uint8_t r_int = (uint8_t)(r + 0.5);
            uint8_t g_int = (uint8_t)(g + 0.5);
            uint8_t b_int = (uint8_t)(b + 0.5);
            
            dst_data[y * dst_width + x] = 
                ((r_int & 0x1F) << 11) | ((g_int & 0x3F) << 5) | (b_int & 0x1F);
        }
    }
}
7.2.2 图像旋转
// 图像旋转(最近邻插值)
void ili9341_rotate_image_nearest(uint16_t width, uint16_t height,
                                 const uint16_t *src_data,
                                 float angle,
                                 uint16_t *dst_data) {
    // 计算旋转中心
    float center_x = (float)width / 2.0f;
    float center_y = (float)height / 2.0f;
    
    // 计算旋转矩阵
    float cos_a = cos(angle);
    float sin_a = sin(angle);
    
    // 计算旋转后图像边界
    float min_x = FLT_MAX, max_x = -FLT_MAX;
    float min_y = FLT_MAX, max_y = -FLT_MAX;
    
    // 四个角点
    float corners[4][2] = {
        {0, 0},
        {width, 0},
        {width, height},
        {0, height}
    };
    
    for (int i = 0; i < 4; i++) {
        float x = corners[i][0] - center_x;
        float y = corners[i][1] - center_y;
        
        float rot_x = x * cos_a - y * sin_a;
        float rot_y = x * sin_a + y * cos_a;
        
        min_x = fmin(min_x, rot_x);
        max_x = fmax(max_x, rot_x);
        min_y = fmin(min_y, rot_y);
        max_y = fmax(max_y, rot_y);
    }
    
    // 旋转后图像尺寸
    uint16_t rot_width = (uint16_t)(max_x - min_x + 0.5f);
    uint16_t rot_height = (uint16_t)(max_y - min_y + 0.5f);
    
    // 旋转图像
    for (uint16_t y = 0; y < rot_height; y++) {
        for (uint16_t x = 0; x < rot_width; x++) {
            // 计算在原图像中的坐标
            float src_x = (x + min_x) + center_x;
            float src_y = (y + min_y) + center_y;
            
            // 逆旋转
            float dx = src_x - center_x;
            float dy = src_y - center_y;
            
            float orig_x = dx * cos_a + dy * sin_a + center_x;
            float orig_y = -dx * sin_a + dy * cos_a + center_y;
            
            // 边界检查
            if (orig_x >= 0 && orig_x < width && orig_y >= 0 && orig_y < height) {
                uint16_t src_idx = ((uint16_t)orig_y) * width + (uint16_t)orig_x;
                dst_data[y * rot_width + x] = src_data[src_idx];
            } else {
                dst_data[y * rot_width + x] = 0;  // 透明或黑色
            }
        }
    }
}
7.2.3 图像特效
// 图像灰度化
void ili9341_grayscale_image(uint16_t width, uint16_t height,
                            const uint16_t *src_data,
                            uint16_t *dst_data) {
    for (uint32_t i = 0; i < width * height; i++) {
        uint16_t pixel = src_data[i];
        
        // 提取RGB分量
        uint8_t r = (pixel >> 11) & 0x1F;
        uint8_t g = (pixel >> 5) & 0x3F;
        uint8_t b = pixel & 0x1F;
        
        // 转换为灰度(使用亮度公式)
        float gray = 0.299f * (r / 31.0f) + 0.587f * (g / 63.0f) + 0.114f * (b / 31.0f);
        uint8_t gray_int = (uint8_t)(gray * 31.0f + 0.5f);
        
        // 组合为灰度RGB565
        dst_data[i] = (gray_int << 11) | (gray_int << 6) | gray_int;
    }
}

// 图像二值化
void ili9341_binarize_image(uint16_t width, uint16_t height,
                           const uint16_t *src_data,
                           uint16_t *dst_data,
                           uint8_t threshold) {
    for (uint32_t i = 0; i < width * height; i++) {
        uint16_t pixel = src_data[i];
        
        // 提取RGB分量
        uint8_t r = (pixel >> 11) & 0x1F;
        uint8_t g = (pixel >> 5) & 0x3F;
        uint8_t b = pixel & 0x1F;
        
        // 计算亮度
        float brightness = 0.299f * (r / 31.0f) + 0.587f * (g / 63.0f) + 0.114f * (b / 31.0f);
        
        // 二值化
        uint16_t bw_pixel = (brightness * 255 > threshold) ? 0xFFFF : 0x0000;
        dst_data[i] = bw_pixel;
    }
}

// 图像反色
void ili9341_invert_image(uint16_t width, uint16_t height,
                         const uint16_t *src_data,
                         uint16_t *dst_data) {
    for (uint32_t i = 0; i < width * height; i++) {
        uint16_t pixel = src_data[i];
        
        // 反色
        dst_data[i] = ~pixel;
    }
}

第八章:高级功能与优化

8.1 DMA传输优化

8.1.1 SPI DMA传输
// SPI DMA配置
typedef struct {
    SPI_HandleTypeDef *hspi;      // SPI句柄
    DMA_HandleTypeDef *hdma_tx;   // DMA发送句柄
    uint8_t *tx_buffer;           // 发送缓冲区
    uint32_t buffer_size;         // 缓冲区大小
    volatile uint8_t transfer_complete;  // 传输完成标志
} SPI_DMA_Config;

// 初始化SPI DMA
uint8_t spi_dma_init(SPI_DMA_Config *config, 
                     SPI_HandleTypeDef *hspi,
                     DMA_HandleTypeDef *hdma_tx,
                     uint32_t buffer_size) {
    config->hspi = hspi;
    config->hdma_tx = hdma_tx;
    config->buffer_size = buffer_size;
    config->transfer_complete = 1;
    
    // 分配缓冲区
    config->tx_buffer = (uint8_t *)malloc(buffer_size);
    if (!config->tx_buffer) return 0;
    
    return 1;
}

// 使用DMA传输图像数据
void ili9341_dma_draw_image(uint16_t x, uint16_t y,
                           uint16_t width, uint16_t height,
                           const uint16_t *image_data,
                           SPI_DMA_Config *dma_config) {
    // 等待上一次传输完成
    while (!dma_config->transfer_complete);
    
    // 设置显示窗口
    ili9341_set_window(x, y, x + width - 1, y + height - 1);
    
    // 准备数据
    uint32_t pixel_count = width * height;
    uint8_t *tx_buffer = dma_config->tx_buffer;
    
    // 将16位像素数据转换为8位字节流
    for (uint32_t i = 0; i < pixel_count; i++) {
        tx_buffer[i * 2] = image_data[i] >> 8;
        tx_buffer[i * 2 + 1] = image_data[i] & 0xFF;
    }
    
    // 启动DMA传输
    dma_config->transfer_complete = 0;
    
    // 拉高DC引脚(数据)
    GPIO_WriteHigh(DC_PIN);
    
    // 拉低CS引脚
    GPIO_WriteLow(CS_PIN);
    
    // 启动SPI DMA传输
    HAL_SPI_Transmit_DMA(dma_config->hspi, tx_buffer, pixel_count * 2);
}

// DMA传输完成回调
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
    // 传输完成,拉高CS引脚
    GPIO_WriteHigh(CS_PIN);
    
    // 设置传输完成标志
    // 这里需要根据实际配置找到对应的SPI_DMA_Config
    // dma_config->transfer_complete = 1;
}
8.1.2 8080并行接口DMA
// FSMC(Flexible Static Memory Controller)配置
// 适用于STM32系列MCU

// FSMC初始化
void fsmc_init(void) {
    FSMC_NORSRAM_TimingTypeDef Timing = {0};
    FSMC_NORSRAM_InitTypeDef Init = {0};
    
    // 使能FSMC时钟
    __HAL_RCC_FSMC_CLK_ENABLE();
    
    // 配置时序参数
    Timing.AddressSetupTime = 1;
    Timing.AddressHoldTime = 0;
    Timing.DataSetupTime = 6;
    Timing.BusTurnAroundDuration = 0;
    Timing.CLKDivision = 0;
    Timing.DataLatency = 0;
    Timing.AccessMode = FSMC_ACCESS_MODE_A;
    
    // 初始化FSMC
    Init.NSBank = FSMC_NORSRAM_BANK1;
    Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
    Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
    Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
    Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
    Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
    Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
    Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
    Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
    Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
    Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
    Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
    Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
    Init.PageSize = FSMC_PAGE_SIZE_NONE;
    
    // 应用配置
    HAL_FSMC_NORSRAM_Init(&Init, &Timing);
}

// 使用FSMC DMA传输
void ili9341_fsmc_dma_draw_image(uint16_t x, uint16_t y,
                                uint16_t width, uint16_t height,
                                const uint16_t *image_data) {
    // 设置显示窗口
    ili9341_set_window(x, y, x + width - 1, y + height - 1);
    
    // 启动DMA传输
    // 这里假设ILI9341的数据寄存器映射到0x60020000
    // 命令寄存器映射到0x60000000
    uint32_t pixel_count = width * height;
    
    // 配置DMA
    DMA_HandleTypeDef hdma_memtomem;
    
    hdma_memtomem.Instance = DMA2_Stream0;
    hdma_memtomem.Init.Channel = DMA_CHANNEL_0;
    hdma_memtomem.Init.Direction = DMA_MEMORY_TO_MEMORY;
    hdma_memtomem.Init.PeriphInc = DMA_PINC_ENABLE;
    hdma_memtomem.Init.MemInc = DMA_MINC_ENABLE;
    hdma_memtomem.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_memtomem.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_memtomem.Init.Mode = DMA_NORMAL;
    hdma_memtomem.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_memtomem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_memtomem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_memtomem.Init.MemBurst = DMA_MBURST_INC4;
    hdma_memtomem.Init.PeriphBurst = DMA_PBURST_INC4;
    
    HAL_DMA_Init(&hdma_memtomem);
    
    // 启动DMA传输
    HAL_DMA_Start(&hdma_memtomem, 
                  (uint32_t)image_data, 
                  (uint32_t)(0x60020000), // ILI9341数据寄存器地址
                  pixel_count);
    
    // 等待传输完成
    HAL_DMA_PollForTransfer(&hdma_memtomem, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
}

8.2 双缓冲与页面翻转

8.2.1 软件双缓冲实现
// 双缓冲管理结构
typedef struct {
    uint16_t *front_buffer;   // 前缓冲区(显示)
    uint16_t *back_buffer;    // 后缓冲区(绘制)
    uint32_t buffer_size;     // 缓冲区大小(字节)
    uint8_t buffer_index;     // 当前缓冲区索引
} DoubleBuffer;

// 初始化双缓冲
uint8_t double_buffer_init(DoubleBuffer *db, uint16_t width, uint16_t height) {
    db->buffer_size = width * height * sizeof(uint16_t);
    
    // 分配前后缓冲区
    db->front_buffer = (uint16_t *)malloc(db->buffer_size);
    db->back_buffer = (uint16_t *)malloc(db->buffer_size);
    
    if (!db->front_buffer || !db->back_buffer) {
        free(db->front_buffer);
        free(db->back_buffer);
        return 0;
    }
    
    db->buffer_index = 0;
    
    // 清空缓冲区
    memset(db->front_buffer, 0, db->buffer_size);
    memset(db->back_buffer, 0, db->buffer_size);
    
    return 1;
}

// 交换缓冲区
void double_buffer_swap(DoubleBuffer *db) {
    // 交换缓冲区指针
    uint16_t *temp = db->front_buffer;
    db->front_buffer = db->back_buffer;
    db->back_buffer = temp;
    
    // 更新缓冲区索引
    db->buffer_index ^= 1;
}

// 获取当前绘制缓冲区
uint16_t *double_buffer_get_draw_buffer(DoubleBuffer *db) {
    return db->back_buffer;
}

// 获取当前显示缓冲区
uint16_t *double_buffer_get_display_buffer(DoubleBuffer *db) {
    return db->front_buffer;
}

// 更新显示
void double_buffer_update_display(DoubleBuffer *db) {
    // 将后缓冲区内容复制到显示屏
    ili9341_draw_image_rgb565(0, 0, 
                             DISPLAY_WIDTH, DISPLAY_HEIGHT,
                             db->back_buffer);
}

// 双缓冲绘图示例
void double_buffer_demo(DoubleBuffer *db) {
    static uint16_t x = 0;
    static uint16_t y = 0;
    static int8_t dx = 2;
    static int8_t dy = 2;
    
    // 获取当前绘制缓冲区
    uint16_t *draw_buffer = double_buffer_get_draw_buffer(db);
    
    // 清空绘制缓冲区
    memset(draw_buffer, 0, db->buffer_size);
    
    // 在绘制缓冲区上绘制内容
    // 绘制移动的矩形
    for (uint16_t i = 0; i < 20; i++) {
        for (uint16_t j = 0; j < 20; j++) {
            draw_buffer[(y + i) * DISPLAY_WIDTH + (x + j)] = COLOR_RED;
        }
    }
    
    // 更新位置
    x += dx;
    y += dy;
    
    // 边界检查
    if (x <= 0 || x >= DISPLAY_WIDTH - 20) dx = -dx;
    if (y <= 0 || y >= DISPLAY_HEIGHT - 20) dy = -dy;
    
    // 交换缓冲区
    double_buffer_swap(db);
    
    // 更新显示
    double_buffer_update_display(db);
}
8.2.2 硬件页面翻转
// ILI9341支持的部分页面地址设置
void ili9341_set_partial_display(uint16_t start_row, uint16_t end_row) {
    // 设置部分显示区域
    ili9341_write_command(0x33);  // Partial Area
    ili9341_write_data(start_row >> 8);
    ili9341_write_data(start_row & 0xFF);
    ili9341_write_data(end_row >> 8);
    ili9341_write_data(end_row & 0xFF);
    
    // 启用部分显示模式
    ili9341_write_command(0x37);  // Scan Direction
    // 根据需要设置扫描方向
}

// 页面翻转实现
typedef struct {
    uint16_t page_height;      // 页面高度
    uint16_t current_page;     // 当前页面
    uint16_t total_pages;      // 总页面数
    uint16_t *page_buffers[2]; // 页面缓冲区
} PageFlipBuffer;

// 初始化页面翻转
uint8_t page_flip_init(PageFlipBuffer *pfb, 
                      uint16_t width, uint16_t page_height) {
    pfb->page_height = page_height;
    pfb->current_page = 0;
    pfb->total_pages = (DISPLAY_HEIGHT + page_height - 1) / page_height;
    
    // 分配页面缓冲区
    for (int i = 0; i < 2; i++) {
        pfb->page_buffers[i] = (uint16_t *)malloc(width * page_height * sizeof(uint16_t));
        if (!pfb->page_buffers[i]) {
            // 清理已分配的内存
            for (int j = 0; j < i; j++) {
                free(pfb->page_buffers[j]);
            }
            return 0;
        }
    }
    
    return 1;
}

// 页面翻转
void page_flip(PageFlipBuffer *pfb) {
    // 计算当前显示页面
    uint16_t display_page = pfb->current_page;
    uint16_t draw_page = (pfb->current_page + 1) % 2;
    
    // 更新当前页面
    pfb->current_page = draw_page;
    
    // 设置显示区域为当前页面
    uint16_t start_row = display_page * pfb->page_height;
    uint16_t end_row = start_row + pfb->page_height - 1;
    
    if (end_row >= DISPLAY_HEIGHT) {
        end_row = DISPLAY_HEIGHT - 1;
    }
    
    // 显示当前页面
    ili9341_set_partial_display(start_row, end_row);
    ili9341_draw_image_rgb565(0, start_row, 
                             DISPLAY_WIDTH, pfb->page_height,
                             pfb->page_buffers[display_page]);
}

// 获取当前绘制页面缓冲区
uint16_t *page_flip_get_draw_buffer(PageFlipBuffer *pfb) {
    uint16_t draw_page = (pfb->current_page + 1) % 2;
    return pfb->page_buffers[draw_page];
}

8.3 触摸屏集成

8.3.1 电阻式触摸屏驱动
// 触摸屏控制器(例如XPT2046)驱动

// 触摸屏校准点
typedef struct {
    uint16_t lcd_x;    // LCD坐标
    uint16_t lcd_y;
    uint16_t touch_x;  // 触摸原始坐标
    uint16_t touch_y;
} CalibrationPoint;

// 触摸屏校准数据
typedef struct {
    CalibrationPoint points[4];  // 4点校准
    float a;  // 校准参数
    float b;
    float c;
    float d;
    float e;
    float f;
} TouchCalibration;

// 初始化触摸屏
void touch_init(void) {
    // 初始化SPI接口
    spi_init(TOUCH_SPI, TOUCH_SPI_FREQ);
    
    // 配置触摸屏引脚
    gpio_set_mode(TOUCH_CS_PIN, GPIO_MODE_OUTPUT);
    gpio_set_mode(TOUCH_IRQ_PIN, GPIO_MODE_INPUT);
    
    gpio_write(TOUCH_CS_PIN, 1);  // 禁用触摸屏
}

// 读取触摸位置
uint8_t touch_read_raw(uint16_t *x, uint16_t *y) {
    uint8_t touch_pressed = 0;
    
    // 检查触摸(IRQ引脚为低表示触摸)
    if (gpio_read(TOUCH_IRQ_PIN) == 0) {
        // 选择触摸屏
        gpio_write(TOUCH_CS_PIN, 0);
        
        // 发送读取X坐标命令
        uint8_t cmd_x = 0x90;  // 通道Y+
        spi_transfer(TOUCH_SPI, cmd_x);
        
        // 读取X坐标(12位)
        uint16_t raw_x = spi_transfer(TOUCH_SPI, 0x00) << 8;
        raw_x |= spi_transfer(TOUCH_SPI, 0x00);
        raw_x >>= 4;
        
        // 发送读取Y坐标命令
        uint8_t cmd_y = 0xD0;  // 通道X+
        spi_transfer(TOUCH_SPI, cmd_y);
        
        // 读取Y坐标(12位)
        uint16_t raw_y = spi_transfer(TOUCH_SPI, 0x00) << 8;
        raw_y |= spi_transfer(TOUCH_SPI, 0x00);
        raw_y >>= 4;
        
        // 取消选择触摸屏
        gpio_write(TOUCH_CS_PIN, 1);
        
        // 返回原始坐标
        *x = raw_x;
        *y = raw_y;
        
        touch_pressed = 1;
    }
    
    return touch_pressed;
}

// 触摸屏校准
void touch_calibrate(TouchCalibration *cal) {
    // 定义校准点(屏幕四个角)
    cal->points[0].lcd_x = 30;
    cal->points[0].lcd_y = 30;
    
    cal->points[1].lcd_x = DISPLAY_WIDTH - 30;
    cal->points[1].lcd_y = 30;
    
    cal->points[2].lcd_x = DISPLAY_WIDTH - 30;
    cal->points[2].lcd_y = DISPLAY_HEIGHT - 30;
    
    cal->points[3].lcd_x = 30;
    cal->points[3].lcd_y = DISPLAY_HEIGHT - 30;
    
    // 显示校准界面并获取触摸点
    for (int i = 0; i < 4; i++) {
        // 显示校准点
        ili9341_fill_circle(cal->points[i].lcd_x, cal->points[i].lcd_y, 5, COLOR_RED);
        
        // 等待触摸
        uint16_t touch_x, touch_y;
        while (!touch_read_raw(&touch_x, &touch_y));
        
        // 保存触摸点
        cal->points[i].touch_x = touch_x;
        cal->points[i].touch_y = touch_y;
        
        // 短暂延时
        delay_ms(500);
    }
    
    // 计算校准参数(使用最小二乘法)
    // 这里简化处理,实际需要实现完整的校准算法
    // ...
}

// 坐标转换
void touch_convert_coords(TouchCalibration *cal, 
                         uint16_t touch_x, uint16_t touch_y,
                         uint16_t *lcd_x, uint16_t *lcd_y) {
    // 使用校准参数转换坐标
    *lcd_x = (uint16_t)(cal->a * touch_x + cal->b * touch_y + cal->c);
    *lcd_y = (uint16_t)(cal->d * touch_x + cal->e * touch_y + cal->f);
    
    // 边界检查
    if (*lcd_x >= DISPLAY_WIDTH) *lcd_x = DISPLAY_WIDTH - 1;
    if (*lcd_y >= DISPLAY_HEIGHT) *lcd_y = DISPLAY_HEIGHT - 1;
}

第九章:性能优化技巧

9.1 显示优化策略

9.1.1 局部刷新优化
// 脏矩形优化
typedef struct {
    uint16_t x1;
    uint16_t y1;
    uint16_t x2;
    uint16_t y2;
    uint8_t dirty;  // 脏标志
} DirtyRect;

// 脏矩形管理器
typedef struct {
    DirtyRect rects[MAX_DIRTY_RECTS];  // 最大脏矩形数量
    uint8_t count;                     // 当前脏矩形数量
} DirtyRectManager;

// 标记脏矩形
void dirty_rect_mark(DirtyRectManager *drm, 
                    uint16_t x, uint16_t y,
                    uint16_t width, uint16_t height) {
    // 计算矩形边界
    uint16_t x2 = x + width - 1;
    uint16_t y2 = y + height - 1;
    
    // 边界检查
    if (x2 >= DISPLAY_WIDTH) x2 = DISPLAY_WIDTH - 1;
    if (y2 >= DISPLAY_HEIGHT) y2 = DISPLAY_HEIGHT - 1;
    
    // 查找是否可以合并到现有脏矩形
    for (uint8_t i = 0; i < drm->count; i++) {
        DirtyRect *rect = &drm->rects[i];
        
        // 检查是否重叠或相邻
        if (!(x2 < rect->x1 || x > rect->x2 || y2 < rect->y1 || y > rect->y2)) {
            // 合并矩形
            rect->x1 = MIN(rect->x1, x);
            rect->y1 = MIN(rect->y1, y);
            rect->x2 = MAX(rect->x2, x2);
            rect->y2 = MAX(rect->y2, y2);
            rect->dirty = 1;
            return;
        }
    }
    
    // 添加新的脏矩形
    if (drm->count < MAX_DIRTY_RECTS) {
        DirtyRect *rect = &drm->rects[drm->count++];
        rect->x1 = x;
        rect->y1 = y;
        rect->x2 = x2;
        rect->y2 = y2;
        rect->dirty = 1;
    } else {
        // 达到最大数量,标记整个屏幕为脏
        dirty_rect_mark_all(drm);
    }
}

// 刷新脏矩形
void dirty_rect_flush(DirtyRectManager *drm, uint16_t *framebuffer) {
    for (uint8_t i = 0; i < drm->count; i++) {
        DirtyRect *rect = &drm->rects[i];
        
        if (rect->dirty) {
            // 计算矩形尺寸
            uint16_t width = rect->x2 - rect->x1 + 1;
            uint16_t height = rect->y2 - rect->y1 + 1;
            
            // 从framebuffer中提取矩形区域
            uint16_t *rect_data = (uint16_t *)malloc(width * height * sizeof(uint16_t));
            
            for (uint16_t y = 0; y < height; y++) {
                uint16_t *src = &framebuffer[(rect->y1 + y) * DISPLAY_WIDTH + rect->x1];
                uint16_t *dst = &rect_data[y * width];
                memcpy(dst, src, width * sizeof(uint16_t));
            }
            
            // 显示矩形区域
            ili9341_draw_image_rgb565(rect->x1, rect->y1, width, height, rect_data);
            
            // 释放内存
            free(rect_data);
            
            // 清除脏标志
            rect->dirty = 0;
        }
    }
    
    // 重置脏矩形计数
    drm->count = 0;
}
9.1.2 命令缓冲优化
// 命令缓冲区
typedef struct {
    uint8_t *buffer;      // 缓冲区
    uint32_t size;        // 缓冲区大小
    uint32_t write_pos;   // 写位置
    uint32_t read_pos;    // 读位置
    uint8_t flushing;     // 刷新标志
} CommandBuffer;

// 初始化命令缓冲区
uint8_t command_buffer_init(CommandBuffer *cb, uint32_t size) {
    cb->buffer = (uint8_t *)malloc(size);
    if (!cb->buffer) return 0;
    
    cb->size = size;
    cb->write_pos = 0;
    cb->read_pos = 0;
    cb->flushing = 0;
    
    return 1;
}

// 写入命令到缓冲区
uint8_t command_buffer_write(CommandBuffer *cb, uint8_t cmd, 
                            const uint8_t *data, uint32_t data_len) {
    // 检查缓冲区空间
    uint32_t total_len = 1 + data_len + 2;  // 命令 + 数据 + 长度标记
    
    if (cb->write_pos + total_len > cb->size) {
        return 0;  // 缓冲区满
    }
    
    // 写入命令
    cb->buffer[cb->write_pos++] = cmd;
    
    // 写入数据长度(高字节在前)
    cb->buffer[cb->write_pos++] = (data_len >> 8) & 0xFF;
    cb->buffer[cb->write_pos++] = data_len & 0xFF;
    
    // 写入数据
    if (data_len > 0) {
        memcpy(&cb->buffer[cb->write_pos], data, data_len);
        cb->write_pos += data_len;
    }
    
    return 1;
}

// 刷新命令缓冲区
void command_buffer_flush(CommandBuffer *cb) {
    cb->flushing = 1;
    
    while (cb->read_pos < cb->write_pos) {
        // 读取命令
        uint8_t cmd = cb->buffer[cb->read_pos++];
        
        // 读取数据长度
        uint16_t data_len = (cb->buffer[cb->read_pos++] << 8);
        data_len |= cb->buffer[cb->read_pos++];
        
        // 发送命令
        ili9341_write_command(cmd);
        
        // 发送数据
        if (data_len > 0) {
            for (uint16_t i = 0; i < data_len; i++) {
                ili9341_write_data(cb->buffer[cb->read_pos++]);
            }
        }
    }
    
    // 重置缓冲区
    cb->write_pos = 0;
    cb->read_pos = 0;
    cb->flushing = 0;
}

9.2 内存优化策略

9.2.1 显存管理优化
// 内存池管理
typedef struct {
    uint8_t *memory;           // 内存池
    uint32_t total_size;       // 总大小
    uint32_t used_size;        // 已使用大小
    uint32_t block_count;      // 块数量
    MemoryBlock *blocks;       // 块数组
} MemoryPool;

// 内存块
typedef struct {
    uint32_t offset;           // 偏移量
    uint32_t size;             // 大小
    uint8_t used;              // 使用标志
} MemoryBlock;

// 初始化内存池
uint8_t memory_pool_init(MemoryPool *mp, uint32_t size) {
    mp->memory = (uint8_t *)malloc(size);
    if (!mp->memory) return 0;
    
    mp->total_size = size;
    mp->used_size = 0;
    mp->block_count = 0;
    
    // 初始化块数组(动态分配)
    mp->blocks = NULL;
    
    return 1;
}

// 分配内存
void *memory_pool_alloc(MemoryPool *mp, uint32_t size) {
    // 对齐到4字节边界
    size = (size + 3) & ~3;
    
    // 查找空闲块
    for (uint32_t i = 0; i < mp->block_count; i++) {
        if (!mp->blocks[i].used && mp->blocks[i].size >= size) {
            // 找到合适块
            mp->blocks[i].used = 1;
            return &mp->memory[mp->blocks[i].offset];
        }
    }
    
    // 分配新块
    if (mp->used_size + size <= mp->total_size) {
        // 扩展块数组
        MemoryBlock *new_blocks = realloc(mp->blocks, 
                                         (mp->block_count + 1) * sizeof(MemoryBlock));
        if (!new_blocks) return NULL;
        
        mp->blocks = new_blocks;
        
        // 添加新块
        MemoryBlock *block = &mp->blocks[mp->block_count++];
        block->offset = mp->used_size;
        block->size = size;
        block->used = 1;
        
        mp->used_size += size;
        
        return &mp->memory[block->offset];
    }
    
    return NULL;  // 内存不足
}

// 释放内存
void memory_pool_free(MemoryPool *mp, void *ptr) {
    uint32_t offset = (uint8_t *)ptr - mp->memory;
    
    // 查找对应的块
    for (uint32_t i = 0; i < mp->block_count; i++) {
        if (mp->blocks[i].offset == offset) {
            mp->blocks[i].used = 0;
            return;
        }
    }
}

// 合并空闲块
void memory_pool_compact(MemoryPool *mp) {
    // 按偏移量排序块
    for (uint32_t i = 0; i < mp->block_count - 1; i++) {
        for (uint32_t j = i + 1; j < mp->block_count; j++) {
            if (mp->blocks[i].offset > mp->blocks[j].offset) {
                MemoryBlock temp = mp->blocks[i];
                mp->blocks[i] = mp->blocks[j];
                mp->blocks[j] = temp;
            }
        }
    }
    
    // 合并相邻空闲块
    for (uint32_t i = 0; i < mp->block_count - 1; ) {
        MemoryBlock *curr = &mp->blocks[i];
        MemoryBlock *next = &mp->blocks[i + 1];
        
        if (!curr->used && !next->used) {
            // 合并块
            curr->size += next->size;
            
            // 移除下一个块
            memmove(next, next + 1, 
                   (mp->block_count - i - 2) * sizeof(MemoryBlock));
            mp->block_count--;
        } else {
            i++;
        }
    }
}
9.2.2 图像压缩存储
// RLE(Run-Length Encoding)压缩
typedef struct {
    uint16_t color;
    uint16_t count;
} RLEEntry;

// RLE压缩图像
uint32_t rle_compress(const uint16_t *image_data, uint32_t pixel_count,
                     RLEEntry *output, uint32_t max_entries) {
    if (pixel_count == 0) return 0;
    
    uint16_t current_color = image_data[0];
    uint16_t current_count = 1;
    uint32_t entry_count = 0;
    
    for (uint32_t i = 1; i < pixel_count; i++) {
        if (image_data[i] == current_color && current_count < 65535) {
            current_count++;
        } else {
            // 保存当前运行
            if (entry_count < max_entries) {
                output[entry_count].color = current_color;
                output[entry_count].count = current_count;
                entry_count++;
            }
            
            // 开始新的运行
            current_color = image_data[i];
            current_count = 1;
        }
    }
    
    // 保存最后一个运行
    if (entry_count < max_entries) {
        output[entry_count].color = current_color;
        output[entry_count].count = current_count;
        entry_count++;
    }
    
    return entry_count;
}

// RLE解压显示
void rle_display(uint16_t x, uint16_t y, 
                const RLEEntry *rle_data, uint32_t entry_count) {
    uint32_t total_pixels = 0;
    
    // 计算总像素数
    for (uint32_t i = 0; i < entry_count; i++) {
        total_pixels += rle_data[i].count;
    }
    
    // 计算图像尺寸(假设为矩形)
    uint16_t width = DISPLAY_WIDTH;  // 实际应用中需要知道原始尺寸
    uint16_t height = (total_pixels + width - 1) / width;
    
    // 设置显示窗口
    ili9341_set_window(x, y, x + width - 1, y + height - 1);
    
    // 显示RLE数据
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint32_t i = 0; i < entry_count; i++) {
            uint16_t color = rle_data[i].color;
            uint16_t count = rle_data[i].count;
            
            uint8_t color_high = color >> 8;
            uint8_t color_low = color & 0xFF;
            
            for (uint16_t j = 0; j < count; j++) {
                spi_transfer(color_high);
                spi_transfer(color_low);
            }
        }
        
        GPIO_WriteHigh(CS_PIN);
    } else {
        GPIO_WriteHigh(DC_PIN);
        
        for (uint32_t i = 0; i < entry_count; i++) {
            uint16_t color = rle_data[i].color;
            uint16_t count = rle_data[i].count;
            
            for (uint16_t j = 0; j < count; j++) {
                set_data_bus_16bit(color);
                
                GPIO_WriteLow(WR_PIN);
                asm("nop");
                GPIO_WriteHigh(WR_PIN);
            }
        }
    }
}

第十章:实际项目应用

10.1 嵌入式GUI框架集成

10.1.1 简单GUI框架设计
// GUI控件基类
typedef struct {
    uint16_t x;             // X坐标
    uint16_t y;             // Y坐标
    uint16_t width;         // 宽度
    uint16_t height;        // 高度
    uint16_t bg_color;      // 背景色
    uint16_t fg_color;      // 前景色
    uint8_t visible;        // 可见性
    uint8_t enabled;        // 使能状态
    void (*draw)(void *);   // 绘制函数
    void (*handle_event)(void *, GUIEvent);  // 事件处理函数
} GUIWidget;

// GUI事件
typedef struct {
    uint8_t type;           // 事件类型
    uint16_t x;             // 事件X坐标
    uint16_t y;             // 事件Y坐标
    uint32_t param;         // 事件参数
} GUIEvent;

// 事件类型定义
typedef enum {
    EVENT_NONE,
    EVENT_TOUCH_PRESS,
    EVENT_TOUCH_RELEASE,
    EVENT_TOUCH_MOVE,
    EVENT_TIMER,
    EVENT_CUSTOM
} GUIEventType;

// 按钮控件
typedef struct {
    GUIWidget base;         // 基类
    char *text;             // 按钮文本
    void (*on_click)(void *);  // 点击回调
} GUIButton;

// 按钮绘制函数
void button_draw(void *widget) {
    GUIButton *button = (GUIButton *)widget;
    
    // 绘制按钮背景
    ili9341_fill_rect(button->base.x, button->base.y,
                     button->base.width, button->base.height,
                     button->base.bg_color);
    
    // 绘制按钮边框
    ili9341_draw_rect(button->base.x, button->base.y,
                     button->base.width, button->base.height,
                     button->base.fg_color);
    
    // 计算文本位置(居中)
    uint16_t text_x = button->base.x + (button->base.width - strlen(button->text) * 8) / 2;
    uint16_t text_y = button->base.y + (button->base.height - 16) / 2;
    
    // 绘制按钮文本
    ili9341_draw_string_8x16(text_x, text_y, button->text,
                            button->base.fg_color, button->base.bg_color);
}

// 按钮事件处理
void button_handle_event(void *widget, GUIEvent event) {
    GUIButton *button = (GUIButton *)widget;
    
    if (event.type == EVENT_TOUCH_PRESS) {
        // 检查触摸点是否在按钮内
        if (event.x >= button->base.x && event.x < button->base.x + button->base.width &&
            event.y >= button->base.y && event.y < button->base.y + button->base.height) {
            
            // 调用点击回调
            if (button->on_click) {
                button->on_click(button);
            }
        }
    }
}

// GUI管理器
typedef struct {
    GUIWidget **widgets;     // 控件数组
    uint32_t widget_count;   // 控件数量
    uint32_t widget_capacity; // 控件容量
    GUIWidget *focused;      // 当前焦点控件
} GUIManager;

// 初始化GUI管理器
uint8_t gui_manager_init(GUIManager *manager, uint32_t capacity) {
    manager->widgets = (GUIWidget **)malloc(capacity * sizeof(GUIWidget *));
    if (!manager->widgets) return 0;
    
    manager->widget_count = 0;
    manager->widget_capacity = capacity;
    manager->focused = NULL;
    
    return 1;
}

// 添加控件
uint8_t gui_manager_add_widget(GUIManager *manager, GUIWidget *widget) {
    if (manager->widget_count >= manager->widget_capacity) {
        // 扩展容量
        uint32_t new_capacity = manager->widget_capacity * 2;
        GUIWidget **new_widgets = realloc(manager->widgets, 
                                         new_capacity * sizeof(GUIWidget *));
        if (!new_widgets) return 0;
        
        manager->widgets = new_widgets;
        manager->widget_capacity = new_capacity;
    }
    
    manager->widgets[manager->widget_count++] = widget;
    return 1;
}

// 处理GUI事件
void gui_manager_handle_event(GUIManager *manager, GUIEvent event) {
    for (uint32_t i = 0; i < manager->widget_count; i++) {
        GUIWidget *widget = manager->widgets[i];
        
        if (widget->enabled && widget->handle_event) {
            widget->handle_event(widget, event);
        }
    }
}

// 绘制GUI
void gui_manager_draw(GUIManager *manager) {
    for (uint32_t i = 0; i < manager->widget_count; i++) {
        GUIWidget *widget = manager->widgets[i];
        
        if (widget->visible && widget->draw) {
            widget->draw(widget);
        }
    }
}
10.1.2 页面管理系统
// 页面基类
typedef struct {
    void (*on_create)(void *);      // 创建回调
    void (*on_destroy)(void *);     // 销毁回调
    void (*on_show)(void *);        // 显示回调
    void (*on_hide)(void *);        // 隐藏回调
    void (*on_event)(void *, GUIEvent);  // 事件回调
    GUIManager gui_manager;         // GUI管理器
    void *user_data;                // 用户数据
} GUIPage;

// 页面管理器
typedef struct {
    GUIPage **pages;                // 页面栈
    uint32_t page_count;            // 页面数量
    uint32_t page_capacity;         // 页面容量
    int32_t current_page;           // 当前页面索引
} PageManager;

// 初始化页面管理器
uint8_t page_manager_init(PageManager *pm, uint32_t capacity) {
    pm->pages = (GUIPage **)malloc(capacity * sizeof(GUIPage *));
    if (!pm->pages) return 0;
    
    pm->page_count = 0;
    pm->page_capacity = capacity;
    pm->current_page = -1;
    
    return 1;
}

// 添加页面
uint8_t page_manager_add_page(PageManager *pm, GUIPage *page) {
    if (pm->page_count >= pm->page_capacity) {
        // 扩展容量
        uint32_t new_capacity = pm->page_capacity * 2;
        GUIPage **new_pages = realloc(pm->pages, 
                                     new_capacity * sizeof(GUIPage *));
        if (!new_pages) return 0;
        
        pm->pages = new_pages;
        pm->page_capacity = new_capacity;
    }
    
    pm->pages[pm->page_count++] = page;
    return 1;
}

// 切换页面
void page_manager_switch_page(PageManager *pm, uint32_t page_index) {
    if (page_index >= pm->page_count) return;
    
    // 隐藏当前页面
    if (pm->current_page >= 0) {
        GUIPage *current_page = pm->pages[pm->current_page];
        if (current_page->on_hide) {
            current_page->on_hide(current_page);
        }
    }
    
    // 显示新页面
    pm->current_page = page_index;
    GUIPage *new_page = pm->pages[page_index];
    
    // 清屏
    ili9341_fill_screen(COLOR_BLACK);
    
    // 调用页面显示回调
    if (new_page->on_show) {
        new_page->on_show(new_page);
    }
    
    // 绘制页面GUI
    gui_manager_draw(&new_page->gui_manager);
}

// 页面事件处理
void page_manager_handle_event(PageManager *pm, GUIEvent event) {
    if (pm->current_page >= 0) {
        GUIPage *current_page = pm->pages[pm->current_page];
        
        // 调用页面事件回调
        if (current_page->on_event) {
            current_page->on_event(current_page, event);
        }
        
        // 传递给GUI管理器
        gui_manager_handle_event(&current_page->gui_manager, event);
    }
}

10.2 工业HMI应用

10.2.1 数据可视化
// 图表控件
typedef struct {
    GUIWidget base;                 // 基类
    float *data;                    // 数据数组
    uint32_t data_count;            // 数据数量
    uint32_t data_capacity;         // 数据容量
    uint16_t grid_color;            // 网格颜色
    uint16_t data_color;            // 数据颜色
    float min_value;                // 最小值
    float max_value;                // 最大值
    uint8_t show_grid;              // 显示网格
    uint8_t auto_scale;             // 自动缩放
} ChartWidget;

// 图表绘制函数
void chart_draw(void *widget) {
    ChartWidget *chart = (ChartWidget *)widget;
    
    // 绘制背景
    ili9341_fill_rect(chart->base.x, chart->base.y,
                     chart->base.width, chart->base.height,
                     chart->base.bg_color);
    
    // 绘制边框
    ili9341_draw_rect(chart->base.x, chart->base.y,
                     chart->base.width, chart->base.height,
                     chart->base.fg_color);
    
    // 绘制网格
    if (chart->show_grid) {
        // 水平网格线
        uint16_t grid_spacing_y = chart->base.height / 10;
        for (uint16_t i = 1; i < 10; i++) {
            uint16_t y = chart->base.y + i * grid_spacing_y;
            ili9341_draw_hline(chart->base.x, y, chart->base.width, chart->grid_color);
        }
        
        // 垂直网格线
        uint16_t grid_spacing_x = chart->base.width / 10;
        for (uint16_t i = 1; i < 10; i++) {
            uint16_t x = chart->base.x + i * grid_spacing_x;
            ili9341_draw_vline(x, chart->base.y, chart->base.height, chart->grid_color);
        }
    }
    
    // 计算数据范围
    float min_val = chart->min_value;
    float max_val = chart->max_value;
    
    if (chart->auto_scale && chart->data_count > 0) {
        min_val = chart->data[0];
        max_val = chart->data[0];
        
        for (uint32_t i = 1; i < chart->data_count; i++) {
            if (chart->data[i] < min_val) min_val = chart->data[i];
            if (chart->data[i] > max_val) max_val = chart->data[i];
        }
        
        // 添加一些边距
        float range = max_val - min_val;
        if (range == 0) range = 1;
        min_val -= range * 0.1;
        max_val += range * 0.1;
    }
    
    // 绘制数据
    if (chart->data_count > 1) {
        float x_scale = (float)(chart->base.width - 2) / (chart->data_count - 1);
        float y_scale = (float)(chart->base.height - 2) / (max_val - min_val);
        
        for (uint32_t i = 0; i < chart->data_count - 1; i++) {
            uint16_t x1 = chart->base.x + 1 + (uint16_t)(i * x_scale);
            uint16_t x2 = chart->base.x + 1 + (uint16_t)((i + 1) * x_scale);
            
            uint16_t y1 = chart->base.y + chart->base.height - 1 - 
                         (uint16_t)((chart->data[i] - min_val) * y_scale);
            uint16_t y2 = chart->base.y + chart->base.height - 1 - 
                         (uint16_t)((chart->data[i + 1] - min_val) * y_scale);
            
            ili9341_draw_line(x1, y1, x2, y2, chart->data_color);
        }
    }
    
    // 绘制坐标轴标签
    char buffer[16];
    
    // 最小值标签
    sprintf(buffer, "%.1f", min_val);
    ili9341_draw_string_8x16(chart->base.x + 2, 
                            chart->base.y + chart->base.height - 16,
                            buffer, chart->base.fg_color, chart->base.bg_color);
    
    // 最大值标签
    sprintf(buffer, "%.1f", max_val);
    ili9341_draw_string_8x16(chart->base.x + 2, 
                            chart->base.y + 2,
                            buffer, chart->base.fg_color, chart->base.bg_color);
}

// 添加数据点
void chart_add_data(ChartWidget *chart, float value) {
    // 检查是否需要扩展数组
    if (chart->data_count >= chart->data_capacity) {
        uint32_t new_capacity = chart->data_capacity * 2;
        float *new_data = realloc(chart->data, new_capacity * sizeof(float));
        if (!new_data) return;
        
        chart->data = new_data;
        chart->data_capacity = new_capacity;
    }
    
    // 添加数据
    chart->data[chart->data_count++] = value;
    
    // 如果数据太多,移除旧数据
    if (chart->data_count > chart->base.width / 2) {
        uint32_t remove_count = chart->data_count - (chart->base.width / 2);
        memmove(chart->data, chart->data + remove_count, 
               (chart->data_count - remove_count) * sizeof(float));
        chart->data_count -= remove_count;
    }
}
10.2.2 报警系统
// 报警级别
typedef enum {
    ALARM_NONE,      // 无报警
    ALARM_INFO,      // 信息
    ALARM_WARNING,   // 警告
    ALARM_ERROR,     // 错误
    ALARM_CRITICAL   // 严重
} AlarmLevel;

// 报警条目
typedef struct {
    uint32_t id;            // 报警ID
    AlarmLevel level;       // 报警级别
    char *message;          // 报警信息
    uint32_t timestamp;     // 时间戳
    uint8_t active;         // 激活状态
} AlarmEntry;

// 报警管理器
typedef struct {
    AlarmEntry *alarms;      // 报警数组
    uint32_t alarm_count;    // 报警数量
    uint32_t alarm_capacity; // 报警容量
    uint32_t next_id;        // 下一个ID
} AlarmManager;

// 初始化报警管理器
uint8_t alarm_manager_init(AlarmManager *am, uint32_t capacity) {
    am->alarms = (AlarmEntry *)malloc(capacity * sizeof(AlarmEntry));
    if (!am->alarms) return 0;
    
    am->alarm_count = 0;
    am->alarm_capacity = capacity;
    am->next_id = 1;
    
    return 1;
}

// 添加报警
uint32_t alarm_manager_add_alarm(AlarmManager *am, 
                                AlarmLevel level,
                                const char *message) {
    // 检查容量
    if (am->alarm_count >= am->alarm_capacity) {
        return 0;  // 报警列表已满
    }
    
    AlarmEntry *alarm = &am->alarms[am->alarm_count++];
    alarm->id = am->next_id++;
    alarm->level = level;
    alarm->message = strdup(message);
    alarm->timestamp = get_current_timestamp();
    alarm->active = 1;
    
    return alarm->id;
}

// 清除报警
void alarm_manager_clear_alarm(AlarmManager *am, uint32_t id) {
    for (uint32_t i = 0; i < am->alarm_count; i++) {
        if (am->alarms[i].id == id) {
            am->alarms[i].active = 0;
            break;
        }
    }
}

// 报警显示控件
typedef struct {
    GUIWidget base;                 // 基类
    AlarmManager *alarm_manager;    // 报警管理器
    uint16_t alarm_colors[5];       // 报警级别颜色
    uint8_t max_display;            // 最大显示数量
} AlarmDisplayWidget;

// 报警显示绘制函数
void alarm_display_draw(void *widget) {
    AlarmDisplayWidget *display = (AlarmDisplayWidget *)widget;
    
    // 绘制背景
    ili9341_fill_rect(display->base.x, display->base.y,
                     display->base.width, display->base.height,
                     display->base.bg_color);
    
    // 绘制边框
    ili9341_draw_rect(display->base.x, display->base.y,
                     display->base.width, display->base.height,
                     display->base.fg_color);
    
    // 绘制标题
    ili9341_draw_string_8x16(display->base.x + 4, display->base.y + 4,
                            "Alarms:", display->base.fg_color, display->base.bg_color);
    
    // 绘制报警列表
    uint16_t y = display->base.y + 24;
    uint8_t display_count = 0;
    
    for (int32_t i = display->alarm_manager->alarm_count - 1; 
         i >= 0 && display_count < display->max_display; i--) {
        AlarmEntry *alarm = &display->alarm_manager->alarms[i];
        
        if (alarm->active) {
            // 绘制报警级别指示器
            uint16_t level_color = display->alarm_colors[alarm->level];
            ili9341_fill_rect(display->base.x + 4, y, 8, 8, level_color);
            
            // 绘制报警信息
            char buffer[64];
            snprintf(buffer, sizeof(buffer), "%s", alarm->message);
            
            ili9341_draw_string_8x16(display->base.x + 16, y,
                                    buffer, display->base.fg_color, display->base.bg_color);
            
            y += 20;
            display_count++;
        }
    }
    
    // 如果没有报警
    if (display_count == 0) {
        ili9341_draw_string_8x16(display->base.x + 4, display->base.y + 24,
                                "No active alarms",
                                COLOR_GRAY, display->base.bg_color);
    }
}

第十一章:调试与故障排除

11.1 常见问题与解决方案

11.1.1 显示问题排查
// 显示诊断工具
void ili9341_diagnostic(void) {
    printf("ILI9341 Diagnostic Tool\n");
    printf("======================\n\n");
    
    // 1. 电源检查
    printf("1. Power Supply Check:\n");
    printf("   - VCC (3.3V): %s\n", check_voltage(VCC_PIN, 3.3, 0.1) ? "OK" : "FAIL");
    printf("   - AVDD (3.3V): %s\n", check_voltage(AVDD_PIN, 3.3, 0.1) ? "OK" : "FAIL");
    printf("   - LED Backlight: %s\n", check_backlight() ? "OK" : "FAIL");
    
    // 2. 通信测试
    printf("\n2. Communication Test:\n");
    if (test_spi_communication()) {
        printf("   - SPI Communication: OK\n");
        
        // 读取ID
        uint32_t id = ili9341_read_id();
        printf("   - Chip ID: 0x%06lX\n", id);
        
        if (id == 0x9341 || id == 0x9341) {
            printf("   - ID Verification: PASS\n");
        } else {
            printf("   - ID Verification: FAIL (Expected 0x9341)\n");
        }
    } else {
        printf("   - SPI Communication: FAIL\n");
    }
    
    // 3. 显示测试模式
    printf("\n3. Display Test Patterns:\n");
    
    // 测试颜色条
    printf("   - Color Bars: ");
    test_color_bars();
    printf("DONE\n");
    
    // 测试渐变
    printf("   - Gradient: ");
    test_gradient();
    printf("DONE\n");
    
    // 测试文本
    printf("   - Text Display: ");
    test_text_display();
    printf("DONE\n");
    
    // 4. 性能测试
    printf("\n4. Performance Test:\n");
    uint32_t fill_time = test_fill_performance();
    printf("   - Screen Fill Time: %lu ms\n", fill_time);
    
    uint32_t line_time = test_line_performance();
    printf("   - Line Drawing Time: %lu ms/line\n", line_time);
    
    // 5. 内存测试
    printf("\n5. Memory Test:\n");
    if (test_gram_access()) {
        printf("   - GRAM Access: PASS\n");
    } else {
        printf("   - GRAM Access: FAIL\n");
    }
    
    printf("\nDiagnostic Complete.\n");
}

// 测试颜色条
void test_color_bars(void) {
    uint16_t colors[] = {
        COLOR_RED, COLOR_GREEN, COLOR_BLUE,
        COLOR_YELLOW, COLOR_CYAN, COLOR_MAGENTA,
        COLOR_WHITE, COLOR_BLACK
    };
    
    uint16_t bar_width = DISPLAY_WIDTH / 8;
    
    for (uint8_t i = 0; i < 8; i++) {
        ili9341_fill_rect(i * bar_width, 0, bar_width, DISPLAY_HEIGHT, colors[i]);
    }
    
    delay_ms(2000);
}

// 测试渐变
void test_gradient(void) {
    for (uint16_t y = 0; y < DISPLAY_HEIGHT; y++) {
        uint16_t color = (y * 31) / DISPLAY_HEIGHT;
        color = (color << 11) | (color << 6) | color;
        
        ili9341_draw_hline(0, y, DISPLAY_WIDTH, color);
    }
    
    delay_ms(2000);
}

// 读取芯片ID
uint32_t ili9341_read_id(void) {
    uint32_t id = 0;
    
    // 发送读取ID命令
    ili9341_write_command(0x04);  // Read Display ID
    
    // 读取ID数据
    id = ili9341_read_data() << 16;
    id |= ili9341_read_data() << 8;
    id |= ili9341_read_data();
    
    return id;
}

// 测试GRAM访问
uint8_t test_gram_access(void) {
    // 测试写/读
    uint16_t test_x = 100;
    uint16_t test_y = 100;
    uint16_t test_color = 0x5A5A;
    
    // 写入测试像素
    ili9341_draw_pixel(test_x, test_y, test_color);
    
    // 等待写入完成
    delay_ms(10);
    
    // 读取像素
    // 注意:ILI9341需要配置为读模式
    uint16_t read_color = ili9341_read_pixel(test_x, test_y);
    
    // 比较颜色
    return (read_color == test_color);
}

// 读取像素颜色
uint16_t ili9341_read_pixel(uint16_t x, uint16_t y) {
    uint16_t color = 0;
    
    // 设置读取窗口
    ili9341_set_window(x, y, x, y);
    
    // 发送读GRAM命令
    ili9341_write_command(0x2E);  // Memory Read
    
    // 读取颜色数据(需要丢弃前几个字节)
    // ILI9341在开始返回有效数据前会发送一些虚拟数据
    ili9341_read_data();  // 丢弃
    ili9341_read_data();  // 丢弃
    
    // 读取颜色
    uint16_t high_byte = ili9341_read_data();
    uint16_t low_byte = ili9341_read_data();
    
    color = (high_byte << 8) | low_byte;
    
    return color;
}
11.1.2 通信问题排查
// SPI通信诊断
uint8_t test_spi_communication(void) {
    // 测试SPI回环
    uint8_t test_pattern[] = {0xAA, 0x55, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
    uint8_t rx_buffer[8];
    
    // 配置SPI为回环模式
    spi_enable_loopback();
    
    // 发送测试数据
    spi_transfer_bulk(test_pattern, rx_buffer, 8);
    
    // 比较数据
    for (uint8_t i = 0; i < 8; i++) {
        if (test_pattern[i] != rx_buffer[i]) {
            spi_disable_loopback();
            return 0;
        }
    }
    
    spi_disable_loopback();
    return 1;
}

// 信号质量测试
void test_signal_quality(void) {
    printf("Signal Quality Test\n");
    printf("===================\n");
    
    // 测试时钟信号
    printf("1. Clock Signal:\n");
    uint32_t clock_freq = measure_frequency(SCLK_PIN);
    printf("   - Frequency: %lu Hz\n", clock_freq);
    printf("   - Duty Cycle: %.1f%%\n", measure_duty_cycle(SCLK_PIN) * 100);
    
    // 测试数据信号
    printf("\n2. Data Signals:\n");
    
    // 发送测试模式并测量信号完整性
    uint8_t test_data[100];
    for (uint8_t i = 0; i < 100; i++) {
        test_data[i] = i;
    }
    
    // 测量上升/下降时间
    float rise_time = measure_rise_time(MOSI_PIN);
    float fall_time = measure_fall_time(MOSI_PIN);
    
    printf("   - Rise Time: %.1f ns\n", rise_time);
    printf("   - Fall Time: %.1f ns\n", fall_time);
    
    // 测试噪声水平
    float noise_level = measure_noise(MOSI_PIN);
    printf("   - Noise Level: %.2f V\n", noise_level);
    
    printf("\nSignal Quality: %s\n", 
           (rise_time < 10 && fall_time < 10 && noise_level < 0.1) ? "GOOD" : "POOR");
}

// 接口模式检测
void detect_interface_mode(void) {
    printf("Interface Mode Detection\n");
    printf("========================\n");
    
    // 读取IM[3:0]引脚状态
    uint8_t im3 = gpio_read(IM3_PIN);
    uint8_t im2 = gpio_read(IM2_PIN);
    uint8_t im1 = gpio_read(IM1_PIN);
    uint8_t im0 = gpio_read(IM0_PIN);
    
    printf("IM Pins: %d%d%d%d\n", im3, im2, im1, im0);
    
    // 解析接口模式
    const char *interface_mode = "Unknown";
    
    if (im3 == 1 && im2 == 1 && im1 == 0 && im0 == 0) {
        interface_mode = "8-bit 8080 Parallel";
    } else if (im3 == 1 && im2 == 1 && im1 == 0 && im0 == 1) {
        interface_mode = "16-bit 8080 Parallel";
    } else if (im3 == 1 && im2 == 1 && im1 == 1 && im0 == 1) {
        interface_mode = "3-line/4-line SPI";
    } else if (im3 == 0 && im2 == 1 && im1 == 0 && im0 == 1) {
        interface_mode = "RGB 6-6-6";
    }
    
    printf("Interface Mode: %s\n", interface_mode);
    
    // 建议的初始化序列
    printf("\nRecommended Initialization:\n");
    if (strcmp(interface_mode, "3-line/4-line SPI") == 0) {
        printf("- Use SPI commands with D/CX pin\n");
        printf("- Max clock: 40MHz\n");
        printf("- Mode: CPOL=0, CPHA=0\n");
    } else if (strstr(interface_mode, "Parallel")) {
        printf("- Use WR# and RD# control signals\n");
        printf("- Data width: %s\n", strstr(interface_mode, "8-bit") ? "8-bit" : "16-bit");
        printf("- Timing critical: ensure proper setup/hold times\n");
    }
}

11.2 性能优化验证

11.2.1 基准测试工具
// 性能基准测试
typedef struct {
    uint32_t fill_time;           // 填充时间(ms)
    uint32_t line_time;           // 画线时间(ms/线)
    uint32_t rect_time;           // 矩形时间(ms/矩形)
    uint32_t text_time;           // 文本时间(ms/字符)
    uint32_t image_time;          // 图像时间(ms/图像)
    uint32_t fps;                 // 帧率(FPS)
} PerformanceMetrics;

// 运行基准测试
PerformanceMetrics run_benchmark(void) {
    PerformanceMetrics metrics = {0};
    
    printf("Running ILI9341 Performance Benchmark\n");
    printf("=====================================\n\n");
    
    // 1. 屏幕填充测试
    printf("1. Screen Fill Test... ");
    uint32_t start_time = get_tick_count();
    
    for (uint8_t i = 0; i < 10; i++) {
        ili9341_fill_screen(COLOR_RED);
        ili9341_fill_screen(COLOR_GREEN);
        ili9341_fill_screen(COLOR_BLUE);
    }
    
    uint32_t end_time = get_tick_count();
    metrics.fill_time = (end_time - start_time) / 30;  // 平均每次填充时间
    printf("%lu ms/fill\n", metrics.fill_time);
    
    // 2. 画线测试
    printf("2. Line Drawing Test... ");
    start_time = get_tick_count();
    
    for (uint16_t i = 0; i < 100; i++) {
        ili9341_draw_line(0, i, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - i - 1, COLOR_WHITE);
    }
    
    end_time = get_tick_count();
    metrics.line_time = (end_time - start_time) / 100;
    printf("%lu ms/line\n", metrics.line_time);
    
    // 3. 矩形测试
    printf("3. Rectangle Drawing Test... ");
    start_time = get_tick_count();
    
    for (uint16_t i = 0; i < 50; i++) {
        ili9341_draw_rect(i * 2, i * 2, 100, 100, COLOR_YELLOW);
    }
    
    end_time = get_tick_count();
    metrics.rect_time = (end_time - start_time) / 50;
    printf("%lu ms/rect\n", metrics.rect_time);
    
    // 4. 文本测试
    printf("4. Text Rendering Test... ");
    start_time = get_tick_count();
    
    const char *test_text = "Hello ILI9341!";
    uint16_t text_len = strlen(test_text);
    
    for (uint8_t i = 0; i < 100; i++) {
        ili9341_draw_string_8x16(10, 10, test_text, COLOR_WHITE, COLOR_BLACK);
    }
    
    end_time = get_tick_count();
    metrics.text_time = (end_time - start_time) / (100 * text_len);
    printf("%lu ms/char\n", metrics.text_time);
    
    // 5. 图像显示测试
    printf("5. Image Display Test... ");
    
    // 创建测试图像
    uint16_t test_image[50 * 50];
    for (uint16_t y = 0; y < 50; y++) {
        for (uint16_t x = 0; x < 50; x++) {
            test_image[y * 50 + x] = ((x * 31 / 50) << 11) | ((y * 63 / 50) << 5);
        }
    }
    
    start_time = get_tick_count();
    
    for (uint8_t i = 0; i < 20; i++) {
        ili9341_draw_image_rgb565(10, 10, 50, 50, test_image);
    }
    
    end_time = get_tick_count();
    metrics.image_time = (end_time - start_time) / 20;
    printf("%lu ms/image\n", metrics.image_time);
    
    // 6. 帧率测试
    printf("6. Frame Rate Test... ");
    
    uint32_t frame_count = 0;
    start_time = get_tick_count();
    end_time = start_time + 5000;  // 测试5秒
    
    while (get_tick_count() < end_time) {
        // 绘制动画帧
        uint16_t x = (frame_count * 2) % (DISPLAY_WIDTH - 50);
        uint16_t y = (frame_count * 3) % (DISPLAY_HEIGHT - 50);
        
        ili9341_fill_rect(x, y, 50, 50, COLOR_RED);
        frame_count++;
    }
    
    uint32_t total_time = get_tick_count() - start_time;
    metrics.fps = (frame_count * 1000) / total_time;
    printf("%lu FPS\n", metrics.fps);
    
    printf("\nBenchmark Complete.\n");
    
    return metrics;
}

// 生成性能报告
void generate_performance_report(PerformanceMetrics metrics) {
    printf("\nILI9341 Performance Report\n");
    printf("===========================\n");
    
    printf("Screen Fill:      %6lu ms\n", metrics.fill_time);
    printf("Line Drawing:     %6lu ms/line\n", metrics.line_time);
    printf("Rectangle:        %6lu ms/rect\n", metrics.rect_time);
    printf("Text Rendering:   %6lu ms/char\n", metrics.text_time);
    printf("Image Display:    %6lu ms/image\n", metrics.image_time);
    printf("Frame Rate:       %6lu FPS\n", metrics.fps);
    
    printf("\nPerformance Rating: ");
    
    uint32_t score = 0;
    score += (metrics.fill_time < 100) ? 20 : (metrics.fill_time < 200) ? 15 : 5;
    score += (metrics.fps > 30) ? 20 : (metrics.fps > 15) ? 15 : 5;
    score += (metrics.text_time < 1) ? 20 : (metrics.text_time < 2) ? 15 : 5;
    score += (metrics.line_time < 5) ? 20 : (metrics.line_time < 10) ? 15 : 5;
    score += (metrics.image_time < 50) ? 20 : (metrics.image_time < 100) ? 15 : 5;
    
    if (score >= 90) {
        printf("EXCELLENT\n");
    } else if (score >= 75) {
        printf("GOOD\n");
    } else if (score >= 60) {
        printf("FAIR\n");
    } else {
        printf("POOR - Consider Optimization\n");
    }
    
    printf("Overall Score: %lu/100\n", score);
    
    // 优化建议
    printf("\nOptimization Suggestions:\n");
    if (metrics.fill_time > 150) {
        printf("- Optimize fill functions (use DMA or bulk transfers)\n");
    }
    if (metrics.fps < 15) {
        printf("- Implement double buffering or partial updates\n");
    }
    if (metrics.text_time > 2) {
        printf("- Use bitmapped fonts or cache rendered text\n");
    }
    if (metrics.image_time > 100) {
        printf("- Optimize image transfer (DMA, compressed formats)\n");
    }
}

第十二章:未来发展与扩展

12.1 高级特性支持

12.1.1 硬件加速探索
// GPU加速接口定义
typedef struct {
    void (*draw_rectangle)(uint16_t x, uint16_t y, 
                          uint16_t width, uint16_t height,
                          uint16_t color);
    void (*draw_line)(uint16_t x1, uint16_t y1,
                     uint16_t x2, uint16_t y2,
                     uint16_t color);
    void (*draw_triangle)(uint16_t x1, uint16_t y1,
                         uint16_t x2, uint16_t y2,
                         uint16_t x3, uint16_t y3,
                         uint16_t color);
    void (*blit_image)(uint16_t x, uint16_t y,
                      uint16_t width, uint16_t height,
                      const uint16_t *image);
    void (*alpha_blend)(uint16_t x, uint16_t y,
                       uint16_t width, uint16_t height,
                       const uint16_t *image,
                       uint8_t alpha);
} GPU_Interface;

// 软件模拟GPU
void software_gpu_init(GPU_Interface *gpu) {
    gpu->draw_rectangle = software_draw_rectangle;
    gpu->draw_line = software_draw_line;
    gpu->draw_triangle = software_draw_triangle;
    gpu->blit_image = software_blit_image;
    gpu->alpha_blend = software_alpha_blend;
}

// 带透明度混合的blit
void software_alpha_blend(uint16_t x, uint16_t y,
                         uint16_t width, uint16_t height,
                         const uint16_t *image,
                         uint8_t alpha) {
    // 设置窗口
    ili9341_set_window(x, y, x + width - 1, y + height - 1);
    
    // 准备混合
    float alpha_ratio = alpha / 255.0f;
    
    if (current_interface == INTERFACE_SPI) {
        GPIO_WriteHigh(DC_PIN);
        GPIO_WriteLow(CS_PIN);
        
        for (uint16_t i = 0; i < width * height; i++) {
            // 注意:这里简化处理,实际需要读取当前像素进行混合
            uint16_t src_color = image[i];
            // uint16_t dst_color = read_current_pixel(); // 需要读操作支持
            
            // 简化实现:直接绘制(无混合)
            spi_transfer(src_color >> 8);
            spi_transfer(src_color & 0xFF);
        }
        
        GPIO_WriteHigh(CS_PIN);
    }
}
12.1.2 多图层支持
// 图层管理
typedef struct {
    uint16_t *buffer;        // 图层缓冲区
    uint16_t width;          // 宽度
    uint16_t height;         // 高度
    uint16_t x;              // X位置
    uint16_t y;              // Y位置
    uint8_t visible;         // 可见性
    uint8_t alpha;           // 透明度(0-255)
    void (*update_callback)(void *);  // 更新回调
    void *user_data;         // 用户数据
} Layer;

// 图层管理器
typedef struct {
    Layer **layers;          // 图层数组
    uint32_t layer_count;    // 图层数量
    uint32_t layer_capacity; // 图层容量
    uint16_t *composite_buffer;  // 合成缓冲区
} LayerManager;

// 图层合成
void layer_manager_composite(LayerManager *lm) {
    // 清空合成缓冲区
    memset(lm->composite_buffer, 0, 
           DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t));
    
    // 从底层到顶层合成
    for (uint32_t i = 0; i < lm->layer_count; i++) {
        Layer *layer = lm->layers[i];
        
        if (layer->visible) {
            // 合成图层
            for (uint16_t y = 0; y < layer->height; y++) {
                for (uint16_t x = 0; x < layer->width; x++) {
                    uint16_t src_pixel = layer->buffer[y * layer->width + x];
                    
                    // 计算目标位置
                    uint16_t dst_x = layer->x + x;
                    uint16_t dst_y = layer->y + y;
                    
                    if (dst_x < DISPLAY_WIDTH && dst_y < DISPLAY_HEIGHT) {
                        uint32_t dst_idx = dst_y * DISPLAY_WIDTH + dst_x;
                        
                        // Alpha混合
                        if (layer->alpha == 255) {
                            // 完全覆盖
                            lm->composite_buffer[dst_idx] = src_pixel;
                        } else if (layer->alpha > 0) {
                            // Alpha混合
                            uint16_t dst_pixel = lm->composite_buffer[dst_idx];
                            
                            // 提取颜色分量
                            uint8_t src_r = (src_pixel >> 11) & 0x1F;
                            uint8_t src_g = (src_pixel >> 5) & 0x3F;
                            uint8_t src_b = src_pixel & 0x1F;
                            
                            uint8_t dst_r = (dst_pixel >> 11) & 0x1F;
                            uint8_t dst_g = (dst_pixel >> 5) & 0x3F;
                            uint8_t dst_b = dst_pixel & 0x1F;
                            
                            float alpha = layer->alpha / 255.0f;
                            
                            // 混合
                            uint8_t r = (uint8_t)(src_r * alpha + dst_r * (1 - alpha));
                            uint8_t g = (uint8_t)(src_g * alpha + dst_g * (1 - alpha));
                            uint8_t b = (uint8_t)(src_b * alpha + dst_b * (1 - alpha));
                            
                            lm->composite_buffer[dst_idx] = 
                                (r << 11) | (g << 5) | b;
                        }
                    }
                }
            }
        }
    }
    
    // 显示合成结果
    ili9341_draw_image_rgb565(0, 0, 
                             DISPLAY_WIDTH, DISPLAY_HEIGHT,
                             lm->composite_buffer);
}

12.2 物联网与云集成

12.2.1 远程显示控制
// 远程命令协议
typedef struct {
    uint8_t command;         // 命令类型
    uint16_t x;              // X坐标
    uint16_t y;              // Y坐标
    uint16_t param1;         // 参数1
    uint16_t param2;         // 参数2
    uint32_t color;          // 颜色
    uint8_t data_length;     // 数据长度
    uint8_t data[];          // 数据
} RemoteCommand;

// 远程显示服务器
void remote_display_server(void) {
    printf("Remote Display Server Started\n");
    
    while (1) {
        // 等待网络连接
        int client_fd = accept_connection();
        
        if (client_fd >= 0) {
            printf("Client connected\n");
            
            // 处理客户端请求
            while (1) {
                RemoteCommand cmd;
                
                // 接收命令
                ssize_t bytes = receive_data(client_fd, &cmd, sizeof(RemoteCommand));
                
                if (bytes <= 0) {
                    printf("Client disconnected\n");
                    break;
                }
                
                // 处理命令
                switch (cmd.command) {
                    case CMD_CLEAR_SCREEN:
                        ili9341_fill_screen(cmd.color);
                        break;
                        
                    case CMD_DRAW_RECTANGLE:
                        ili9341_draw_rect(cmd.x, cmd.y, 
                                         cmd.param1, cmd.param2,
                                         cmd.color);
                        break;
                        
                    case CMD_DRAW_LINE:
                        ili9341_draw_line(cmd.x, cmd.y,
                                         cmd.param1, cmd.param2,
                                         cmd.color);
                        break;
                        
                    case CMD_DRAW_TEXT:
                        if (cmd.data_length > 0) {
                            // 确保字符串以null结尾
                            char text[256];
                            uint8_t len = cmd.data_length < 255 ? cmd.data_length : 255;
                            memcpy(text, cmd.data, len);
                            text[len] = '\0';
                            
                            ili9341_draw_string_8x16(cmd.x, cmd.y, text,
                                                    cmd.color, COLOR_BLACK);
                        }
                        break;
                        
                    case CMD_DRAW_IMAGE:
                        if (cmd.data_length > 0) {
                            // 假设数据是RGB565图像
                            uint16_t *image_data = (uint16_t *)cmd.data;
                            uint32_t pixel_count = cmd.data_length / 2;
                            
                            // 计算图像尺寸
                            uint16_t width = cmd.param1;
                            uint16_t height = cmd.param2;
                            
                            if (width * height * 2 == cmd.data_length) {
                                ili9341_draw_image_rgb565(cmd.x, cmd.y,
                                                         width, height,
                                                         image_data);
                            }
                        }
                        break;
                        
                    default:
                        printf("Unknown command: %d\n", cmd.command);
                }
                
                // 发送确认
                send_ack(client_fd);
            }
            
            // 关闭连接
            close_connection(client_fd);
        }
    }
}
12.2.2 云数据可视化
// 云端数据可视化
void cloud_data_visualization(void) {
    printf("Cloud Data Visualization Started\n");
    
    // 连接云服务
    if (!connect_to_cloud()) {
        printf("Failed to connect to cloud\n");
        return;
    }
    
    // 创建图表
    ChartWidget temperature_chart;
    ChartWidget humidity_chart;
    
    // 初始化图表
    chart_init(&temperature_chart, 10, 10, 300, 100, "Temperature (°C)");
    chart_init(&humidity_chart, 10, 120, 300, 100, "Humidity (%)");
    
    while (1) {
        // 从云端获取数据
        CloudData data;
        if (get_cloud_data(&data)) {
            // 更新图表
            chart_add_data(&temperature_chart, data.temperature);
            chart_add_data(&humidity_chart, data.humidity);
            
            // 绘制图表
            chart_draw(&temperature_chart);
            chart_draw(&humidity_chart);
            
            // 显示当前值
            char temp_str[32];
            char hum_str[32];
            
            sprintf(temp_str, "Temp: %.1f°C", data.temperature);
            sprintf(hum_str, "Hum: %.1f%%", data.humidity);
            
            ili9341_draw_string_8x16(320, 10, temp_str, COLOR_WHITE, COLOR_BLACK);
            ili9341_draw_string_8x16(320, 30, hum_str, COLOR_WHITE, COLOR_BLACK);
            
            // 检查报警条件
            if (data.temperature > 30.0) {
                // 温度过高报警
                ili9341_draw_string_8x16(320, 60, "HIGH TEMP!", COLOR_RED, COLOR_BLACK);
            } else if (data.temperature < 10.0) {
                // 温度过低报警
                ili9341_draw_string_8x16(320, 60, "LOW TEMP!", COLOR_BLUE, COLOR_BLACK);
            } else {
                ili9341_draw_string_8x16(320, 60, "NORMAL", COLOR_GREEN, COLOR_BLACK);
            }
        }
        
        // 延时
        delay_ms(5000);  // 5秒更新一次
    }
}

总结

本文全面深入地探讨了ILI9341显示驱动芯片的技术细节、应用实践和性能优化。我们从硬件接口、通信协议、初始化配置开始,逐步深入到图形绘制、文本显示、图像处理等高级主题,最后探讨了实际项目应用和未来发展方向。

通过本文的学习,您应该能够:

  1. 理解ILI9341的工作原理:掌握芯片的接口模式、寄存器配置和显示机制。

  2. 实现高效的显示驱动:通过SPI和8080两种接口模式,实现优化的显示操作。

  3. 构建丰富的图形界面:实现基本的几何图形、文本显示和图像处理功能。

  4. 优化显示性能:通过双缓冲、DMA传输、脏矩形等技术提升显示效率。

  5. 开发实际应用:构建GUI框架、数据可视化系统和工业HMI界面。

  6. 调试和优化:使用诊断工具和性能测试来优化显示效果。

ILI9341作为一款成熟可靠的显示驱动芯片,在嵌入式领域有着广泛的应用。随着物联网和智能设备的发展,对高效、可靠的显示解决方案需求将持续增长。掌握ILI9341的深度应用技术,将为您在嵌入式显示领域的开发工作提供坚实的技术基础。

希望本文能够成为您学习和应用ILI9341的有力参考,祝您在嵌入式显示开发的旅程中取得成功!


版权声明:本文为技术分享文章,允许在注明出处的前提下自由转载和使用。文中代码示例遵循MIT开源协议,可根据需要修改和使用。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐