zoukankan      html  css  js  c++  java
  • stm32 移植ucGUI

    2013  9  24
    按照qq meteor群共享里面的移植ucosgui移植文档,移植,就可以了,不同的是,这个文档,移植的是不带ucosii系统的,是在裸系统上移植的,所以把不同之处记录下来:
    1,按照文档所述,把底层驱动的一些函数都写好,之后按照要求LCDDummy。c文件中的需要改的地方,改掉,注意添加你自己写的驱动文件的头文件。如#include "LCD9341_Driver.h"     //LCD驱动头文件
    2.把一切配置文件,LCDConf.h GUIConf.h按自己要求改掉,
    3.要添加GUI_X_uCOS。c文件的时候和GUI_X。c文件,因为带操作系统,如果两者都要加,这时候编译的时候,会发现,两个源文件出现重定义的链接错误,这时候保留前者GUI_X_uCOS。c的定义,把GUI_X。c重复的函数屏蔽掉。(网上说,可以不用 GUI_X。c ,把缺少的函数补在GUI_X_uCOS。c后面就可以,自己可以试试。
    4.编译的时候最后会出现,内存不够的报错,那么要改配置文件GUIConf.h的内存大小那个配置
    5,还会出现这个情况void GUI_X_ExecIdle (void)

    {

        OS_X_Delay(1);

    }

    改为:

    void GUI_X_ExecIdle (void)

    {

        OSTimeDly(1);      

    }

    告诉OS_X_Delay没有定义,把设计到的这个函数换成 OSTimeDly(1)就可以了,因为我们带了操作系统

    6.在main文件中,调用gui的api函数时,添加这个头文件即可#include "GUI.H"

     
    在MDK环境下将3.90版本的UCGUI移植到STM32下了,为了方便大家,特写此移植方法,大家可以借鉴(有错误之处,望大家指点出来共同讨论!)
    移植步骤:
    第一步:首先,得把你的TFT底层驱动写好,既在裸机下,可以正常显示。
    第二步:加入UCGUI程序包。
    第三步:配置LCDConf.h GUIConf.h GUITouchConf.h(由于我的液晶不带触摸功能,此配置在此不讲。)
            配置LCDConf.h文件如下:
            #ifndef LCDCONF_H
    #define LCDCONF_H
    #define LCD_XSIZE          (160)   //配置TFT的水平分辨率
    #define LCD_YSIZE          (128)   //配置TFT的垂直分辨率
    #define LCD_CONTROLLER     (54124) //TFT控制器的名称
    #define LCD_BITSPERPIXEL   (16)    //每个像素的位数
    #define LCD_FIXEDPALETTE   (565)   //调色板格式
    #define LCD_SWAP_RB        (0)     //红蓝反色交换
    #define LCD_INIT_CONTROLLER()   TFT_Init() ;        //此处需要定义的是你的TFT初始化函数
            #endif /* LCDCONF_H */

            配置GUIConf.h文件如下:
            #ifndef GUICONF_H
            #define GUICONF_H

    #define GUI_OS                 (1)  //多任务
    #define GUI_SUPPORT_TOUCH      (0)  //触摸
                         #define GUI_SUPPORT_UNICODE    (1)  //Unicode支持  
    #define GUI_DEFAULT_FONT        &GUI_Font6x8  //GUI默认字体  
    #define GUI_ALLOC_SIZE          5000  //动态内存的大小
    #define GUI_WINSUPPORT          1  //窗口控件支持
    #define GUI_SUPPORT_MEMDEV      1  //支持内存设备
    #define GUI_SUPPORT_AA          1  /* Anti aliasing available */

            #endif  /* Avoid multiple inclusion */
    第四步:最关键的一步。那就是让GUI能够找到你的LCD驱动。修改LCDDriver。
            在编写你的TFT底层驱动程序的时候,一定不能忘记编写这两个函数:设置一个像素和获取一个像素的颜色,因为后面很多UCGUI和你的TFT驱动关联起来需要这两个函数为前提。以我的TFT为例:
    void LCD_SetPixel(unsigned short x, unsigned short y, unsigned short color)  
    {
    ….

    }

    unsigned short LCD_GetPixel(unsigned short x, unsigned short y)  
    {
       …

    }
    这两个函数写好,并测试可以正常显示后,接下来需要修改TFT与UCGUI关联的函数(在一个C文件下(我的是ili9320_ucgui.c),建议大家在移植GCGUI之前最好下载个别人移植好的例程,对着修改这样难度降低很多):
    int LCD_L0_Init(void)
    {   
      TFT_Init();
      return 0;
    }
    这个函数,是GCGUI初始化TFT需要调用的,里面的函数就是你TFT底层驱动的初始化函数。
    void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)
    {
      LCD_SetPixel(x,y,PixelIndex);
    }
    unsigned int LCD_L0_GetPixelIndex(int x, int y)
    {
      return LCD_GetPixel(x,y);
    }
    上面两个函数是其他函数的最基本元素,其他函数比如画线、点、圆都需要调用改函数。里面的LCD_SetPixel(x,y,PixelIndex)、LCD_GetPixel(x,y);就是你TFT底层驱动设置像素和获取像素的两个函数。
    紧接着把该ili9320_ucgui.c文件下其他函数修改一下(凡是遇到设置像素和获取像素的地方用以上两个函数代替。)
    接着,修改另一个C文件(ili9320_api.c)这里修改很简单,仅仅也是将设置像素和获取像素的函数替换掉自己定义的即可。
     
     
     

    二、移植过程

        先来看看解压后都有些什么东西:     核心的东西包括Config和GUI两个文件夹,这里面是ucgui的所有源码和配置文件。ConvertColor包含彩色转换函数,ConvertMono包含灰度到彩色转换的函数,Core包含核心程序,Font是字体文件,LCDDriver包含多种控制器驱动,Widget是窗口控件库,WM是窗口库,提供复杂的功能。其他文件夹包含一些应用范例以及一些有用的工具,留待慢慢探索。

    1、config文件的移植: 

    Config文件夹是ucgui的配置文件夹,里面有3个文件:

    GUIConf.h:gui的基本属性配置文件,有很多开关可以配置,具体可以参考ucgui的用户手册,这里只需配置几个必要的参数如下:

    #ifndef GUICONF_H

    #define GUICONF_H

    #define GUI_OS                    (1) 

    #define GUI_SUPPORT_TOUCH         (1) 

    #define GUI_SUPPORT_MOUSE         (0) 

    #define GUI_SUPPORT_UNICODE       (1) 

    #define GUI_DEFAULT_FONT          &GUI_Font6x8

    #define GUI_ALLOC_SIZE            12500

    #define GUI_WINSUPPORT            1 

    #define GUI_SUPPORT_MEMDEV        0 

    #define GUI_SUPPORT_AA            0 

    #endif 

     

    LCDConf.h:LCD控制器的硬件配置文件,这个文件与硬件直接相关,一般是根据你所使用的LCD的类型和所用的LCD控制器的类型来配置。我的配置是一块友晶公司的800*480的触摸屏,支持18位色,不过我只使用16位,RGB565色彩模式,足矣。LCD控制器就是写的一个硬件模块,挂在avalon总线上,负责读取显示缓冲区中的数据,然后按照该LCD的时序输出显示到LCD上。显示缓冲区直接开辟在系统内存中,系统使用一块512K SRAM作为系统内存,CPU可以直接对其进行16位读写访问。通过仔细阅读ucgui的用户手册,可以知道,在我这种硬件配置条件下,可以选择LCDLin.c这个驱动文件,那么对应了LCD_CONTROLLER 配置为1300。在实际配置时,LCD大小为400*240,这是因为在硬件工程的pixbuffer模块中对分辨率进行了硬扩。

    #include <system.h> #include <altera_avalon_pio_regs.h>

    #define LCD_XSIZE      (400)    #define LCD_YSIZE      (240)   

    #define LCD_BITSPERPIXEL (16) #define LCD_CONTROLLER   1300

    #define LCD_ENDIAN_BIG    0 #define LCD_FIXEDPALETTE  565 #define LCD_SWAP_RB       1 #define LCD_VRAM_ADR      SRAM_BASE #define LCD_BUSWIDTH      16 #define LCD_OPTIMIZE      1

    #define LCD_READ_MEM(Off)              IORD_16DIRECT(LCD_VRAM_ADR,(Off<<1)) #define LCD_WRITE_MEM(Off,data)        IOWR_16DIRECT(LCD_VRAM_ADR,(Off<<1),data)

    #define LCD_INIT_CONTROLLER()

        在这里,最重要的就是LCD_READ_MEM(Off),LCD_WRITE_MEM(Off,data)的定义,当时在LCD驱动文件上花了很大时间,仔细研究了LCDLin.c文件后,发现很多都是针对特定的LCD控制器写的,我们根本用不到,由于LCD控制器中已经对LCD屏进行了初始化,所以在这里LCD_INIT_CONTROLLER()也不必定义。

     

    GUITouchConf.h:触摸屏的配置文件。

    //#define GUI_TOUCH_AD_LEFT  100   //#define GUI_TOUCH_AD_RIGHT  4000    #define GUI_TOUCH_SWAP_XY    1 #define GUI_TOUCH_MIRROR_X   0 #define GUI_TOUCH_MIRROR_Y   1

        这里要根据特定的触摸屏来定义,主要修改GUICoreGUI_TOUCH_DriverAnalog.c文件,在后面将会继续讲述。至此,config文件移植完毕。

    2、LCD device驱动的移植

    三、运行第一个程序:hello_gui

    下面,我们就让刚移植好的gui到实际的系统上去运行一下。

    1、配置好FPGA的硬件;

    2、打开nios II IDE,以hello_world工程为模版建立一个新的工程hello_gui;

    3、将ucgui的Config和GUI两个文件夹(包含有我们刚刚修改过的几个文件)复制到工程目录下;

     

    5、修改hello_world.c的内容为:

    #include "GUI.H"

    #include <system.h>

    void main(void) {

    GUI_Init();                

    GUI_SetBkColor(GUI_BLUE);  

    GUI_Clear();               

    GUI_SetColor(GUI_RED);     

    GUI_DispString("Hello world!");

    while(1);

    }

    6、在system library选项中选择RTOS为MicroC/OS-II;

    这时如果编译工程,会出现一些未定义错误,类似于GUI_X_未定义等等,原来是缺少GUI_X.c文件,这个文件定义了gui与rtos的接口,以及debug错误报告等函数,于是我们需要添加这个文件。经过寻找,在Sample文件夹中发现了GUI_X这个文件夹,打开一看,里面有我们所需要的GUI_X.c文件,由于我们使用了MicroC/OS-II操作系统,所以我们使用其中的GUI_X_uCOS.c文件,将这个文件copy到工程目录下,并在文件结尾添加下面这几行:

    void GUI_X_Log     (const char *s) { GUI_USE_PARA(s); }

    void GUI_X_Warn    (const char *s) { GUI_USE_PARA(s); }

    void GUI_X_ErrorOut(const char *s) { GUI_USE_PARA(s); }

    并将其中的:

    void GUI_X_ExecIdle (void)

    {

        OS_X_Delay(1);

    }

    改为:

    void GUI_X_ExecIdle (void)

    {

        OSTimeDly(1);      

    }

    方可编译通过。

    7、Debug as hardware,这样,就可以看见结果了。我的结果是LCD上用篮底红字显示出了“hello world!”字样。表示ucgui3.98在Nios II上初步移植成功!

     

     

    http://www.openedv.com/posts/list/20610.htm

     

    ucGUI入门——ucGUI-ucOS-STM32-TFT触摸屏  

    2011-09-14 11:58:41|  分类: ucGUI|字号 订阅

     
     

      该篇以入门的角度介绍 GUI的移植过程,不作深入研究,只求以最快速度应用起来。

      选用芯片STM32F103VET6(512Flash/64KRAM),开发平台IAR540,系统包括TFT彩屏(ILI9325),电阻式触摸屏(AD7843),使用 OS操作系统 GUI3.90系统。ILI9325配置及操作系统的移植在之前的文章中有介绍,在此就不详细说明了。

      先简单说明一下软件包里用到的文件。软件包解压后有三个文件夹。核心文件在StartGUI里。    GUI入门—— GUI- OS-STM32-TFT触摸屏 - 深海精灵 - 深海精灵   GUI入门—— GUI- OS-STM32-TFT触摸屏 - 深海精灵 - 深海精灵   GUI入门—— GUI- OS-STM32-TFT触摸屏 - 深海精灵 - 深海精灵 

      在完全不明白文件含义和内存够大时,可把文件全部放入项目中,另外加入配置Config和GUI_X两个文件夹,如图:

                  GUI入门—— GUI- OS-STM32-TFT触摸屏 - 深海精灵 - 深海精灵
      Config里的文件在StartConfig可找到,GUI_X里的文件可以SampleGUI_X找到。
      把文件加入项目后就可以开始进行配置了,在头文件里加入"GUI.h” ,在项目option里加入编译时包含文件的路径,这些就不细说了,讲讲具体的配置过程。
    (一)GUIConf.h——GUI基本配置
    #define GUI_OS                        (1)  /* 支持系统*/ #define GUI_SUPPORT_TO H         (1)  /*支持触摸屏 */ #define GUI_SUPPORT_UNICODE       (1)  /* 支持ASCII/UNICODE 字符 */
    #define GUI_DEFAULT_FONT          &GUI_Font6x8  /* 默认字体*/ #define GUI_ALLOC_SIZE          5000  /* 动态存储器大小*/ #define GUI_WINSUPPORT              1  /* 是否使用窗体控制*/ #define GUI_SUPPORT_MEMDEV        1  /* 是否使用存储设备*/ #define GUI_SUPPORT_AA              1
    (二)配置LCD
    (1)LCDConf.h
    #define LCD_XSIZE          (240)   /* LCD宽 */ #define LCD_YSIZE          (320)   /* LCD高*/
    #define LCD_BITSPERPIXEL   (16) /* 位数  8位/16位 */
    #define LCD_CONTROLLER   9325 #define LCD_SWAP_RB     1       // 红蓝反色
     
    (2)ILI9325_ gui.c——GUI和ILI9325.c的函数接口 #define BKCOLOR LCD_BKCOLORINDEX #define   COLOR LCD_COLORINDEX
     
    #if (LCD_CONTROLLER == 9325)
    int LCD_L0_Init(void) {     TFT_Init();   return 0; }
    void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {  // 设定指定点颜色   TFT_PaintPoint(x,y,COLOR); }
    unsigned int LCD_L0_GetPixelIndex(int x, int y) {  // 获取指定点颜色   return TFT_GetPoint(x,y); }
    void LCD_L0_XorPixel(int x, int y) {   LCD_PIXELINDEX Index = TFT_GetPoint(x,y);   TFT_PaintPoint(x,y,LCD_NUM_COLORS-1-Index); }
    void LCD_L0_DrawHLine  (int x0, int y,  int x1) {   TFT_PaintLine(x0,y,x1,y,LCD_COLORINDEX); }
    void LCD_L0_DrawVLine  (int x, int y0,  int y1) {   TFT_PaintLine(x,y0,x,y1,LCD_COLORINDEX); }
    void LCD_L0_FillRect(int x0, int y0, int x1, int y1) { #if !LCD_SWAP_XY   for (; y0 <= y1; y0++) {     LCD_L0_DrawHLine(x0,y0, x1);   } #else   for (; x0 <= x1; x0++) {     LCD_L0_DrawVLine(x0,y0, y1);   } #endif }
    ………………………………(以下省略)
     
    (三)GUI_X_OS.c——配置操作系统
      这个文件从Sample中拷过来基本都不用修改,只改了一下延时的函数。 void GUI_X_ExecIdle (void)  {   OSTimeDly(50);    //    原来是OS_X_Delay(1);   }
     
    (四)触摸屏配置
    (1)GUITouchConf.h #define GUI_TOUCH_AD_LEFT  0    #define GUI_TOUCH_AD_RIGHT  240 #define GUI_TOUCH_AD_TOP  0    #define GUI_TOUCH_AD_BOTTOM  320 #define GUI_TOUCH_SWAP_XY    0 #define GUI_TOUCH_MIRROR_X   0 #define GUI_TOUCH_MIRROR_Y   0
    (2)GUI_X_Touch.c——GUI和AD7843.c的接口函数
    void GUI_TOUCH_X_ActivateX(void) { }
    void GUI_TOUCH_X_ActivateY(void) { }
    int  GUI_TOUCH_X_MeasureX(void) {  u16 X = 0;  X = AD7843_X(); 
    return (X); }
    int  GUI_TOUCH_X_MeasureY(void) {  u16 Y = 0;  Y = AD7843_Y();
      return (Y); }
      注意触摸屏的坐标需要校准,要把采集到的AD值转换成与LCD屏相对应的坐标。
     
      底层驱动配置完后,就可以开始做上层应用了。
      在 GUI-V3-90a GUI390aSample gui394_sample里有很多例子,随便选一下C文件放入项目中。
      在创建任务时创建两个任务
    static void AppTaskCreate(void) {  INT8U  err;
    OSTaskCreate(MainTask,                     (void *)0,                     &TASK1_STK[TASK1_STK_SIZE - 1],           TASK1_PRIO);  OSTaskNameSet(TASK1_ID, "Task1-MAIN", &err); 
     
    OSTaskCreate(Task_Key,                     (void *)0,                     &TASK_KEY_STK[TASK_KEY_STK_SIZE - 1],                     TASK_KEY_PRIO);  OSTaskNameSet(TASK_KEY_ID, "Task-KEY", &err);   }
     
      MainTask函数在sample例子里,按键响应函数如下:
    void Task_Key(void *pdata) {       AD7843_Ini();   while(1)    {     OSTimeDlyHMSM(0,0,0,10);     GUI_TO H_Exec();     } }
     
      至此,就基本完成,可以编译调试了。
     
     
     
    gui中触摸屏的移植
        最近研究了一下ucGUI,功能还凑合,前面的功能挺简单,研究到触摸屏遇到了一点小困难。我创建了一个按钮,点击它老是没反应,折腾了近一天终于搞定。
        简要介绍一下移植方法,首先在GUIConf.h中定义#define GUI_SUPPORT_TOUCH     (1) 支持触摸屏。
    然后是触摸屏的驱动程序(起码能读出AD转换后的X、Y值),有了驱动程序,然后加入GUI_X_Touch.c文件,并添加以下内容。
    #include "GUI.h"
    #include "GUI_X.h"
    #include "dp_touch.h"
     
    void GUI_TOUCH_X_ActivateX(void) {
    }
     
    void GUI_TOUCH_X_ActivateY(void) {
    }
     
    int  GUI_TOUCH_X_MeasureX(void) 
    {
        int xa[MAX_NUM],temp;
        u8 i,j;
        int tmx;
        u8 xcount=0;
        do
       {
            xa[xcount]=XPT2046_GetOneTouchX();
            if((xa[xcount]>300)&&(xa[xcount]<4000))
                xcount++;
           else
               break;
        }while(xcount<MAX_NUM);//循环读数10次
        if(xcount>=MAX_NUM)
        {
            xcount=0;
            for(i=0;i<MAX_NUM-1;i++)
            {
                for(j=i+1;j<MAX_NUM;j++)
                {
                   if(xa[i]>xa[j])
                   {
                       temp=xa[i];
                       xa[i]=xa[j];
                       xa[j]=temp;
                   }
                 }
             }
          tmx=(xa[3]+xa[4]+xa[5]+xa[6])/4;
        }
        return tmx;
    }
    //y坐标滤波
    int  GUI_TOUCH_X_MeasureY(void)
    {
        int ya[MAX_NUM],temp;
        u8 i,j;
        int tmy;
        u8 ycount=0;
        do
        {
            ya[ycount]=XPT2046_GetOneTouchY();
            if((ya[ycount]>300)&&(ya[ycount]<4000))
                ycount++;
            else
                break;
        }while(ycount<MAX_NUM);//循环读数10次
        if(ycount>=MAX_NUM)
        {
            ycount=0;
            for(i=0;i<MAX_NUM-1;i++)
            {
                for(j=i+1;j<MAX_NUM;j++)
               {
                    if(ya[i]>ya[j])
                    {
                        temp=ya[i];
                        ya[i]=ya[j];
                        ya[j]=temp;
                    }
               }
           }
           tmy=(ya[3]+ya[4]+ya[5]+ya[6])/4;
       }
        return tmy;
    }
     
        void GUI_TOUCH_X_ActivateX(void)和void GUI_TOUCH_X_ActivateY(void)直接为空即可,
    int  GUI_TOUCH_X_MeasureX(void) 和int  GUI_TOUCH_X_MeasureY(void)返回读取的X和Y值(其实是AD转换值),程序里滤了一下波。XPT2046_GetOneTouchX()和XPT2046_GetOneTouchY()是我自己编写的读坐标程序(未滤波)。
        然后点击屏幕的左上角和右下角,记下坐标(AD转换值,具体方法自己发挥,我把值打印在屏幕上了),然后配置GUITouchConf.h,如下所示。
    #ifndef GUITOUCH_CONF_H
    #define GUITOUCH_CONF_H
     
     
    #define GUI_TOUCH_AD_LEFT   3850   
    #define GUI_TOUCH_AD_RIGHT   310 
    #define GUI_TOUCH_AD_TOP        380
    #define GUI_TOUCH_AD_BOTTOM     3840
       
    #define GUI_TOUCH_SWAP_XY    0
    #define GUI_TOUCH_MIRROR_X   0
    #define GUI_TOUCH_MIRROR_Y   1//镜像,根据自己的屏幕确定
     
    #endif
     
     
        至此准备工作完成,一个简单的实例。暂时没使用操作系统,所以偶在定时器2中每隔10ms调用GUI_TOUCH_Exec();获得触摸屏坐标(ucGUI已根据GUITouchConf.h中的配置转换完成),主程序如下。
    int main(void)
    {
        BUTTON_Handle hButton;//按钮句柄
        GUI_PID_STATE Button_State; //输入设备状态
        int temp=1;  
        SystemInit();//系统初始化
        GUI_Init(); //液晶屏初始化
        XPT2046_Config();//触摸屏初始化
        SPI2_Config();//spi初始化
        GUI_SetBkColor(GUI_BLUE);//设置背景色
        GUI_Clear();
        hButton=BUTTON_Create(10,20,40,20,GUI_ID_OK,WM_CF_SHOW);//创建一个按钮
        BUTTON_SetText(hButton, "Click");
     
        TIMER2_Config();//在定时器2中每隔10ms调用GUI_TOUCH_Exec();获得触摸屏坐标
        NVIC_Config();
        while(1)
        {
            TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE);//关中断
            GUI_TOUCH_GetState(&Button_State);//得到输入设备状态
            GUI_TOUCH_StoreStateEx(&Button_State);//存储输入设备状态
            GUI_DispDecAt(Button_State.x,10,50,4);//输入设备当前x坐标
            GUI_DispDecAt(Button_State.y,10,80,4);//输入设备当前y坐标
            GUI_DispDecAt(Button_State.Pressed,10,100,4);//是否按下
            GUI_Exec();//执行回调函数重绘无效窗口(通常GUI_Delay()自动调用此函数)
            if(GUI_GetKey()==GUI_ID_OK)//按钮按下
            {
                if(temp==1)
                {
                    temp=0;
                    BUTTON_SetText(hButton,"yes");
                }
                else
                {
                    temp=1;
                    BUTTON_SetText(hButton,"no");
                 }
             }
            TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开中断
            delay_ms(1000);
        }
    }
     
        注释的比较详细了,具体就是显示一个按钮,按钮按下时上面的文字在“yes”和“no”之间进行切换。按钮下方显示按下位置的坐标和状态。

     

  • 相关阅读:
    Linux 通过sendmail 发邮件到外部邮箱
    基于Ruby的Watir-WebDriver自动化测试方案
    高性能Linux服务器构建实战笔记
    Unix Linux 通用vi命令,使用帮助手册【珍藏版】
    软件测试人员必备Linux命令(初、中、高级)
    网络七层知多少,学以致用
    手机终端高级测试工程师经验总结
    临别前夕,工作总结 于2014年8月13日 终稿
    基于ruby的watir自动化测试 笔记二
    高级软件测试工程师笔试题
  • 原文地址:https://www.cnblogs.com/darren-715/p/3457670.html
Copyright © 2011-2022 走看看