STM32F429IGT6移植STEMWIN
1. 用cube生成sdram配置
2.cube配置LTDC
这里使用的事正点原子的f429,所有使用RGB565
(uint32_t)ltdc_framebuf[0];
3.打开DMA2D
这里配不配置都没影响。主要是移植正点原子的代码,使用时就开
4.GPIO的配置
- 打开背光控制
2.
2.cube生成的LTDC与正点开发板的GPIO不匹配,所以我们要修改引脚复用。
先放大概的位置,方便对应修改
这里是LTDC用到的引脚
生成代码,修改代码
1.首先RGB需要注意的是速率和FIFO
2.对应大小的屏给对应的LCD_TFT CLOCKS(小的屏幕给太高的速录,显示就会有问题,大屏幕就要给高)
这里使用的是正点原子的学习代码,再次感谢正点原子
首先初始化
要先给RGB的FIFO赋地址,不然显示会不正常,
ltdc_framebuf[0]=(u32*)<dc_lcd_framebuf;
我把他放到主函数开头了,因为 MX_LTDC_Init();里面使用到了。如果不先赋值,这里面使用了,就会出错,
3.移植屏幕,最重要的就是 刷屏函数,画点函数。读点函数
刷屏函数
//在指定区域内填充指定颜色块,DMA2D填充
//此函数仅支持u16,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(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
{
u32 psx,psy,pex,pey; //以LCD面板为基准的坐标系,不随横竖屏变化而变化
u32 timeout=0;
u16 offline;
u32 addr;
//坐标系转换
if(lcdltdc.dir) //横屏
{
psx=sx;psy=sy;
pex=ex;pey=ey;
}else //竖屏
{
psx=sy;psy=lcdltdc.pheight-ex-1;
pex=ey;pey=lcdltdc.pheight-sx-1;
}
offline=lcdltdc.pwidth-(pex-psx+1);
addr=((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*psy+psx));
__HAL_RCC_DMA2D_CLK_ENABLE(); //使能DM2D时钟
DMA2D->CR&=~(DMA2D_CR_START); //先停止DMA2D
DMA2D->CR=DMA2D_M2M; //存储器到存储器模式
DMA2D->FGPFCCR=LCD_PIXFORMAT; //设置颜色格式
DMA2D->FGOR=0; //前景层行偏移为0
DMA2D->OOR=offline; //设置行偏移
DMA2D->FGMAR=(u32)color; //源地址
DMA2D->OMAR=addr; //输出存储器地址
DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16); //设定行数寄存器
DMA2D->CR|=DMA2D_CR_START; //启动DMA2D
while((DMA2D->ISR&(DMA2D_FLAG_TC))==0) //等待传输完成
{
timeout++;
if(timeout>0X1FFFFF)break; //超时退出
}
DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志
}
画点函数、读点函数
//画点函数
//x,y:写入坐标
//color:颜色值
void LTDC_Draw_Point(u16 x,u16 y,u32 color)
{
#if LCD_PIXFORMAT==LCD_PIXFORMAT_ARGB8888||LCD_PIXFORMAT==LCD_PIXFORMAT_RGB888
if(lcdltdc.dir) //横屏
{
*(u32*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*y+x))=color;
}else //竖屏
{
*(u32*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*(lcdltdc.pheight-x)+y))=color;
}
#else
if(lcdltdc.dir) //横屏
{
*(u16*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*y+x))=color;
}else //竖屏
{
*(u16*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*(lcdltdc.pheight-x-1)+y))=color;
}
#endif
}
//读点函数
//x,y:读取点的坐标
//返回值:颜色值
u32 LTDC_Read_Point(u16 x,u16 y)
{
#if LCD_PIXFORMAT==LCD_PIXFORMAT_ARGB8888||LCD_PIXFORMAT==LCD_PIXFORMAT_RGB888
if(lcdltdc.dir) //横屏
{
return *(u32*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*y+x));
}else //竖屏
{
return *(u32*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*(lcdltdc.pheight-x)+y));
}
#else//rgb565每次写入两个字节
if(lcdltdc.dir) //横屏
{
return *(u16*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*y+x));
}else //竖屏
{
return *(u16*)((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*(lcdltdc.pheight-x-1)+y));
}
#endif
}
因为这里使用的是RGB565 所有每个像素占两个字节
lcdltdc.pixsize=2;//每个像素占2个字节
4.显示的时候要打开背光
移植TOUCH
我用的触摸屏用的是正点原子的4.3寸RGB,触摸芯片是GT9147
注意的是,没有移植串口,,需要把PRINTF屏蔽了,里面用到了大量延时函数,也需要初始化延时,不然会死机,
CUBE生成FreeRTOS
这里使用的时钟是滴答定时器,因为需要微妙延时,我仔细看了下,微妙延时只是查询法,不会造成影响
移植STEMWIN
1.把STEMWIN所需要的c文件添加到代码中
2.修改文件配置
1. 修改GUIConf.h
这里直接用正点原子的代码覆盖,简单明了
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_NUM_LAYERS 1 //最大支持1层
#define GUI_OS (1) // 使用操作系统
#define GUI_MAXTASK (5) // 最大可调用EMWIN的任务数
#define GUI_SUPPORT_TOUCH (1) // 支持触摸
#define GUI_DEFAULT_FONT &GUI_Font6x8 //默认字体
#define GUI_SUPPORT_MOUSE (1) //支持鼠标
#define GUI_WINSUPPORT (1) //窗口管理
#define GUI_SUPPORT_MEMDEV (1) //存储设备
#define GUI_SUPPORT_DEVICES (1) //使用设备指针
#endif
2.GUI_X_OS.C
因为STEMWIN带操作系统是基于FREERTOS,所以这个文件可以不修改
3 .LCDConf_FlexColor_Template.c
#include "GUI.h"
#include "lcd.h"
#include "GUIDRV_Template.h"
#include "GUIDRV_FlexColor.h"
//屏幕大小
#define XSIZE_PHYS 480 //X轴
#define YSIZE_PHYS 272 //Y轴
#define VXSIZE_PHYS 480
#define VYSIZE_PHYS 272
//配置检查
#ifndef VXSIZE_PHYS
#define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef VYSIZE_PHYS
#define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef XSIZE_PHYS
#error Physical X size of display is not defined!
#endif
#ifndef YSIZE_PHYS
#error Physical Y size of display is not defined!
#endif
#ifndef GUICC_565
#error Color conversion not defined!
#endif
#ifndef GUIDRV_FLEXCOLOR
#error No display driver defined!
#endif
//配置程序,用于创建显示驱动器件,设置颜色转换程序和显示尺寸
void LCD_X_Config(void) {
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0); //创建显示驱动器件
LCD_SetSizeEx (0, lcddev.width, lcddev.height);
LCD_SetVSizeEx (0, lcddev.width, lcddev.height);
GUI_TOUCH_Calibrate(GUI_COORD_X,0,lcddev.width,0,lcddev.width-1);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,lcddev.height,0,lcddev.height-1);
}
//显示器驱动的回调函数
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
int r;
(void) LayerIndex;
(void) pData;
switch (Cmd) {
case LCD_X_INITCONTROLLER: {
//当初始化的时候被调用,主要是设置显示控制器,如果显示控制器在外部初始化则需要用户初始化
// TFTLCD_Init(); //初始化LCD 已经在开始初始化了,所以此处不需要初始化。
return 0;
}
default:
r = -1;
}
return r;
}
4.GUIDRV_Template.c
这个文件主要是画点,读点,填充函数,主要修改参考正点原子
5.因为需要带触摸功能。
新建一个c文件到工程中去
GUI_X_Touch_Analog.c
#include "GUI.h"
#include "gt9147.h"
#include "lcd.h"
void GUI_TOUCH_X_ActivateX(void)
{
// XPT2046_WriteCMD(0x90);
}
void GUI_TOUCH_X_ActivateY(void)
{
//XPT2046_WriteCMD(0xd0);
}
int GUI_TOUCH_X_MeasureX(void)
{
int32_t xvalue;
tp_dev.scan(0);
xvalue=tp_dev.x[0];
return xvalue;
}
int GUI_TOUCH_X_MeasureY(void)
{
int32_t yvalue;
tp_dev.scan(0);
yvalue = tp_dev.y[0];
return yvalue;
}
移植心得
1.很多时候移植不成功,更多的是,内存溢出,调整内存大小,或者跑GUI任务所分配的的堆栈大小不够,
不管带不带操作系统移植,切记要打开CRC时钟,
2.使用前,初始化好外设,