259 lines
7.3 KiB
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;
|
|
}
|
|
}
|