目录

银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-09-23 gingko 初次建立

STM32CubeMX教程六十——LCD实验驱动4.3寸液晶屏

1.在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 3.配置RCC,使用外部时钟源 4.时基源选择SysTick 5.配置GPIO和引脚模式,引脚为PA10,PB4,PB7,PB8,PF6,PI1,PI2,PI3。 6.配置LTDC,引脚为PA8,PC7,PD3,PF10,PG6,PG7,PG10,PG12,PH9,PH10,PH11,PH12,PH13,PH15,PI0,PI5,PI6,PI7,PI9,PI10。 7.配置TIM12。 8.配置FMC,引脚为PD0,PD1,PD8,PD9,PD10,PD14,PD15,PE0,PE1,PE7,PE8,PE9,PE10,PE11,PE12,PE13,PE14,PE15,PF0,PF1,PF2,PF3,PF4,PF5,PF11,PF12,PF13,PF14,PF15,PG0,PG1,PG2,PG4,PG5,PG8,PG15,PH2,PH3,PH5。 9.时钟源设置,选择外部高速时钟源,配置为最大主频。 10.工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27 11.点击Code Generator,进行进一步配置

12.然后点击GENERATE CODE 创建工程 创建成功,打开工程。


实验六十:LCD实验驱动4.3寸液晶屏

一、 实验目的与意义

  1. 了解STM32 LTDC结构
  2. 了解STM32 LTDC特征
  3. 掌握LCD液晶屏的使用方法
  4. 掌握STM32 HAL库中LTDC属性的配置方法
  5. 掌握KEIL MDK 集成开发环境使用方法

二、 实验设备及平台

  1. iCore4T 双核心板
  2. iCore4T 扩展底板
  3. iCore 4.3寸液晶屏底板
  4. JLINK(或相同功能)仿真器
  5. Micro USB线缆
  6. Keil MDK 开发平台
  7. STM32CubeMX开发平台
  8. 装有WIN XP(及更高版本)系统的计算机

三、 实验原理

LCD-TFT显示控制器(LTDC) 简介

LCD-TFT(液晶显示器——薄膜晶体管)显示器控制器提供并行数字 RGB(红色、绿色、 蓝色)以及水平同步、垂直同步、像素时钟和数据使能信号,这些信号直接输出到不同 LCD 和 TFT 面板的接口。STM32H750xx 的 LTDC 主要特性如下:

LTDC 控制器主要包含:信号线、图像处理单元、AXI 接口、配置和状态寄存器以及时钟部分,其框图如下所示:

2.LCD的DE同步模式和HV同步模式

通常,STM32H7都是用SDRAM作为LCD的显存,LTDC控制器会从SDRAM读取数据刷新到LCD显示屏上。刷新模式有DE同步模式和HV同步模式两种。一般大分辨率显示屏用DE同步模式,小分辨率的显示屏用HV同步模式。

DE模式需要LCD_DE和LCD_CLK信号来控制刷新。比如一个800×480分辨率的裸屏,在DE有效信号的时候(高电平或低电平),就有800个LCD_CLK输出时钟来确认行中800个点。每个时钟有效的时候,从显存读取一次RGB数据。因为存在回扫信号,所以DE是个方波。一个周期的LCD_DE信号,裸屏就扫描一行。扫描480行后,又从第一行扫描开始。这个规律由裸屏的驱动IC所决定的。

HV模式需要LCD_CLK时钟信号,行同步信号LCD_HSYNC和场同步信号LCD_VSYNC来控制刷新。比如一个480×272分辨率的裸屏,有一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),就有480个LCD_CLK输出时钟来确认行中480个点。每个时钟有效的时候,从显存读取一次RGB数据。再来一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),切换到下一行,继续行同步和时钟输出,扫描272行后,发送一个场同步信号LCD_VSYNC,又重新从第一行扫描开始。

3.LTDC的时序配置

LTDC的时序控制就是下面几个参数的设置,这几个参数都可以通过寄存器进行配置。

4.窗口

可为每个层定位和调整大小,各个层必须位于有效显示区域内。 窗口位置和大小通过左上和右下的 X/Y 位置以及包含同步、后沿大小和有效数据区域的内部时序发生器配置。 可编程层位置和大小定义了一行中的第一个/最后一个可见像素和窗口中的第一个/最后一个可见行。它允许显示完整的图像帧,也允许只显示图像帧的一部分。

