用户工具

站点工具


icore4tx_60
银杏科技有限公司旗下技术文档发布平台
技术支持电话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,进行进一步配置

  • Copy all used libraries into the project folder
  • 将HAL库的所有.C和.H都复制到所建工程中
    • 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便
    • 缺点:体积大,编译时间很长
  • Copy only the necessary library files
  • 只复制所需要的.C和.H(推荐)
    • 优点:体积相对小,编译时间短,并且工程可复制拷贝
    • 缺点:新增外设时需要重新用STM32CubeMX导入
  • Add necessary library files as reference in the toolchain project configuration file
  • 不复制文件,直接从软件包存放位置导入.C和.H
    • 优点:体积小,比较节约硬盘空间
    • 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径
  • 自行选择方式即可

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 主要特性如下:

  • 24 位 RGB 并行像素输出;每像素 8 位数据(RGB888)
  • 2 个带有专用 FIFO 的显示层(FIFO 深度 64×64 位)
  • 支持查色表 (CLUT),每层高达 256 种颜色(256×24 位)
  • 可针对不同显示面板编程时序
  • 可编程背景色
  • 可编程 HSync、VSync 和数据使能(DE)信号的极性
  • 每层有多达 8 种颜色格式可供选择:ARGB8888、RGB888、RGB565、ARGB1555、ARGB4444、L8(8 位 Luminance 或 CLUT)、AL44(4 位 alpha+4 位 luminance)和 AL88(8 位 alpha+8位 luminance)
  • 每通道的低位采用伪随机抖动输出(红色、绿色、蓝色的抖动宽度为 2 位)
  • 使用 alpha 值(每像素或常数)在两层之间灵活混合
  • 色键(透明颜色)
  • 可编程窗口位置和大小
  • 支持薄膜晶体管 (TFT) 彩色显示器
  • AXI 主接口支持 16 个双字的突发
  • 高达 4 个可编程中断事件

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

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

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

  • DE同步模式

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

  • HV同步模式

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

3.LTDC的时序配置

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

  • HSYNC width水平同步宽度设置,以LCD_CLK的像素时钟输出为单位。
  • HBP(horizontal back porch period)水平后沿周期设置,以LCD_CLK的像素时钟输出为单位。
  • Active width有效宽度设置,以LCD_CLK的像素时钟输出为单位。以480*272分辨率为例,Active width = 480。
  • HFP(horizontal front porch period)水平前沿周期设置,以LCD_CLK的像素时钟输出为单位。
  • VSYNC width垂直同步宽度设置,以LCD_CLK的像素时钟输出为单位。
  • VBP(vertical back porch period)垂直后沿周期设置,以LCD_CLK的像素时钟输出为单位。
  • Active height有效高度设置,以LCD_CLK的像素时钟输出为单位。以480*272分辨率为例,Active height = 272。
  • VFP(vertical front porch period)垂直前沿周期设置,以LCD_CLK的像素时钟输出为单位。

4.窗口

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

  • 层中的第一个和最后一个可见像素通过配置 LTDC_LxWHPCR 寄存器中WHSTPOS[11:0] 和WHSPPOS[11:0] 进行设置。
  • 层中的第一个和最后一个可见行通过配置 LTDC_LxWVPCR 寄存器中的 WVSTPOS[10:0] 和 WVSPPOS[10:0] 进行设置。

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供使用:

  • 一个是常数Alpha(0x00表示完全透明,0xFF表示完全不透明),所有颜色格式都可以使用。
  • 另一个是像素Alpha,也就是ARGB8888,ARGB1555,ARGB4444等颜色格式的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 模式,单步运行或设置断点验证程序逻辑。

六、 实验现象

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

icore4tx_60.txt · 最后更改: 2022/04/01 11:35 由 sean