银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2020-10-21 | gingko | 初次建立 |
1.在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 3.配置RCC,使用外部时钟源 4.时基源选择SysTick 5.配置GPIO和引脚模式,引脚为PA10,PB4,PB7,PB8,PF6。 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,进行进一步配置
LCD-TFT(液晶显示器——薄膜晶体管)显示器控制器提供并行数字 RGB(红色、绿色、 蓝色)以及水平同步、垂直同步、像素时钟和数据使能信号,这些信号直接输出到不同 LCD 和 TFT 面板的接口。STM32H750xx 的 LTDC 主要特性如下:
通常,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来控制刷新。比如一个800×480分辨率的裸屏,有一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),就有800个LCD_CLK输出时钟来确认行中800个点。每个时钟有效的时候,从显存读取一次RGB数据。再来一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),切换到下一行,继续行同步和时钟输出,扫描480行后,发送一个场同步信号LCD_VSYNC,又重新从第一行扫描开始。
LTDC的时序控制就是下面几个参数的设置,这几个参数都可以通过寄存器进行配置。
可为每个层定位和调整大小,各个层必须位于有效显示区域内。 窗口位置和大小通过左上和右下的 X/Y 位置以及包含同步、后沿大小和有效数据区域的内部时序发生器配置。 可编程层位置和大小定义了一行中的第一个/最后一个可见像素和窗口中的第一个/最后一个可见行。它允许显示完整的图像帧,也允许只显示图像帧的一部分。
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种颜色格式:
实现Alpha混合的关键是要有一个变量可以设置各种透明度。对此,STM32H7准备了两个Alpha供使用:
STM32H7的参考手册给出了具体的混合公式: BC = BF1 x C + BF2 x Cs 混合后的颜色= 混合系数1 x 当前层颜色 + 混合系数2 x 底层混合后的颜色
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; clear_screen(WHITE); LCD_ON; demo(); //运行弹球demo while (1) { } }
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)>=LCD_WIDTH || (x-r)<=0){ xs=-1*xs; x = x + 2*xs; co++; if(co==7){ co=0; clear_screen(bg); } } if((y+r)>=LCD_HEIGHT || (y-r)<=0){ ys=-1*ys; y = y + 2*ys; co++; if(co==7){ co=0; clear_screen(bg); } } 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>LCD_WIDTH-1 || i<1 || i>LCD_HEIGHT-1)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); //延时 } }
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 = 1; //垂直同步宽度 hltdc.Init.AccumulatedHBP = 45; //水平同步后沿宽度 hltdc.Init.AccumulatedVBP = 22; //垂直同步后沿高度 hltdc.Init.AccumulatedActiveW = 845;//有效宽度 hltdc.Init.AccumulatedActiveH = 502;//有效高度 hltdc.Init.TotalWidth = 1055; //总宽度 hltdc.Init.TotalHeigh = 525; //总高度 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 = 800; pLayerCfg.WindowY0 = 0; //屏幕像素高 pLayerCfg.WindowY1 = 480; 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 = 800; //图层宽 pLayerCfg.ImageHeight = 480; //图层高 pLayerCfg.Backcolor.Blue = 255; //图层背景RGB数值,白色 pLayerCfg.Backcolor.Green = 255; pLayerCfg.Backcolor.Red = 255; if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) { Error_Handler();} }
int set_pixel(int x, int y, int color) { if(x<0 || x>LCD_WIDTH || y<0 || y>LCD_HEIGHT)return 0; *(volatile unsigned short int *) (address_sdram[y] + (x << 1)) = color; return 0; }
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; }}}
int draw_circle(int x, int y, int r, int color, int fill) { int i,j; if(x<0 || x>LCD_WIDTH || y<0 || y>LCD_HEIGHT)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; }
有一个小球在屏幕中来回弹,触碰到边界时小球颜色改变。