"); //-->
事实上液晶的正确初始化就是需要明确显示缓冲区跟视窗屏幕的对应关系 为了达到这个目的 可是通
过单步调试 逐个显示点来观察这种对应关系 在上图中那就是这样一个顺序
Bmp[0]=0xF000;//点 0
Bmp[0]=0xFF00;//点 0 1
Bmp[0]=0xFFF0;//点 0 1 2
Bmp[0]=0xFFFF;//点 0 1 2 3
单步执行 查看液晶屏上显示点的位置 这样就可以确定对应关系了
这 44BO 中的液晶控制寄存器中有 BSWP 这个设置位 它是用于调整每 4 个字节的字节顺序的 也是通
过单步调试来明确这种对应关系的 .
#define SCR_XSIZE (320)//视窗屏幕大小
#define SCR_YSIZE (240)
#define LCD_XSIZE (320)//液晶屏幕大小
#define LCD_YSIZE (240)
#define MVAL_USED (0)
#define MVAL (13)
#define INVCLK (0)
#define INVFRAME (0)
#define INVLINE (0)
#define CLKVAL_SL (8) //VCLK=MCLK/(CLKVAL*2) (CLKVAL >= 2)
#define M5D(n) ((n) & 0x1fffff)
#define ARRAY_SIZE_G16 (SCR_XSIZE*SCR_YSIZE)
unsigned short Bmp[ARRAY_SIZE_G16/2];//液晶显示缓冲数组
#define CLKVAL_G16 (10) //40Mhz, CLKVAL=10 ->101Hz
#define HOZVAL (LCD_XSIZE/4-1)
#define LINEVAL (LCD_YSIZE-1)
#define MVAL (13)
#define BSWP (1)//这个决定了每 4 个字节的顺序是否进行交换
#define MODESEL (2)//Gray 16
void LcdInit(void)
{
//The following value has to be changed for better display.
rDITHMODE=0x12210;
//rDITHMODE=0x0;
rDP1_2 =0xa5a5;
rDP4_7 =0xba5da65;
rDP3_5 =0xa5a5f;
rDP2_3 =0xd6b;
rDP5_7 =0xeb7b5ed;
rDP3_4 =0x7dbe;
rDP4_5 =0x7ebdf;
rDP6_7 =0x7fdfbfe;
rLCDCON1 = (0)|(1<<5)|(MVAL_USED<<7)|(0x3<<8)|(0x3<<10)|(CLKVAL_G16<<12);
// disable,4B_SNGL_SCAN,WDLY=8clk,WLH=8clk,
rLCDCON2 = (LINEVAL)|(HOZVAL<<10)|(10<<21);
//LINEBLANK=10 (without any calculation)
rLCDSADDR1 = (MODESEL<<27) | ( ((uint)Bmp>>22)<<21 ) | M5D((uint)Bmp>>1);
// 16-gray, LCDBANK, LCDBASEU
rLCDSADDR2 = (BSWP<<29)|M5D((((uint)Bmp+(SCR_XSIZE*LCD_YSIZE/2))>>1))|(MVAL<<21);
rLCDSADDR3 = (LCD_XSIZE/4) | ( ((SCR_XSIZE-LCD_XSIZE)/4)<<9 );
rLCDCON1 = (1)|(1<<5)|(MVAL_USED<<7)|(0x3<<8)|(0x3<<10)|(CLKVAL_G16<<12);
}
二 UCGUI 的移植
移植的思路是使用 UCGUI 支持的 buffer 型的 LCD控制器 EPSON 1375我想就是这样一个使用双口 RAM的 LCD
控制器吧 因为我注意到 UCGUI 的代码中 若是使用 1375 控制器时 需要定义四个读写函数
#define LCD_READ_MEM(Off) *((U16*) (0xc00000+(((U32)(Off))<<1)))
#define LCD_WRITE_MEM(Off,data) *((U16*) (0xc00000+(((U32)(Off))<<1)))=data
#define LCD_READ_REG(Off) *((volatile U16*)(0xc1ffe0+(((U16)(Off))<<1)))
#define LCD_WRITE_REG(Off,data) *((volatile U16*)(0xc1ffe0+(((U16)(Off))<<1)))=data
前两个是读写内存的定义
后两个是读写寄存器的定义
注意到常数 0xc00000 和 0xc1ffe0 没有
0xc00000 是 1375 控制器的显示缓冲区开始地址(Base Address)
0xc1ffe0 是 1375 控制器的寄存器开始地址(Base Address)
读写显示缓冲区就是根据地址偏移 off 和开始地址 0xc00000 来读写 Buffer 的
读写控制寄存器就是根据地址偏移 off 和开始地址 0xc1ffe0 来读写 Buffer 的
我想可以使用欺骗的一招 我们把我们液晶的显示缓冲区的开始地址(Bmp[0])告诉这几个函数 那么就可以了 而
读写寄存器的两个函数我们就不用了
等我移植完毕 我发现网络上的其它移植版本也是如此使用了 1375控制器的了 不信看看他们提供的演示 DOME
显示的液晶控制器是不是 EPSON 13705
在 LCD.H中定义数据类型
#define I8 signed char
#define U8 unsigned char /* unsigned 8 bits. */
#define I16 signed short /* signed 16 bits. */
#define U16 unsigned short /* unsigned 16 bits. */
#define I32 signed long /* signed 32 bits. */
#define U32 unsigned long /* unsigned 32 bits. */
#define I16P I16 /* signed 16 bits OR MORE ! */
#define U16P U16 /* unsigned 16 bits OR MORE ! */
在 LCDConf.H中定义
#define LCD_XSIZE (320) /* X-resolution of LCD, Logical coor. */
#define LCD_YSIZE (240) /* Y-resolution of LCD, Logical coor. */
#define LCD_BITSPERPIXEL (4) //16灰度
#define LCD_CONTROLLER 1375
extern unsigned short Bmp[]; //引入显示缓冲区数组
#define LCD_READ_MEM(Off) *((U16*) (Bmp+(((U32)(Off)))))
#define LCD_WRITE_MEM(Off,data) *((U16*) (Bmp+(((U32)(Off)))))=data
//#define LCD_READ_REG(Off) //这个函数可以不用定义 反正我们没有用到
#define LCD_WRITE_REG(Off,data) //有些地方用到了 定义为空 避免做大改动
#define LCD_SWAP_BYTE_ORDER (1) //这个是做字节转换的
在 LCD13XX.C中定义液晶总线宽度
#ifndef LCD_BUSWIDTH
#define LCD_BUSWIDTH (16)
#endif
这里提及关键对应部分
->定义显示缓冲区时使用的short数据类型,它是16bit的:
unsigned short Bmp[ARRAY_SIZE_G16/2];//液晶显示缓冲数组
->定义读写缓冲区时使用的数据类型,也是16bit的U16:
#define LCD_READ_MEM(Off) *((U16*) (Bmp+(((U32)(Off)))))
#define LCD_WRITE_MEM(Off,data) *((U16*) (Bmp+(((U32)(Off)))))=data
//#define LCD_READ_REG(Off) //这个函数可以不用定义 反正我们没有用到
#define LCD_WRITE_REG(Off,data) //有些地方用到了 定义为空 避免做大改动
->定义液晶总线宽度 定义位 16bit 的
#ifndef LCD_BUSWIDTH
#define LCD_BUSWIDTH (16)
#endif
->定义字节顺序
#define LCD_SWAP_BYTE_ORDER (1) //16bit时需要交换的
读者已经能看到了对应关系了 都是使用16bit的数据类型 这是关键 别用错了
由此延伸 若是把这些对应关系换成8bit的数据类型 如下
->定义显示缓冲区时使用的char数据类型,它是8bit的:
unsigned char Bmp[ARRAY_SIZE_G16];//液晶显示缓冲数组
->定义读写缓冲区时使用的数据类型,也是8bit的U8:
#define LCD_READ_MEM(Off) *((U8*) (Bmp+(((U32)(Off)))))
#define LCD_WRITE_MEM(Off,data) *((U8*) (Bmp+(((U32)(Off)))))=data
//#define LCD_READ_REG(Off) //这个函数可以不用定义 反正我们没有用到
#define LCD_WRITE_REG(Off,data) //有些地方用到了 定义为空 避免做大改动
->定义液晶总线宽度 定义位 8bit 的
#ifndef LCD_BUSWIDTH
#define LCD_BUSWIDTH (8)
#endif
->定义字节顺序
#define LCD_SWAP_BYTE_ORDER (0) //8bit时不需要交换的
这样的对应关系也是可行的 我测试过 不过若是你想把它换成32bit的话就不行了 因为UCGUI不支持32bit
的液晶总线宽度的
以上两部分是整个移植工作的关键 当然还有一些繁琐的事情 请阅读UCGUI的手册中Getting Started一章
在IAR下移植时 需要建立group 对照文件夹加入UCGUI代码
需要说明的是
除了LCDDriver下只加入LCD13XX.C 在Config下额外加入GUI_X.C外其余的都是加入相应文件夹中的所有C文件
我还额外加入了跟开发板有关的文件:
LCDLIB.C(液晶的初始化函数LcdInit())
Platform.C(板级初始化函数 它会调用LcdInit()来初始化液晶控制器)
设置include路径:
我加入的include路径为
D:\Program Files\IAR Systems\UCGUI\gui\core\
D:\Program Files\IAR Systems\UCGUI\Config\
D:\Program Files\IAR Systems\UCGUI\gui\WM\
D:\Program Files\IAR Systems\UCGUI\gui\Widget\
D:\Program Files\IAR Systems\UCGUI\Sample\GUIDemo\
在GUIConf.H中定义
#define GUI_OS (0) /* Compile with multitasking support */
#define GUI_WINSUPPORT (1) /* Use window manager if true (1) */
#define GUI_SUPPORT_MEMDEV (1) /* Support memory devices */
#define GUI_SUPPORT_TOUCH (0) /* Support a touch screen (req. win-manager) */
#define GUI_SUPPORT_UNICODE (1) /* Support mixed ASCII/UNICODE strings */
我们还没有移植到OS上 也没有加入触摸屏的支持
void GUI_X_Delay(int ms) {
// int tEnd = OS_TimeMS + ms;
// while ((tEnd - OS_TimeMS) > 0);
extern void Delay(int time);//我自己的延时函数
Delay(150*ms);
}
原因是在UCGUI的应用中有一些函数是跟时间相关的 UCGUI认为使用的是UCOS UCOS会维护时间OS_TimeMS;这里
我调用我自己的延迟程序来实现延迟 事实上正是因为有一些函数跟时间有关 因此在UCGUI提供的演示程序中就出
现了问题 例如在GUIDEMO_Speed.C中有这么个循环
for (i = 0; (((t + 8000) - (int)GUI_GetTime()) > 0) && !GUIDEMO_CheckCancel(); i++) {
}
它调用了GUI_GetTime读取当前系统时间来控制循环 若是系统没有维护时间OS_TimeMS 那就会出问题了 我的简
单解决方法是改为
for (i = 0;i<0xFFF;i++){
}
在其它的GUIDEMO_XXXX.C中也有这样一些循环 你要是调试是发现液晶屏上的显示一直停在一个画面上很久的话
估计就是碰上了上面的问题
好了 加入那个最简单的主函数 Basic_Helloworld.C
void BoardInit (void);
void main(void) {
/*
ToDo: Make sure hardware is initilized first!!
*/
BoardInit ();//板级初始化 它调用了LcdInit()
GUI_Init();
GUI_DispString("Hello world!");
while(1);
}
应该能在你的液晶屏上看到UCGUI跟你打招呼的了 "Hello world!"
这样UCGUI的移植基本上已经完成了 当然了这里只提供了移植关键的部分 更多的 更完整的移植还需要做不少的工作,如触控屏的移植,键盘、鼠标的移植,中文字体的移植,UCGUI支持UNICODE 中文字体不成大问题的。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。