#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; } }