5.LTDC层混合

LTDC除了图层1和图层2两个硬件图层以外,还有一个背景层。由于背景层的刷新不需要显存空间,所以可以用这个图层验证LTDC时序配置是否有问题。

背景层仅支持单色设置,固定颜色格式RGB888(LTDC_HandleTypeDef hltdc)我们这里将背景设置为白色: hltdc.Init.Backcolor.Blue = 255 hltdc.Init.Backcolor.Green = 255 hltdc.Init.Backcolor.Red = 255

对于图层1和图层2来说,支持如下8种颜色格式:

  1. ARGB8888
  2. RGB888
  3. RGB565
  4. ARGB1555
  5. ARGB4444
  6. L8(8 位 Luminance 或 CLUT)
  7. AL44(4 位 alpha + 4 位 luminance)
  8. AL88(8 位 alpha + 8 位 luminance)

实现Alpha混合的关键是要有一个变量可以设置各种透明度。对此,STM32H7准备了两个Alpha供使用:

STM32H7的参考手册给出了具体的混合公式: BC = BF1 x C + BF2 x Cs 混合后的颜色= 混合系数1 x 当前层颜色 + 混合系数2 x 底层混合后的颜色

四、 实验程序

1.主函数

int main(void)
{
        int i;
	HAL_Init();
	/* Configure the system clock */
	SystemClock_Config();
	/* USER CODE BEGIN SysInit */
	i2c.initialize();       //I2C初始化
	axp152.initialize();   //电源芯片配置
	axp152.set_dcdc1(3500);//[ARM & FPGA BK1/2/6 &OTHER]
	axp152.set_dcdc2(1200);//[FPGA INT & PLL D]
	axp152.set_aldo1(2500);//[FPGA PLL A]
	axp152.set_dcdc4(3300);//[POWER_OUTPUT]
	axp152.set_dcdc3(3300);//[FPGA BK4][Adjustable]
	axp152.set_aldo2(3300);//[FPGA BK3][Adjustable]
	axp152.set_dldo1(3300);//[FPGA BK7][Adjustable]
	axp152.set_dldo2(3300);//[FPGA BK5][Adjustable]
	HAL_Delay(500);
	/* USER CODE END SysInit */
	/* Initialize all configured peripherals */
	MX_GPIO_Init();    //GPIO初始化
	MX_FMC_Init();     //FMC初始化
	MX_LTDC_Init();    //LTDC初始化
	MX_TIM12_Init();   //TIM12初始化
	BSP_SDRAM_Init();  //SDRAM初始化
 
	HAL_TIM_PWM_Start(&htim12,TIM_CHANNEL_1);  //定时器使能,通道1
	LED_ON;
 
	//帧缓冲区地址映射二维数组
	for(i = 0;i < LCD_HEIGHT;i ++)address_sdram[i] = LCD_SDRAM_ADDRESS + (i * LCD_WIDTH) * 2;
 
	demo();  //运行弹球demo
	LCD_ON;
        while (1)
        { }
}

2.弹球demo函数

void demo(void){
	int bg = WHITE;   //背景色
	int colo[7] = {RED,BLUE,YELLOW,GREEN,0x7BEF,0x0000,0x03E0};//颜色列表
	int x=35,y=35,xs=1,ys=2;  //圆心起始坐标,速度的xy分量
	int oldx,oldy,co=0,i,j;
	int r=30;           //圆半径
	clear_screen(bg);
	draw_circle(x, y, r, RED, 1);
 
	while(1){
		oldx = x;
		oldy = y;
	        x = x + xs;
		y = y + ys;
		if((x+r)>=480 || (x-r)<=0){
		        xs=-1*xs; 
		        x = x + 2*xs;
		        co++;
		        if(co==7)co=0;
                }
		if((y+r)>=272 || (y-r)<=0){
		        ys=-1*ys;
		        y = y + 2*ys;
		        co++;
		        if(co==7)co=0;
                }
		draw_circle(x, y, r, colo[co], 1);  //画圆
			for(j = oldx-r-2;j < oldx+r+2;j ++){
				for(i = oldy-r-2;i < oldy+r+2;i ++){
					if(j<1 || j>479 || i<1 || i>271)continue;
						if( (int)(x-j)*(x-j) + (int)(y-i)*(y-i) > (int)r*r  ){
							*(volatile unsigned short int *) (address_sdram[i] + (j << 1)) = bg;
						}}}
		HAL_Delay(6);  //延时
	}
}

