210 lines
5.9 KiB
C
210 lines
5.9 KiB
C
#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();
|
||
}
|