#include "includes.h" void LCD_GPIO_Init(void) { gpio_init_type gpio_init_struct; wk_spi2_init(); /* 必须先用默认参数填充结构体,否则 out_type/pull 等字段是栈上随机值, 可能导致引脚被配成开漏输出,背光和复位引脚拉不高,屏幕不亮 */ gpio_default_para_init(&gpio_init_struct); // LCD控制引脚:DC(PA8)、RESET(PA10) —— 推挽输出 gpio_init_struct.gpio_pins = LCD_DC_PIN | LCD_RES_PIN; gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOA, &gpio_init_struct); // 背光引脚:BL(PC9) —— 推挽输出 gpio_init_struct.gpio_pins = LCD_BLK_PIN; gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOC, &gpio_init_struct); // 初始状态 LCD_BLK_Clr(); // 背光灯关闭 LCD_RES_Set(); // 复位引脚高电平 } // 发送8位命令(硬件NSS自动拉低/拉高) void LCD_WR_REG(uint8_t reg) { LCD_DC_Clr(); while (!(SPI2->sts & SPI_I2S_TDBE_FLAG)); /* 等待发送缓冲空,避免丢字节 */ spi_i2s_data_transmit(SPI2, reg); while (SPI2->sts & SPI_I2S_BF_FLAG); /* 等待本次发送完成 */ } // 发送8位数据(硬件NSS自动拉低/拉高) void LCD_WR_DATA8(uint8_t data) { LCD_DC_Set(); while (!(SPI2->sts & SPI_I2S_TDBE_FLAG)); spi_i2s_data_transmit(SPI2, data); while (SPI2->sts & SPI_I2S_BF_FLAG); } // 发送16位数据(RGB565格式,SPI为8位模式,必须分两次发:高字节在前) void LCD_WR_DATA16(uint16_t data) { LCD_DC_Set(); while (!(SPI2->sts & SPI_I2S_TDBE_FLAG)); spi_i2s_data_transmit(SPI2, (data >> 8) & 0xFF); while (!(SPI2->sts & SPI_I2S_TDBE_FLAG)); spi_i2s_data_transmit(SPI2, data & 0xFF); while (SPI2->sts & SPI_I2S_BF_FLAG); } /*! * @brief SPI2 DMA 批量发送数据(仅用于连续像素/图片数据) * @param data 数据缓冲区指针 * @param len 字节数 * @note 调用前需等待上一次DMA完成,此函数内部会等待传输完成 */ void LCD_SPI_DMA_Send(const uint8_t *data, uint32_t len) { uint32_t tmp; if (len == 0) return; tmp = len; while (tmp--) { // SPI 轮询发送 while (!(SPI2->sts & SPI_I2S_TDBE_FLAG)); SPI2->dt = *(data++); } while (SPI2->sts & SPI_I2S_BF_FLAG); } /****************************************************************************** 函数说明:设置起始和结束地址 入口数据:x1,x2 设置列的起始和结束地址 y1,y2 设置行的起始和结束地址 返回值: 无 ******************************************************************************/ void LCD_SetWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { LCD_WR_REG(0x2A); // 列地址设置 LCD_WR_DATA16(x1); LCD_WR_DATA16(x2); LCD_WR_REG(0x2B); // 行地址设置 LCD_WR_DATA16(y1); LCD_WR_DATA16(y2); LCD_WR_REG(0x2C); // 开始写入GRAM } void LCD_Init(void) { LCD_GPIO_Init();//初始化GPIO // 复位LCD(ILI9341要求复位低电平≥10μs,复位高后等待≥5ms即可) LCD_RES_Clr(); wk_delay_ms(10); // 10ms >> 10μs要求 LCD_RES_Set(); wk_delay_ms(10); // 10ms >> 5ms要求 //************* Start Initial Sequence **********// LCD_WR_REG(0x11); //Sleep out wk_delay_ms(120); //Delay 120ms (ILI9341要求,不可缩短) //************* Start Initial Sequence **********// LCD_WR_REG(0xCF); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0xC1); LCD_WR_DATA8(0X30); LCD_WR_REG(0xED); LCD_WR_DATA8(0x64); LCD_WR_DATA8(0x03); LCD_WR_DATA8(0X12); LCD_WR_DATA8(0X81); LCD_WR_REG(0xE8); LCD_WR_DATA8(0x85); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x79); LCD_WR_REG(0xCB); LCD_WR_DATA8(0x39); LCD_WR_DATA8(0x2C); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x34); LCD_WR_DATA8(0x02); LCD_WR_REG(0xF7); LCD_WR_DATA8(0x20); LCD_WR_REG(0xEA); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x00); LCD_WR_REG(0xC0); //Power control LCD_WR_DATA8(0x1D); //VRH[5:0] LCD_WR_REG(0xC1); //Power control LCD_WR_DATA8(0x12); //SAP[2:0];BT[3:0] LCD_WR_REG(0xC5); //VCM control LCD_WR_DATA8(0x33); LCD_WR_DATA8(0x3F); LCD_WR_REG(0xC7); //VCM control LCD_WR_DATA8(0x92); LCD_WR_REG(0x3A); // Memory Access Control LCD_WR_DATA8(0x55); LCD_WR_REG(0x36); // Memory Access Control if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08); else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8); else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x78); else LCD_WR_DATA8(0xA8); LCD_WR_REG(0xB1); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x12); LCD_WR_REG(0xB6); // Display Function Control LCD_WR_DATA8(0x0A); LCD_WR_DATA8(0xA2); LCD_WR_REG(0x44); LCD_WR_DATA8(0x02); LCD_WR_REG(0xF2); // 3Gamma Function Disable LCD_WR_DATA8(0x00); LCD_WR_REG(0x26); //Gamma curve selected LCD_WR_DATA8(0x01); LCD_WR_REG(0xE0); //Set Gamma LCD_WR_DATA8(0x0F); LCD_WR_DATA8(0x22); LCD_WR_DATA8(0x1C); LCD_WR_DATA8(0x1B); LCD_WR_DATA8(0x08); LCD_WR_DATA8(0x0F); LCD_WR_DATA8(0x48); LCD_WR_DATA8(0xB8); LCD_WR_DATA8(0x34); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x0C); LCD_WR_DATA8(0x09); LCD_WR_DATA8(0x0F); LCD_WR_DATA8(0x07); LCD_WR_DATA8(0x00); LCD_WR_REG(0XE1); //Set Gamma LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x23); LCD_WR_DATA8(0x24); LCD_WR_DATA8(0x07); LCD_WR_DATA8(0x10); LCD_WR_DATA8(0x07); LCD_WR_DATA8(0x38); LCD_WR_DATA8(0x47); LCD_WR_DATA8(0x4B); LCD_WR_DATA8(0x0A); LCD_WR_DATA8(0x13); LCD_WR_DATA8(0x06); LCD_WR_DATA8(0x30); LCD_WR_DATA8(0x38); LCD_WR_DATA8(0x0F); // LCD_WR_REG(0x29); //Display on LCD_FillByColor(0, 0, 240, 320, BLACK); LCD_WR_REG(0x29); //Display on LCD_BLK_Set(); }