3.LTDC驱动配置

void MX_LTDC_Init(void)
{
	LTDC_LayerCfgTypeDef pLayerCfg = {0};
	LTDC_LayerCfgTypeDef pLayerCfg1 = {0};
	hltdc.Instance = LTDC;
	hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; //水平同步极性
	hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; //垂直同步极性
	hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; //数据使能极性
	hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC; //像素时钟极性
	hltdc.Init.HorizontalSync = 0;       //水平同步宽度
	hltdc.Init.VerticalSync = 0;         //垂直同步宽度
	hltdc.Init.AccumulatedHBP = 20;     //水平同步后沿宽度
	hltdc.Init.AccumulatedVBP = 9;       //垂直同步后沿高度
	hltdc.Init.AccumulatedActiveW = 500;//有效宽度
	hltdc.Init.AccumulatedActiveH = 281;//有效高度
	hltdc.Init.TotalWidth = 524;          //总宽度
	hltdc.Init.TotalHeigh = 287;          //总高度
	hltdc.Init.Backcolor.Blue = 255;     //背景RGB数值,白色
	hltdc.Init.Backcolor.Green = 255;
	hltdc.Init.Backcolor.Red = 255;
	if (HAL_LTDC_Init(&hltdc) != HAL_OK)
	{Error_Handler();}
	pLayerCfg.WindowX0 = 0;    //屏幕像素宽
	pLayerCfg.WindowX1 = 480;
  	pLayerCfg.WindowY0 = 0;    //屏幕像素高
	pLayerCfg.WindowY1 = 272;
	pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; //屏幕格式
  	pLayerCfg.Alpha = 0xff;    //透明度,不透明
	pLayerCfg.Alpha0 = 0;      //默认透明度
	pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
	pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
	pLayerCfg.FBStartAdress = 0xC0000000;  //帧缓冲区起始地址
	pLayerCfg.ImageWidth = 480;  //图层宽
	pLayerCfg.ImageHeight = 272;  //图层高
	pLayerCfg.Backcolor.Blue = 255;    //图层背景RGB数值,白色
	pLayerCfg.Backcolor.Green = 255;
	pLayerCfg.Backcolor.Red = 255;
	if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
	{ Error_Handler();}
}

4.画点函数

int set_pixel(int x, int y, int color) {
	if(x<0 || x>480 || y<0 || y>272)return 0;
	*(volatile unsigned short int *) (address_sdram[y] + (x << 1)) = color;
	return 1;
}

5.清屏函数

void clear_screen(int color)
{
	int i,j;
	for(j = 0;j < LCD_WIDTH;j ++){
		for(i = 0;i < LCD_HEIGHT;i ++){
			*(volatile unsigned short int *) (address_sdram[i] + (j << 1)) = color;
}}}

6.画圆函数

int draw_circle(int x, int y, int r, int color, int fill) {
	int i,j;
	if(x<0 || x>480 || y<0 || y>272)return 0;
	for(j = x-r;j < x+r;j ++){
		for(i = y-r;i < y+r;i ++){
			if(fill == 1){
				if( (int)(x-j)*(x-j) + (int)(y-i)*(y-i) <= (int)r*r  ){
					*(volatile unsigned short int *) (address_sdram[i] + (j << 1)) = color;
				}
			}
			else{
				if( (x-i)*(x-i) + (y-j)*(y-j) >= (r-2)*(r) && (x-i)*(x-i) + (y-j)*(y-j) <= (r+1)*(r) ){
					*(volatile unsigned short int *) (address_sdram[i] + (j << 1)) = color;
				}
			}
		}
	}
	return 1;
}

五、 实验步骤

  1. 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
  2. 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电;
  3. 将屏幕连接到4.3寸液晶屏底板上,并将液晶屏底板与iCore4T底板通过排线相连。
  4. 打开Keil MDK 开发环境,并打开本实验工程;
  5. 烧写程序到iCore4T上;
  6. 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。

六、 实验现象

有一个小球在屏幕中来回弹,触碰到边界时小球颜色改变。