找了很久都没有cubmx来配置原子RGB屏幕的,于是自己写一个, 我的分辨率是7寸1024x600
使用RGB屏幕前提是配置好SDRAM,因为需要缓冲区是建立在SDRAM上面, 如何配置请看我这个文章https://blog.youkuaiyun.com/a2267542848/article/details/110944197
如果是其他RGB分辨率,需要改的地方有
1 时序
2 宏定义 分辨率
3 LCD时钟
硬件接口
一定要注意引脚对应,不然会点不亮屏幕
cubmex配置
1 打开DMA2D
2 打开LTDC
宏定义, 因为在配置时序和缓冲区都要分辨率, 所以直接配置为宏定义
1 配置时序,这个PIXEL_W是宏定义, 在user constants里面我定义为1024 , 其他时序自己看原子的, 我的是1024分辨率就配置这
如果屏幕不能显示, 检查一下是否为这个配置, 记住一定要Decinmal, 下面才会计算20-1+40这些
2 配置缓冲区
注意Alpha这个是255
3 配置宏定义(可选)
4 修改IO
因为默认的LTDC IO口不是原子屏幕的接口,所以需要调整IO口, 另外注意要把PB5这个引脚设置为输出, 这个是液晶背光控制
原子屏幕是没有DISP这个引脚的, 只有野火才有
IO口速度要设置为High, 有一次我设置为LOW, 结果跑不起
/**LTDC GPIO Configuration
PI9 ------> LTDC_VSYNC
PI10 ------> LTDC_HSYNC
PF10 ------> LTDC_DE
PH9 ------> LTDC_R3
PH10 ------> LTDC_R4
PH11 ------> LTDC_R5
PH12 ------> LTDC_R6
PG6 ------> LTDC_R7
PG7 ------> LTDC_CLK
PH13 ------> LTDC_G2
PH14 ------> LTDC_G3
PH15 ------> LTDC_G4
PI0 ------> LTDC_G5
PI1 ------> LTDC_G6
PI2 ------> LTDC_G7
PG11 ------> LTDC_B3
PI4 ------> LTDC_B4
PI5 ------> LTDC_B5
PI6 ------> LTDC_B6
PI7 ------> LTDC_B7
*/
5 修改LCD_TFT时钟
我这个1024x600的时钟为45M, 其他分辨率请看原子文档
如果屏幕出现花屏, 就把时钟改小点, 改到25M, 如果是7寸1024x600 可以跑到45M时钟,如果不能跑到45M, 检查SDRAM时序和突发传输, 另外检查layer是不是只设置了一个
3 代码修改
ltdc.c 头部
/* USER CODE BEGIN 0 */
#include "dma2d.h"
//LCD帧缓冲区首地址,这里定义在SDRAM里面.
#define LCD_FRAME_BUF_ADDR 0XC0000000
//定义最大屏分辨率时,LCD所需的帧缓存数组大小
uint16_t g_ltdc_framebuf[PIXELS_W][PIXELS_H] __attribute__((at(LCD_FRAME_BUF_ADDR)));
/* USER CODE END 0 */
自定义函数
/* USER CODE BEGIN 1 */
//LTDC填充矩形,DMA2D填充
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+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(PIXELS_DIR) //横屏
{
psx=sx;psy=sy;
pex=ex;pey=ey;
}else //竖屏
{
psx=sy;psy=PIXELS_H-ex-1;
pex=ey;pey=PIXELS_H-sx-1;
}
offline=PIXELS_W-(pex-psx+1);
addr=(LCD_FRAME_BUF_ADDR+2*(PIXELS_W*psy+psx));
__HAL_RCC_DMA2D_CLK_ENABLE(); //使能DM2D时钟
DMA2D->CR&=~(DMA2D_CR_START); //先停止DMA2D
DMA2D->CR=DMA2D_R2M; //寄存器到存储器模式
DMA2D->OPFCCR=LTDC_PIXEL_FORMAT_RGB565; //设置颜色格式
DMA2D->OOR=offline; //设置行偏移
DMA2D->OMAR=addr; //输出存储器地址
DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16); //设定行数寄存器
DMA2D->OCOLR=color; //设定输出颜色寄存器
DMA2D->CR|=DMA2D_CR_START; //启动DMA2D
while((DMA2D->ISR&(DMA2D_FLAG_TC))==0) //等待传输完成
{
timeout++;
if(timeout>0X1FFFFF)break; //超时退出
}
DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志
}
// 清屏
void LTDC_Clear(uint32_t color)
{
LTDC_Fill(0,0,PIXELS_H-1,PIXELS_W-1,color);
}
// 电源打开
void LTDC_ON(void)
{
HAL_GPIO_WritePin(LCD_BK_GPIO_Port,LCD_BK_Pin,1);
}
// 电源关闭
void LTDC_OFF(void)
{
HAL_GPIO_WritePin(LCD_BK_GPIO_Port,LCD_BK_Pin,0);
}
// 初始化
void LTDC_Init(void)
{
HAL_LTDC_SetWindowPosition(&hltdc,0,0,0); //设置窗口的位置
HAL_LTDC_SetWindowSize(&hltdc,PIXELS_W,PIXELS_H,0);//设置窗口大小
LTDC_ON();
LTDC_Clear(0XFFFFFFFF); //清屏
return;
}
/* USER CODE END 1 */
ltdc.h
/* USER CODE BEGIN Private defines */
//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
/* USER CODE END Private defines */
void MX_LTDC_Init(void);
/* USER CODE BEGIN Prototypes */
void LTDC_Init(void);
void LTDC_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint32_t color);
void LTDC_Clear(uint32_t color);
/* USER CODE END Prototypes */
主函数调用
/* USER CODE BEGIN 2 */
MX_SDRAM_InitEx();
LTDC_Init();
HAL_Delay(1000);
LTDC_Clear(YELLOW);
HAL_Delay(1000);
LTDC_Clear(BLUE);
HAL_Delay(1000);
LTDC_Clear(RED);
/* USER CODE END 2 */
效果
下载地址:
git: https://github.com/KiritoGoLeon/stm32-HAL-learn/tree/master/stm32_f429_rgb_lcd
csdn: https://download.youkuaiyun.com/download/a2267542848/13626887
视频: https://www.bilibili.com/video/BV1cA411s7X7