#include "bsp_ltdc.h" #include "elog.h" uint8_t *DISP_BUF[2]; extern LTDC_HandleTypeDef hltdc; LTDC_HandleTypeDef *Ltdc_Handler = &hltdc; // LCD_DrawPropTypeDef DrawProp[2]; // 每层的渲染参数 static void LCD_GPIO_Config(void); MY_LTDC_TypeDef my_ltdc = { // 0, 0, 0, 0, // 像素宽 像素高 宽度 高度 0, 0, // 像素宽 像素高 // 0,4, // 横屏还是竖屏控制:0,竖屏;1,横屏,像素大小。 0, 0, 0, 0, 0, 0, //hsw HSYNC宽度 ,vsw VSYNC宽度 // hbp HSYNC后的无效像素, vbp VSYNC后的无效行数 //hfp HSYNC前的无效像素 ,vfp,/VSYNC前的无效行数 0xFFFF, //LCD ID 0, //activelayer // {LCD_BUF_ADDRESS,LCD_BUF_ADDRESS}, // Layer_Addr }; // LTDC初始化函数 void LTDC_Init(void) { if (Ltdc_Handler->State != HAL_LTDC_STATE_RESET) { HAL_LTDC_MspDeInit(Ltdc_Handler); // 去初始化 HAL_Delay(200); } if (my_ltdc.id == 0xFFFF) { LTDC_PanelID_Read(); } RCC_PeriphCLKInitTypeDef periph_clk_init_struct; __HAL_RCC_LTDC_CLK_ENABLE(); // 使能LTDC时钟 __HAL_RCC_DMA2D_CLK_ENABLE(); // 使能LTDC时钟 HAL_LTDC_MspInit(Ltdc_Handler); // TODO 不同方向会导致 消隐变化?? Ltdc_Handler->Instance = LTDC; Ltdc_Handler->Init.HorizontalSync = my_ltdc.hsw-1; Ltdc_Handler->Init.VerticalSync = my_ltdc.vsw-1; Ltdc_Handler->Init.AccumulatedHBP = my_ltdc.hsw + my_ltdc.hbp-1; Ltdc_Handler->Init.AccumulatedVBP = my_ltdc.vsw + my_ltdc.vbp-1; Ltdc_Handler->Init.AccumulatedActiveW = my_ltdc.hsw + my_ltdc.hbp + my_ltdc.pixel_width -1; Ltdc_Handler->Init.AccumulatedActiveH = my_ltdc.vsw + my_ltdc.vbp+ my_ltdc.pixel_height -1; Ltdc_Handler->Init.TotalWidth = my_ltdc.hsw + my_ltdc.hbp + my_ltdc.pixel_width + my_ltdc.hfp -1; Ltdc_Handler->Init.TotalHeigh = my_ltdc.vsw + my_ltdc.vbp+ my_ltdc.pixel_height + my_ltdc.vfp -1; LTDC_Clk_Set(60, 2,4); // periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; // periph_clk_init_struct.PLLSAI.PLLSAIN = 60; // periph_clk_init_struct.PLLSAI.PLLSAIR = 2; // periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_2; // HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct); Ltdc_Handler->Init.HSPolarity = LTDC_HSPOLARITY_AL; Ltdc_Handler->Init.VSPolarity = LTDC_VSPOLARITY_AL; Ltdc_Handler->Init.DEPolarity = LTDC_DEPOLARITY_AL; Ltdc_Handler->Init.PCPolarity = LTDC_PCPOLARITY_IPC; // if(my_ltdc.id==0X1018)LTDC_Handler.Init.PCPolarity=LTDC_PCPOLARITY_IIPC;//像素时钟极性 // else LTDC_Handler.Init.PCPolarity=LTDC_PCPOLARITY_IPC; //像素时钟极性 Ltdc_Handler->Init.Backcolor.Blue = 0; Ltdc_Handler->Init.Backcolor.Green = 0; Ltdc_Handler->Init.Backcolor.Red = 0; /* 初始化LCD的像素宽度和高度 */ Ltdc_Handler->LayerCfg->ImageWidth = my_ltdc.pixel_width; Ltdc_Handler->LayerCfg->ImageHeight = my_ltdc.pixel_height; /* 设置LCD背景层的颜色,默认黑色 */ Ltdc_Handler->Init.Backcolor.Red = 0; Ltdc_Handler->Init.Backcolor.Green = 0; Ltdc_Handler->Init.Backcolor.Blue = 0; HAL_LTDC_Init(Ltdc_Handler); // #if LCD_PIXFORMAT == LTDC_PIXEL_FORMAT_ARGB8888 || LCD_PIXFORMAT == LTDC_PIXEL_FORMAT_RGB888 // my_ltdc.pixelsize = 4; // 每个像素占4个字节 // #else // my_ltdc.pixelsize = 2; // 每个像素占2个字节 // #endif // my_ltdc.layeraddr[0] = LCD_BUF_ADDRESS; // my_ltdc.layeraddr[1] = LCD_BUF_ADDRESS + my_ltdc.pixel_width * my_ltdc.pixel_height * my_ltdc.pixelsize; // my_ltdc.width = my_ltdc.pixel_width; // my_ltdc.height = my_ltdc.pixel_height; //层配置 // LTDC_Layer_Parameter_Config(0,(uint32_t)my_ltdc.layeraddr[0],LCD_PIXFORMAT,255,0,6,7,LTDC_COLOR_GREEN);//层参数配置 // LTDC_Layer_Window_Config(0,0,0,my_ltdc.pixel_width,my_ltdc.pixel_height); //层窗口配置,以LCD面板坐标系为基准,不要随便修改! // LTDC_Display_Dir(1); // 0竖屏 1横屏 // LTDC_Select_Layer(0); //选择第1层 // LTDC_Clear(LTDC_COLOR_GREEN); //清屏 // LTDC_DISP_ON() LTDC_Enable_Line_IT( my_ltdc.vsw+my_ltdc.vbp+my_ltdc.pixel_height-1 ); // 行中断设置, 参考寄存器编程开启行中断方法 } // LTDC时钟(Fdclk)设置函数 // Fvco=Fin*pllsain; // Fdclk=Fvco/pllsair/2*2^pllsaidivr=Fin*pllsain/pllsair/2*2^pllsaidivr; // Fvco:VCO频率 // Fin:输入时钟频率一般为1Mhz(来自系统时钟PLLM分频后的时钟,见时钟树图) // pllsain:SAI时钟倍频系数N,取值范围:50~432. // pllsair:SAI时钟的分频系数R,取值范围:2~7 // pllsaidivr:LCD时钟分频系数,取值范围:0~3,对应分频2^(pllsaidivr+1) // 假设:外部晶振为25M,pllm=25的时候,Fin=1Mhz. // 例如:要得到20M的LTDC时钟,则可以设置:pllsain=400,pllsair=5,pllsaidivr=1 // Fdclk=1*396/3/2*2^1=396/12=33Mhz // 返回值:0,成功;1,失败。 uint8_t LTDC_Clk_Set(uint32_t pllsain, uint32_t pllsair, uint32_t pllsaidivr) { RCC_PeriphCLKInitTypeDef PeriphClkIniture; //LTDC输出像素时钟,需要根据自己所使用的LCD数据手册来配置! PeriphClkIniture.PeriphClockSelection=RCC_PERIPHCLK_LTDC; //LTDC时钟 PeriphClkIniture.PLLSAI.PLLSAIN=pllsain; PeriphClkIniture.PLLSAI.PLLSAIR=pllsair; PeriphClkIniture.PLLSAIDivR=pllsaidivr; if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkIniture)==HAL_OK) //配置像素时钟 { return 0; //成功 } else return 1; //失败 } // LTDC,层窗口设置,窗口以LCD面板坐标系为基准 // 注意:此函数必须在LTDC_Layer_Parameter_Config之后再设置.另外,当设置的窗口值不等于面板的尺 // 寸时,GRAM的操作(读/写点函数),也要根据窗口的宽高来进行修改,否则显示不正常(本例程就未做修改). // layerx:层值,0/1. // sx,sy:起始坐标 // width,height:宽度和高度 void LTDC_Layer_Window_Config(uint8_t layerx, uint16_t sx, uint16_t sy, uint16_t width, uint16_t height) { HAL_LTDC_SetWindowPosition(Ltdc_Handler, sx, sy, layerx); //设置窗口的位置 HAL_LTDC_SetWindowSize(Ltdc_Handler, width, height, layerx);//设置窗口大小 } // LTDC,基本参数设置. // 注意:此函数,必须在LTDC_Layer_Window_Config之前设置. // layerx:层值,0/1. // bufaddr:层颜色帧缓存起始地址 // pixformat:颜色格式.0,ARGB8888;1,RGB888;2,RGB565;3,ARGB1555;4,ARGB4444;5,L8;6;AL44;7;AL88 // alpha:层颜色Alpha值,0,全透明;255,不透明 // alpha0:默认颜色Alpha值,0,全透明;255,不透明 // bfac1:混合系数1,4(100),恒定的Alpha;6(101),像素Alpha*恒定Alpha // bfac2:混合系数2,5(101),恒定的Alpha;7(111),像素Alpha*恒定Alpha // bkcolor:层默认颜色,32位,低24位有效,RGB888格式 // 返回值:无 void LTDC_Layer_Parameter_Config(uint8_t layerx, uint32_t bufaddr, uint8_t pixformat, uint8_t alpha, uint8_t alpha0, uint8_t bfac1, uint8_t bfac2, uint32_t bkcolor) { LTDC_LayerCfgTypeDef pLayerCfg; pLayerCfg.WindowX0=0; //窗口起始X坐标 pLayerCfg.WindowY0=0; //窗口起始Y坐标 pLayerCfg.WindowX1=my_ltdc.pixel_width; //窗口终止X坐标 pLayerCfg.WindowY1=my_ltdc.pixel_height; //窗口终止Y坐标 pLayerCfg.PixelFormat=pixformat; //像素格式 pLayerCfg.Alpha=alpha; //Alpha值设置,0~255,255为完全不透明 pLayerCfg.Alpha0=alpha0; //默认Alpha值 pLayerCfg.BlendingFactor1=(uint32_t)bfac1<<8; //设置层混合系数 pLayerCfg.BlendingFactor2=(uint32_t)bfac2<<8; //设置层混合系数 pLayerCfg.FBStartAdress=bufaddr; //设置层颜色帧缓存起始地址 pLayerCfg.ImageWidth=my_ltdc.pixel_width; //设置颜色帧缓冲区的宽度 pLayerCfg.ImageHeight=my_ltdc.pixel_height; //设置颜色帧缓冲区的高度 pLayerCfg.Backcolor.Red=(uint8_t)(bkcolor&0X00FF0000)>>16; //背景颜色红色部分 pLayerCfg.Backcolor.Green=(uint8_t)(bkcolor&0X0000FF00)>>8; //背景颜色绿色部分 pLayerCfg.Backcolor.Blue=(uint8_t)bkcolor&0X000000FF; //背景颜色蓝色部分 HAL_LTDC_ConfigLayer( Ltdc_Handler,&pLayerCfg,layerx); //设置所选中的层 } // 开关指定层 // layerx:层号;0,第一层;1,第二层; // sw:1,打开;0,关闭 void LTDC_Layer_Switch(uint8_t layerx, uint8_t on_off) { if(on_off==1) __HAL_LTDC_LAYER_ENABLE(Ltdc_Handler,layerx); else if(on_off==0) __HAL_LTDC_LAYER_DISABLE(Ltdc_Handler,layerx); __HAL_LTDC_RELOAD_CONFIG(Ltdc_Handler); } void LTDC_Enable_Line_IT(uint16_t line) { // 配置LTDC行中断 LTDC->LIPCR = line;//配置行中断的行数为最后一行 // LTDC->IER |=LTDC_IER_LIE; //使能LTDC行中断 // LTDC->SRCR |= (1<<1); } // 读取面板参数 // PG6=R7(M0);PI2=G7(M1);PB9=B7(M2); // M2:M1:M0 // 0 :0 :0 //4.3寸480*272 RGB屏,ID=0X4342 // 0 :0 :1 //7寸800*480 RGB屏,ID=0X7084 // 0 :1 :0 //7寸1024*600 RGB屏,ID=0X7016 // 0 :1 :1 //7寸1280*800 RGB屏,ID=0X7018 // 1 :0 :0 //4.3寸800*480 RGB屏,ID=0X4384 // 1 :0 :1 //10.1寸1280*800 RGB屏,ID=0X1018 // 返回值:LCD ID:0,非法;其他值,ID; uint16_t LTDC_PanelID_Read(void) { uint8_t idx = 0; GPIO_InitTypeDef GPIO_InitStruct; // RCC->AHB1ENR|=1<<6|1<<8|1<<1; //使能PG/PI时钟 __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); idx = HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_6); // 读取M1 idx |= HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_2) << 1; // 读取M0 idx |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) << 2; // 读取M2 switch (idx) { case 0: my_ltdc.id = 0X4342; break; case 1: my_ltdc.id = 0X7084; break; case 2: my_ltdc.id = 0X7016; break; case 3: my_ltdc.id = 0X7018; break; case 4: my_ltdc.id = 0X4384; break; case 5: my_ltdc.id = 0X1018; break; default: my_ltdc.id = 0xFFFF; break; } // TODO :hsw hbp反了 vsw vbp反了 4342已改 if (my_ltdc.id == 0X4342) { my_ltdc.pixel_width = 480; // 面板宽度,单位:像素 my_ltdc.pixel_height = 272; // 面板高度,单位:像素 my_ltdc.hsw = 41; // 水平同步宽度 my_ltdc.vsw = 10; // 垂直同步宽度 my_ltdc.hbp = 8; // 水平后廊 my_ltdc.vbp = 2; // 垂直后廊 // my_ltdc.hsw = 8; // 水平同步宽度 // my_ltdc.vsw = 2; // 垂直同步宽度 // my_ltdc.hbp = 41; // 水平后廊 // my_ltdc.vbp = 10; // 垂直后廊 my_ltdc.hfp = 4; // 水平前廊 my_ltdc.vfp = 4; // 垂直前廊 // LTDC_Clk_Set(288,4,2); //设置像素时钟 9Mhz return my_ltdc.id; } else if (my_ltdc.id == 0X7084) { my_ltdc.pixel_width = 800; // 面板宽度,单位:像素 my_ltdc.pixel_height = 480; // 面板高度,单位:像素 my_ltdc.hsw = 1; // 水平同步宽度 my_ltdc.vsw = 1; // 垂直同步宽度 my_ltdc.hbp = 46; // 水平后廊 my_ltdc.vbp = 23; // 垂直后廊 my_ltdc.hfp = 210; // 水平前廊 my_ltdc.vfp = 22; // 垂直前廊 // LTDC_Clk_Set(396,3,1); //设置像素时钟 33M(如果开双显,需要降低DCLK到:18.75Mhz 300/4/4,才会比较好) return my_ltdc.id; } else if (my_ltdc.id == 0X7016) { my_ltdc.pixel_width = 1024; // 面板宽度,单位:像素 my_ltdc.pixel_height = 600; // 面板高度,单位:像素 my_ltdc.hsw = 20; // 水平同步宽度 my_ltdc.vsw = 3; // 垂直同步宽度 my_ltdc.hbp = 140; // 水平后廊 my_ltdc.vbp = 20; // 垂直后廊 my_ltdc.hfp = 160; // 水平前廊 my_ltdc.vfp = 12; // 垂直前廊 // LTDC_Clk_Set(360,2,1); //设置像素时钟 45Mhz return my_ltdc.id; } else if (my_ltdc.id == 0X7018) { my_ltdc.pixel_width = 1280; // 面板宽度,单位:像素 my_ltdc.pixel_height = 800; // 面板高度,单位:像素 // 其他参数待定. } else if (my_ltdc.id == 0X4384) { my_ltdc.pixel_width = 800; // 面板宽度,单位:像素 my_ltdc.pixel_height = 480; // 面板高度,单位:像素 my_ltdc.hbp = 88; // 水平后廊 my_ltdc.hfp = 40; // 水平前廊 my_ltdc.hsw = 48; // 水平同步宽度 my_ltdc.vbp = 32; // 垂直后廊 my_ltdc.vfp = 13; // 垂直前廊 my_ltdc.vsw = 3; // 垂直同步宽度 // LTDC_Clk_Set(396,3,1); //设置像素时钟 33M return my_ltdc.id; // 其他参数待定. } else if (my_ltdc.id == 0X1018) // 10.1寸1280*800 RGB屏 { my_ltdc.pixel_width = 1280; // 面板宽度,单位:像素 my_ltdc.pixel_height = 800; // 面板高度,单位:像素 my_ltdc.hbp = 140; // 水平后廊 my_ltdc.hfp = 10; // 水平前廊 my_ltdc.hsw = 10; // 水平同步宽度 my_ltdc.vbp = 10; // 垂直后廊 my_ltdc.vfp = 10; // 垂直前廊 my_ltdc.vsw = 3; // 垂直同步宽度 LTDC_Clk_Set(360, 2, 1); // 设置像素时钟 45Mhz return my_ltdc.id; } return 0XFFFF; } void LTDC_IRQHandler(void) { log_i(" LTDC_IRQHandler ..... "); HAL_LTDC_IRQHandler(Ltdc_Handler); } // void LCD_LayerInit(uint16_t LayerIndex, uint32_t FB_Address,uint32_t PixelFormat) // { // LTDC_LayerCfgTypeDef layer_cfg; // /* 层初始化 */ // layer_cfg.WindowX0 = 0; //窗口起始位置X坐标 // layer_cfg.WindowX1 = 480; //窗口结束位置X坐标 // layer_cfg.WindowY0 = 0; //窗口起始位置Y坐标 // layer_cfg.WindowY1 = 272; //窗口结束位置Y坐标 // layer_cfg.PixelFormat = PixelFormat; //像素格式 // layer_cfg.FBStartAdress = FB_Address; //层显存首地址 // layer_cfg.Alpha = 255; //用于混合的透明度常量,范围(0—255)0为完全透明 // layer_cfg.Alpha0 = 0; //默认透明度常量,范围(0—255)0为完全透明 // layer_cfg.Backcolor.Blue = 0; //层背景颜色蓝色分量 // layer_cfg.Backcolor.Green = 0; //层背景颜色绿色分量 // layer_cfg.Backcolor.Red = 0; //层背景颜色红色分量 // layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;//层混合系数1 // layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;//层混合系数2 // layer_cfg.ImageWidth = 480;//设置图像宽度 // layer_cfg.ImageHeight = 272;//设置图像高度 // HAL_LTDC_ConfigLayer(Ltdc_Handler, &layer_cfg, LayerIndex); //设置选中的层参数 // DrawProp[LayerIndex].BackColor = LCD_COLOR_WHITE;//设置层的字体颜色 // DrawProp[LayerIndex].pFont = &LCD_DEFAULT_FONT;//设置层的字体类型 // DrawProp[LayerIndex].TextColor = LCD_COLOR_BLACK; //设置层的字体背景颜色 // __HAL_LTDC_RELOAD_CONFIG(Ltdc_Handler);//重载层的配置参数 // } // // 选择层 // // layerx:层号;0,第一层;1,第二层; // void LTDC_Select_Layer(uint8_t layerx) // { // my_ltdc.activelayer = layerx; // } // // 设置LCD显示方向 // // dir:0,竖屏;1,横屏 // void LTDC_Display_Dir(uint8_t dir) // { // my_ltdc.dir = dir; // 显示方向 // if(dir==0) //竖屏 // { // my_ltdc.width=my_ltdc.pixel_height; // my_ltdc.height=my_ltdc.pixel_width; // }else if(dir==1) //横屏 // { // my_ltdc.width=my_ltdc.pixel_width; // my_ltdc.height=my_ltdc.pixel_height; // } // } // LTDC填充矩形,DMA2D填充 //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1) // 注意:sx,ex,不能大于lcddev.width-1;sy,ey,不能大于lcddev.height-1!!! // color:要填充的颜色 // void LTDC_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color) // { // uint32_t psx, psy, pex, pey; // 以LCD面板为基准的坐标系,不随横竖屏变化而变化 // uint32_t timeout = 0; // uint16_t offline; // uint32_t addr; // // 坐标系转换 // if (my_ltdc.dir) // 横屏 // { // psx = sx; // psy = sy; // pex = ex; // pey = ey; // } // else // 竖屏 // { // psx = sy; // psy = my_ltdc.height - ex - 1; // pex = ey; // pey = my_ltdc.height - sx - 1; // } // offline = my_ltdc.width - (pex - psx + 1); // addr = my_ltdc.layeraddr[my_ltdc.activelayer] + my_ltdc.pixelsize * (my_ltdc.width * psy + psx); // RCC->AHB1ENR |= 1 << 23; // 使能DM2D时钟 // DMA2D->CR &= ~(1 << 0); // 先停止DMA2D // DMA2D->CR = 3 << 16; // 寄存器到存储器模式 // DMA2D->OPFCCR = LCD_PIXFORMAT; // 设置颜色格式 // DMA2D->OOR = offline; // 设置行偏移 // DMA2D->OMAR = addr; // 输出存储器地址 // DMA2D->NLR = (pey - psy + 1) | ((pex - psx + 1) << 16); // 设定行数寄存器 // DMA2D->OCOLR = color; // 设定输出颜色寄存器 // // // 启动传输 阻塞 // DMA2D->CR |= 1 << 0; // 启动DMA2D // while ((DMA2D->ISR & (1 << 1)) == 0) // 等待传输完成 // { // timeout++; // if (timeout > 0X1FFFFF) // break; // 超时退出 // } // DMA2D->IFCR |= 1 << 1; // 清除传输完成标志 // 传输中断 用于数据传输 M2M模式 // DMA2D->CR |= DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE; // DMA2D->CR |= DMA2D_CR_START; // } // 在指定区域内填充指定颜色块,DMA2D填充 // 此函数仅支持uint16_t,RGB565格式的颜色数组填充. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1) // 注意:sx,ex,不能大于lcddev.width-1;sy,ey,不能大于lcddev.height-1!!! // color:要填充的颜色数组首地址 // void LTDC_Color_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color) // { // uint32_t psx, psy, pex, pey; // 以LCD面板为基准的坐标系,不随横竖屏变化而变化 // uint32_t timeout = 0; // uint16_t offline; // uint32_t addr; // // 坐标系转换 // if (my_ltdc.dir) // 横屏 // { // psx = sx; // psy = sy; // pex = ex; // pey = ey; // } // else // 竖屏 // { // psx = sy; // psy = my_ltdc.height - ex - 1; // pex = ey; // pey = my_ltdc.height - sx - 1; // } // offline = my_ltdc.width - (pex - psx + 1); // // if (my_ltdc.activelayer == 0) // // { // // addr = my_ltdc.layeraddr[0] + my_ltdc.pixelsize * (my_ltdc.width * psy + psx); // // } // // else // // { // // addr = my_ltdc.layeraddr[0] + my_ltdc.pixelsize * (my_ltdc.width * psy + psx); // // } // addr = my_ltdc.layeraddr[my_ltdc.activelayer] + my_ltdc.pixelsize * (my_ltdc.width * psy + psx); // RCC->AHB1ENR |= 1 << 23; // 使能DM2D时钟 // DMA2D->CR &= ~(1 << 0); // 先停止DMA2D // DMA2D->CR = 0 << 16; // 存储器到存储器模式 // DMA2D->FGPFCCR = LCD_PIXFORMAT; // 设置颜色格式 // DMA2D->FGOR = 0; // 前景层行偏移为0 // DMA2D->OOR = offline; // 设置行偏移 // DMA2D->FGMAR = (uint32_t)color; // 源地址 // DMA2D->OMAR = addr; // 输出存储器地址 // DMA2D->NLR = (pey - psy + 1) | ((pex - psx + 1) << 16); // 设定行数寄存器 // // // 启动传输 阻塞 // // DMA2D->CR |= 1 << 0; // 启动DMA2D // // while ((DMA2D->ISR & (1 << 1)) == 0) // 等待传输完成 // // { // // timeout++; // // if (timeout > 0X1FFFFF) // // break; // 超时退出 // // } // // DMA2D->IFCR |= 1 << 1; // 清除传输完成标志 // // 传输中断 用于数据传输 M2M模式 // DMA2D->CR |= DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE; // DMA2D->CR |= DMA2D_CR_START; // // // 启动传输 阻塞 // // DMA2D->CR |= DMA2D_CR_START; // // while (DMA2D->CR & DMA2D_CR_START) {} // } // LCD清屏 // color:颜色值 // void LTDC_Clear(uint32_t color) // { // LTDC_Fill(0, 0, my_ltdc.width-1, my_ltdc.height-1, color); // } // void LCD_SetTransparency(uint32_t LayerIndex, uint8_t Transparency) // { // HAL_LTDC_SetAlpha(Ltdc_Handler, Transparency, LayerIndex); // } // if (my_ltdc.id == 0X4342) // { // LTDC_Clk_Set(288, 4, 2); // 设置像素时钟 9Mhz // } // else if (my_ltdc.id == 0X7084) // { // LTDC_Clk_Set(396, 3, 1); // 设置像素时钟 33M(如果开双显,需要降低DCLK到:18.75Mhz 300/4/4,才会比较好) // } // else if (my_ltdc.id == 0X7016) // { // LTDC_Clk_Set(360, 2, 1); // 设置像素时钟 45Mhz // } // else if (my_ltdc.id == 0X7018) // { // // 其他参数待定. // } // else if (my_ltdc.id == 0X4384) // { // LTDC_Clk_Set(396, 3, 1); // 设置像素时钟 33M // // 其他参数待定. // } // else if (my_ltdc.id == 0X1018) // 10.1寸1280*800 RGB屏 // { // LTDC_Clk_Set(360, 2, 1); // 设置像素时钟 45Mhz // } // tempreg = 0 << 28; // 像素时钟极性:不反向 // if (my_ltdc.id == 0X1018) // tempreg = 1 << 28; // 像素时钟极性:反向 // tempreg |= 0 << 29; // 数据使能极性:低电平有效 // tempreg |= 0 << 30; // 垂直同步极性:低电平有效 // tempreg |= 0 << 31; // 水平同步极性:低电平有效 // LTDC->GCR = tempreg; // 设置全局控制寄存器 // tempreg = (my_ltdc.vsw - 1) << 0; // 垂直脉宽-1 // tempreg |= (my_ltdc.hsw - 1) << 16; // 水平脉宽-1 // LTDC->SSCR = tempreg; // 设置同步大小配置寄存器 // tempreg = (my_ltdc.vsw + my_ltdc.vbp - 1) << 0; // 累加垂直后沿=垂直脉宽+垂直后沿-1 // tempreg |= (my_ltdc.hsw + my_ltdc.hbp - 1) << 16; // 累加水平后沿=水平脉宽+水平后沿-1 // LTDC->BPCR = tempreg; // 设置后沿配置寄存器 // tempreg = (my_ltdc.vsw + my_ltdc.vbp + my_ltdc.height - 1) << 0; // 累加有效高度=垂直脉宽+垂直后沿+垂直分辨率-1 // tempreg |= (my_ltdc.hsw + my_ltdc.hbp + my_ltdc.width - 1) << 16; // 累加有效宽度=水平脉宽+水平后沿+水平分辨率-1 // LTDC->AWCR = tempreg; // 设置有效宽度配置寄存器 // tempreg = (my_ltdc.vsw + my_ltdc.vbp + my_ltdc.height + my_ltdc.vfp - 1) << 0; // 总高度=垂直脉宽+垂直后沿+垂直分辨率+垂直前廊-1 // tempreg |= (my_ltdc.hsw + my_ltdc.hbp + my_ltdc.width + my_ltdc.hfp - 1) << 16; // 总宽度=水平脉宽+水平后沿+水平分辨率+水平前廊-1 // LTDC->TWCR = tempreg; // 设置总宽度配置寄存器 // LTDC->BCCR = LCD_COLOR_GREEN; // 设置背景层颜色寄存器(RGB888格式) // static void LCD_GPIO_Config(void) // { // GPIO_InitTypeDef GPIO_InitStruct; // /* 使能LCD使用到的引脚时钟 */ // //红色数据线 // LTDC_R0_GPIO_CLK_ENABLE();LTDC_R1_GPIO_CLK_ENABLE();LTDC_R2_GPIO_CLK_ENABLE();\ // LTDC_R3_GPIO_CLK_ENABLE();LTDC_R4_GPIO_CLK_ENABLE();LTDC_R5_GPIO_CLK_ENABLE();\ // LTDC_R6_GPIO_CLK_ENABLE();LTDC_R7_GPIO_CLK_ENABLE();LTDC_G0_GPIO_CLK_ENABLE();\ // LTDC_G1_GPIO_CLK_ENABLE();LTDC_G2_GPIO_CLK_ENABLE();LTDC_G3_GPIO_CLK_ENABLE();\ // LTDC_G3_GPIO_CLK_ENABLE();LTDC_G5_GPIO_CLK_ENABLE();LTDC_G6_GPIO_CLK_ENABLE();\ // LTDC_G7_GPIO_CLK_ENABLE();LTDC_B0_GPIO_CLK_ENABLE();LTDC_B1_GPIO_CLK_ENABLE();\ // LTDC_B2_GPIO_CLK_ENABLE();LTDC_B3_GPIO_CLK_ENABLE();LTDC_B4_GPIO_CLK_ENABLE();\ // LTDC_B5_GPIO_CLK_ENABLE();LTDC_B6_GPIO_CLK_ENABLE();LTDC_B7_GPIO_CLK_ENABLE();\ // LTDC_CLK_GPIO_CLK_ENABLE();LTDC_HSYNC_GPIO_CLK_ENABLE();LTDC_VSYNC_GPIO_CLK_ENABLE();\ // LTDC_DE_GPIO_CLK_ENABLE();LTDC_DISP_GPIO_CLK_ENABLE();LTDC_BL_GPIO_CLK_ENABLE(); // /* GPIO配置 */ // /* 红色数据线 */ // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_PULLUP; // GPIO_InitStruct.Pin = LTDC_R0_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R0_AF; // HAL_GPIO_Init(LTDC_R0_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R1_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R1_AF; // HAL_GPIO_Init(LTDC_R1_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R2_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R2_AF; // HAL_GPIO_Init(LTDC_R2_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R3_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R3_AF; // HAL_GPIO_Init(LTDC_R3_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R4_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R4_AF; // HAL_GPIO_Init(LTDC_R4_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R5_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R5_AF; // HAL_GPIO_Init(LTDC_R5_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R6_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R6_AF; // HAL_GPIO_Init(LTDC_R6_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_R7_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_R7_AF; // HAL_GPIO_Init(LTDC_R7_GPIO_PORT, &GPIO_InitStruct); // //绿色数据线 // GPIO_InitStruct.Pin = LTDC_G0_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G0_AF; // HAL_GPIO_Init(LTDC_G0_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G1_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G1_AF; // HAL_GPIO_Init(LTDC_G1_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G2_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G2_AF; // HAL_GPIO_Init(LTDC_G2_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G3_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G3_AF; // HAL_GPIO_Init(LTDC_G3_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G4_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G4_AF; // HAL_GPIO_Init(LTDC_G4_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G5_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G5_AF; // HAL_GPIO_Init(LTDC_G5_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G6_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G6_AF; // HAL_GPIO_Init(LTDC_G6_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_G7_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_G7_AF; // HAL_GPIO_Init(LTDC_G7_GPIO_PORT, &GPIO_InitStruct); // //蓝色数据线 // GPIO_InitStruct.Pin = LTDC_B0_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B0_AF; // HAL_GPIO_Init(LTDC_B0_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B1_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B1_AF; // HAL_GPIO_Init(LTDC_B1_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B2_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B2_AF; // HAL_GPIO_Init(LTDC_B2_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B3_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B3_AF; // HAL_GPIO_Init(LTDC_B3_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B4_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B4_AF; // HAL_GPIO_Init(LTDC_B4_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B5_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B5_AF; // HAL_GPIO_Init(LTDC_B5_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B6_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B6_AF; // HAL_GPIO_Init(LTDC_B6_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_B7_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_B7_AF; // HAL_GPIO_Init(LTDC_B7_GPIO_PORT, &GPIO_InitStruct); // //控制信号线 // GPIO_InitStruct.Pin = LTDC_CLK_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_CLK_AF; // HAL_GPIO_Init(LTDC_CLK_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_HSYNC_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_HSYNC_AF; // HAL_GPIO_Init(LTDC_HSYNC_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_VSYNC_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_VSYNC_AF; // HAL_GPIO_Init(LTDC_VSYNC_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_DE_GPIO_PIN; // GPIO_InitStruct.Alternate = LTDC_DE_AF; // HAL_GPIO_Init(LTDC_DE_GPIO_PORT, &GPIO_InitStruct); // //背光BL 及液晶使能信号DISP // GPIO_InitStruct.Pin = LTDC_DISP_GPIO_PIN; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_InitStruct.Pull = GPIO_PULLUP; // HAL_GPIO_Init(LTDC_DISP_GPIO_PORT, &GPIO_InitStruct); // GPIO_InitStruct.Pin = LTDC_BL_GPIO_PIN; // HAL_GPIO_Init(LTDC_BL_GPIO_PORT, &GPIO_InitStruct); // } // RCC_PeriphCLKInitTypeDef periph_clk_init_struct; // __HAL_RCC_LTDC_CLK_ENABLE(); // 使能LTDC时钟 // __HAL_RCC_DMA2D_CLK_ENABLE(); // 使能DMA2D时钟 // /* 初始化LCD引脚 */ // HAL_LTDC_MspInit(Ltdc_Handler); // // LCD_GPIO_Config(); // /* 初始化SDRAM 用作LCD 显存*/ // // SDRAM_Init(); // /* 配置LTDC参数 */ // Ltdc_Handler->Instance = LTDC; // /* 配置行同步信号宽度(HSW-1) */ // Ltdc_Handler->Init.HorizontalSync =hsw-1; // /* 配置垂直同步信号宽度(VSW-1) */ // Ltdc_Handler->Init.VerticalSync = vsw-1; // /* 配置(HSW+HBP-1) */ // Ltdc_Handler->Init.AccumulatedHBP = hsw+hbp-1; // /* 配置(VSW+VBP-1) */ // Ltdc_Handler->Init.AccumulatedVBP = vsw+vbp-1; // /* 配置(HSW+HBP+有效像素宽度-1) */ // Ltdc_Handler->Init.AccumulatedActiveW = hsw+hbp+480-1; // /* 配置(VSW+VBP+有效像素高度-1) */ // Ltdc_Handler->Init.AccumulatedActiveH = vsw+vbp+272-1; // /* 配置总宽度(HSW+HBP+有效像素宽度+HFP-1) */ // Ltdc_Handler->Init.TotalWidth =hsw+ hbp+480 + hfp-1; // /* 配置总高度(VSW+VBP+有效像素高度+VFP-1) */ // Ltdc_Handler->Init.TotalHeigh =vsw+ vbp+272 + vfp-1; // /* 液晶屏时钟配置 */ // /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ // /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ // /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz */ // /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6Mhz */ // periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; // periph_clk_init_struct.PLLSAI.PLLSAIN = 60; // periph_clk_init_struct.PLLSAI.PLLSAIR = 2; // periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_4; // HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct); // /* 初始化LCD的像素宽度和高度 */ // Ltdc_Handler->LayerCfg->ImageWidth = 480; // Ltdc_Handler->LayerCfg->ImageHeight = 272; // /* 设置LCD背景层的颜色,默认黑色 */ // Ltdc_Handler->Init.Backcolor.Red = 0; // Ltdc_Handler->Init.Backcolor.Green = 0; // Ltdc_Handler->Init.Backcolor.Blue = 0; // /* 极性配置 */ // /* 初始化行同步极性,低电平有效 */ // Ltdc_Handler->Init.HSPolarity = LTDC_HSPOLARITY_AL; // /* 初始化场同步极性,低电平有效 */ // Ltdc_Handler->Init.VSPolarity = LTDC_VSPOLARITY_AL; // /* 初始化数据有效极性,低电平有效 */ // Ltdc_Handler->Init.DEPolarity = LTDC_DEPOLARITY_AL; // /* 初始化行像素时钟极性,同输入时钟 */ // Ltdc_Handler->Init.PCPolarity = LTDC_PCPOLARITY_IPC; // HAL_LTDC_Init(Ltdc_Handler); // /* 初始化字体 */ // // LCD_SetFont(&LCD_DEFAULT_FONT); // uint32_t tempreg = 0; // //画点函数 // //x,y:写入坐标 // //color:颜色值 // void LTDC_Draw_Point(uint16_t x,uint16_t y,uint32_t color) // { // #if LCD_PIXFORMAT==LCD_PIXFORMAT_ARGB8888||LCD_PIXFORMAT==LCD_PIXFORMAT_RGB888 // if(my_ltdc.dir) //横屏 // { // *(uint32_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*y+x))=color; // }else //竖屏 // { // *(uint32_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*(my_ltdc.pixel_height-x)+y))=color; // } // #else // if(my_ltdc.dir) //横屏 // { // *(uint16_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*y+x))=color; // }else //竖屏 // { // *(uint16_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*(my_ltdc.pixel_height-x-1)+y))=color; // } // #endif // } // //读点函数 // //x,y:读取点的坐标 // //返回值:颜色值 // uint32_t LTDC_Read_Point(uint16_t x,uint16_t y) // { // #if LCD_PIXFORMAT==LCD_PIXFORMAT_ARGB8888||LCD_PIXFORMAT==LCD_PIXFORMAT_RGB888 // if(my_ltdc.dir) //横屏 // { // return *(uint32_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*y+x)); // }else //竖屏 // { // return *(uint32_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*(my_ltdc.pixel_height-x)+y)); // } // #else // if(my_ltdc.dir) //横屏 // { // return *(uint16_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*y+x)); // }else //竖屏 // { // return *(uint16_t*)((uint32_t)my_ltdc.layeraddr[my_ltdc.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*(my_ltdc.pixel_height-x-1)+y)); // } // #endif // }