wch-code/ch32v307_lvgl_ili9341/User/bsp_lcd_ili9341.c

259 lines
7.3 KiB
C

#include "bsp_lcd_ili9341.h"
#include "debug.h"
static volatile uint8_t bsp_lcd_trans_done = 1;
void DMA1_Channel3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
static void bsp_lcd_send_cmd(uint8_t cmd)
{
GPIO_ResetBits(BSP_LCD_GPIO_PORT, BSP_LCD_DC_GPIO); //D/C=0, 指令
GPIO_ResetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=0
SPI_DataSizeConfig(SPI1, SPI_DataSize_8b);
SPI_I2S_SendData(SPI1, cmd);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //等待传输完成
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=1
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_DC_GPIO); //D/C=1, 数据
}
static void bsp_lcd_send_data(const uint8_t *data, uint8_t len)
{
GPIO_ResetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=0
SPI_DataSizeConfig(SPI1, SPI_DataSize_8b);
for (uint8_t i = 0; i < len; i ++) {
SPI_I2S_SendData(SPI1, data[i]);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //等待传输完成
}
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=1
}
/**
* @brief 初始化ST7789v控制器的寄存器(240*320)
*
* @param spi SPI句柄
*/static void lcd_reg_init_ili9341(void)
{
bsp_lcd_send_cmd(0xCF);
bsp_lcd_send_data((uint8_t[]){0x00, 0xC1, 0X30}, 3);
bsp_lcd_send_cmd(0xED);
bsp_lcd_send_data((uint8_t[]){0x64, 0x03, 0X12, 0X81}, 4);
bsp_lcd_send_cmd(0xE8);
bsp_lcd_send_data((uint8_t[]){0x85, 0x01, 0x79}, 3);
bsp_lcd_send_cmd(0xCB);
bsp_lcd_send_data((uint8_t[]){0x39, 0x2C, 0x00, 0x34, 0x02}, 5);
bsp_lcd_send_cmd(0xF7);
bsp_lcd_send_data((uint8_t[]){0x20}, 1);
bsp_lcd_send_cmd(0xEA);
bsp_lcd_send_data((uint8_t[]){0x00, 0x00}, 2);
bsp_lcd_send_cmd(0xC0);
bsp_lcd_send_data((uint8_t[]){0x18}, 1);
bsp_lcd_send_cmd(0xC1);
bsp_lcd_send_data((uint8_t[]){0x12}, 1);
bsp_lcd_send_cmd(0xC5);
bsp_lcd_send_data((uint8_t[]){0x31, 0x3C}, 2);
bsp_lcd_send_cmd(0xC7);
bsp_lcd_send_data((uint8_t[]){0x99}, 1);
bsp_lcd_send_cmd(0x36);
bsp_lcd_send_data((uint8_t[]){0x28}, 1);
bsp_lcd_send_cmd(0x3A);
bsp_lcd_send_data((uint8_t[]){0x55}, 1);
bsp_lcd_send_cmd(0xB1);
bsp_lcd_send_data((uint8_t[]){0x00, 0x16}, 2);
bsp_lcd_send_cmd(0xF2);
bsp_lcd_send_data((uint8_t[]){0x00}, 1);
bsp_lcd_send_cmd(0x26);
bsp_lcd_send_data((uint8_t[]){0x02}, 1);
bsp_lcd_send_cmd(0xE0);
bsp_lcd_send_data((uint8_t[]){0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15);
bsp_lcd_send_cmd(0xE1);
bsp_lcd_send_data((uint8_t[]){0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15);
bsp_lcd_send_cmd(0xB6);
bsp_lcd_send_data((uint8_t[]){0x0A, 0x82, 0x27, 0x00}, 4);
/* 屏幕方向 */
bsp_lcd_send_cmd(0x36);
//bsp_lcd_send_data((uint8_t[]){0x28}, 1); //横向 芯片在右
// bsp_lcd_send_data((uint8_t[]){0xE8}, 1); //横向 芯片在左
bsp_lcd_send_data((uint8_t[]){0x48}, 1); //竖屏 芯片在下
bsp_lcd_send_cmd(0x11);
Delay_Ms(50);
bsp_lcd_send_cmd(0x29);
Delay_Ms(50);
}
void bsp_lcd_switch(uint8_t sw)
{
if (sw) {
bsp_lcd_send_cmd(0x29);
} else {
bsp_lcd_send_cmd(0x28);
}
}
void DMA1_Channel3_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_FLAG_TC3) != RESET) {
/* 清除DMA中断标志位 */
DMA_ClearITPendingBit(DMA1_FLAG_TC3);
/* 复位DMA */
DMA_Cmd(DMA1_Channel3, DISABLE);
bsp_lcd_trans_done = 1;
}
}
static void bsp_lcd_bus_init(void)
{
/* GPIO外设 */
RCC_APB2PeriphClockCmd(BSP_LCD_GPIO_PORT_RCC, ENABLE);
GPIO_InitTypeDef gpio_conf;
GPIO_StructInit(&gpio_conf);
gpio_conf.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_conf.GPIO_Speed = GPIO_Speed_50MHz;
gpio_conf.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; //PA5=SPI1_CLK PA7=SPI1_MOSI
GPIO_Init(BSP_LCD_GPIO_PORT, &gpio_conf);
/* SPI外设 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //使能SPI外设时钟
SPI_InitTypeDef spi_conf;
SPI_StructInit(&spi_conf);
spi_conf.SPI_Direction = SPI_Direction_1Line_Tx; //仅发送
spi_conf.SPI_Mode = SPI_Mode_Master;
spi_conf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
spi_conf.SPI_FirstBit = SPI_FirstBit_MSB;
spi_conf.SPI_DataSize = SPI_DataSize_8b;
spi_conf.SPI_CPOL = SPI_CPOL_High;
spi_conf.SPI_CPHA = SPI_CPHA_2Edge;
spi_conf.SPI_NSS = SPI_NSS_Soft;
SPI_Init(SPI1, &spi_conf);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); //使能SPI发送DMA请求
SPI_Cmd(SPI1, ENABLE);
/* DMA外设及中断 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
NVIC_InitTypeDef nvic_conf;
nvic_conf.NVIC_IRQChannel = DMA1_Channel3_IRQn;
nvic_conf.NVIC_IRQChannelPreemptionPriority = 0;
nvic_conf.NVIC_IRQChannelSubPriority = 0;
nvic_conf.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_conf);
}
void bsp_lcd_init(void)
{
/* 初始化非SPI的GPIO */
RCC_APB2PeriphClockCmd(BSP_LCD_GPIO_PORT_RCC, ENABLE);
GPIO_InitTypeDef gpio_conf;
GPIO_StructInit(&gpio_conf);
gpio_conf.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_conf.GPIO_Speed = GPIO_Speed_50MHz;
gpio_conf.GPIO_Pin = BSP_LCD_CS_GPIO | BSP_LCD_DC_GPIO | BSP_LCD_RST_GPIO;
GPIO_Init(BSP_LCD_GPIO_PORT, &gpio_conf);
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO | BSP_LCD_DC_GPIO);
GPIO_ResetBits(BSP_LCD_GPIO_PORT, BSP_LCD_RST_GPIO); // RST=0
Delay_Ms(10);
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_RST_GPIO); // RST=1
Delay_Ms(50);
/* 初始化连接LCD的SPI */
bsp_lcd_bus_init();
lcd_reg_init_ili9341(); //初始化LCD寄存器
Delay_Ms(50); //等待屏幕工作正常
bsp_lcd_switch(1); //开显示
}
static void bsp_lcd_send_color(const uint8_t *data, uint32_t len)
{
SPI_DataSizeConfig(SPI1, SPI_DataSize_16b);
DMA_InitTypeDef dma_conf;
dma_conf.DMA_BufferSize = len;
dma_conf.DMA_M2M = DMA_M2M_Disable;
dma_conf.DMA_DIR = DMA_DIR_PeripheralDST;
dma_conf.DMA_MemoryBaseAddr = (uint32_t)data;
dma_conf.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma_conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_conf.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DATAR);
dma_conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dma_conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_conf.DMA_Priority = DMA_Priority_Medium;
dma_conf.DMA_Mode = DMA_Mode_Normal;
DMA_Init(DMA1_Channel3, &dma_conf);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE); //开启DMA传输完成中断
GPIO_ResetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=0
DMA_Cmd(DMA1_Channel3, ENABLE); //启动传输
}
void bsp_lcd_draw_rect(uint16_t x_start, uint16_t y_start,uint16_t x_end, uint16_t y_end, const void *color_data)
{
uint8_t tx_data[4];
tx_data[0] = x_start>>8; //起始地址高8位
tx_data[1] = x_start&0xFF; //起始地址高8位
tx_data[2] = x_end>>8; //结束地址高8位
tx_data[3] = x_end&0xFF; //结束地址高8位
bsp_lcd_send_cmd(0x2A); //设置X坐标
bsp_lcd_send_data(tx_data, 4);
tx_data[0] = y_start>>8;
tx_data[1] = y_start&0xFF;
tx_data[2] = y_end>>8;
tx_data[3] = y_end&0xFF;
bsp_lcd_send_cmd(0x2B); //设置Y坐标
bsp_lcd_send_data(tx_data, 4);
bsp_lcd_send_cmd(0x2C); //开始写GRAM
bsp_lcd_send_color(color_data, (x_end - x_start + 1) * (y_end - y_start + 1));
}
uint8_t bsp_lcd_get_trans_stat(void)
{
if (bsp_lcd_trans_done == 1) {
bsp_lcd_trans_done = 0;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(BSP_LCD_GPIO_PORT, BSP_LCD_CS_GPIO); //CS=1
return 1;
} else {
return 0;
}
}