STM32 + RT Thread OS 学习笔记[六]

来源:互联网 发布:驱鼠软件 编辑:程序博客网 时间:2024/04/29 17:19

1、  触摸屏校准程序

由于GUI目前在持续变更中,有些函数在新版本中已经不同了,而bsp中的校准程序没有跟进修改,所以无法编译通过。

 

修正可编译版本:

#include <rtgui/rtgui.h>

#include <rtgui/dc.h>

#include <rtgui/rtgui_app.h>

#include <rtgui/rtgui_system.h>

#include <rtgui/widgets/window.h>

 

#include "touch.h"

 

// 校准步骤编

#define CALIBRATION_STEP_LEFTTOP        0

#define CALIBRATION_STEP_RIGHTTOP       1

#define CALIBRATION_STEP_RIGHTBOTTOM    2

#define CALIBRATION_STEP_LEFTBOTTOM     3

#define CALIBRATION_STEP_CENTER         4

 

// 窗口自定消息代

#define TOUCH_WIN_UPDATE                1

#define TOUCH_WIN_CLOSE                 2

 

// 校准点大小

#define CALIBRATION_WIDTH               15

#define CALIBRATION_HEIGHT              15

 

struct calibration_session

{

    rt_uint8_t step;

 

    struct calibration_data data;

 

    rt_uint16_t width; rt_uint16_t height;

 

    rt_device_t device;

    rt_thread_t tid;

   

    rtgui_win_t* wid;

};

static struct calibration_session* calibration_ptr = RT_NULL;

 

// 校准回函数,初化置到touch device

static void calibration_data_post(rt_uint16_t x, rt_uint16_t y)

{

    if (calibration_ptr != RT_NULL)

    {

        // 取得次校准点的x, y标值,并与上一次求平均

        switch (calibration_ptr->step)

        {

        case CALIBRATION_STEP_LEFTTOP:

            calibration_ptr->data.min_x = x;

            calibration_ptr->data.min_y = y;

            break;

 

        case CALIBRATION_STEP_RIGHTTOP:

            calibration_ptr->data.max_x = x;

            calibration_ptr->data.min_y = (calibration_ptr->data.min_y + y)/2;

            break;

 

        case CALIBRATION_STEP_LEFTBOTTOM:

            calibration_ptr->data.min_x = (calibration_ptr->data.min_x + x)/2;

            calibration_ptr->data.max_y = y;

            break;

 

        case CALIBRATION_STEP_RIGHTBOTTOM:

            calibration_ptr->data.max_x = (calibration_ptr->data.max_x + x)/2;

            calibration_ptr->data.max_y = (calibration_ptr->data.max_y + y)/2;

            break;

 

        case CALIBRATION_STEP_CENTER:

            /* calibration done */

            {

                rt_uint16_t w, h;

 

                // 关闭校准窗口的消息事件

                struct rtgui_event_command ecmd;

                RTGUI_EVENT_COMMAND_INIT(&ecmd);

                ecmd.wid = calibration_ptr->wid;

                ecmd.command_id = TOUCH_WIN_CLOSE;

 

                /* calculate calibrated data */

                if (calibration_ptr->data.max_x > calibration_ptr->data.min_x)

                    w = calibration_ptr->data.max_x - calibration_ptr->data.min_x;

                else

                    w = calibration_ptr->data.min_x - calibration_ptr->data.max_x;

                w = (w/(calibration_ptr->width - 2 * CALIBRATION_WIDTH)) * CALIBRATION_WIDTH;

 

                if (calibration_ptr->data.max_y > calibration_ptr->data.min_y)

                    h = calibration_ptr->data.max_y - calibration_ptr->data.min_y;

                else

                    h = calibration_ptr->data.min_y - calibration_ptr->data.max_y;

                h = (h/(calibration_ptr->height - 2 * CALIBRATION_HEIGHT)) * CALIBRATION_HEIGHT;

 

                rt_kprintf("w: %d, h: %d\n", w, h);

 

                if (calibration_ptr->data.max_x > calibration_ptr->data.min_x)

                {

                    calibration_ptr->data.min_x -= w;

                    calibration_ptr->data.max_x += w;

                }

                else

                {

                    calibration_ptr->data.min_x += w;

                    calibration_ptr->data.max_x -= w;

                }

 

                if (calibration_ptr->data.max_y > calibration_ptr->data.min_y)

                {

                    calibration_ptr->data.min_y -= h;

                    calibration_ptr->data.max_y += h;

                }

                else

                {

                    calibration_ptr->data.min_y += h;

                    calibration_ptr->data.max_y -= h;

                }

 

                rt_kprintf("calibration data: (%d, %d), (%d, %d)\n",

                    calibration_ptr->data.min_x,

                    calibration_ptr->data.max_x,

                    calibration_ptr->data.min_y,

                    calibration_ptr->data.max_y);

                   

                // 关闭校准窗口

                rtgui_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));

            }

            return;

        }

 

        calibration_ptr->step ++;

 

        /* post command event */

        {

            // 送消息,通知窗口画下一个校准点

            struct rtgui_event_command ecmd;

            RTGUI_EVENT_COMMAND_INIT(&ecmd);

            ecmd.wid = calibration_ptr->wid;

            ecmd.command_id = TOUCH_WIN_UPDATE;

 

            rtgui_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));

        }

    }

}

 

// 窗口事件

// 画校准点,关闭窗口

rt_bool_t calibration_event_handler(struct rtgui_object* widget,struct rtgui_event* event)

{

    switch (event->type)

    {

    case RTGUI_EVENT_PAINT:

    {

        struct rtgui_dc* dc;

        struct rtgui_rect rect;

 

        dc = rtgui_dc_begin_drawing((struct rtgui_widget*)widget);

        if (dc == RT_NULL) break;

 

        /* get rect information */

        rtgui_widget_get_rect((struct rtgui_widget*)widget, &rect);

 

        /* clear whole window */

        RTGUI_WIDGET_BACKGROUND(widget) = white;

        rtgui_dc_fill_rect(dc, &rect);

 

        /* reset color */

        RTGUI_WIDGET_BACKGROUND(widget) = green;

        RTGUI_WIDGET_FOREGROUND(widget) = black;

 

        switch (calibration_ptr->step)

        {

            case CALIBRATION_STEP_LEFTTOP:

                rtgui_dc_draw_hline(dc, 0, 2 * CALIBRATION_WIDTH, CALIBRATION_HEIGHT);

                rtgui_dc_draw_vline(dc, CALIBRATION_WIDTH, 0, 2 * CALIBRATION_HEIGHT);

                RTGUI_WIDGET_FOREGROUND(widget) = red;

                rtgui_dc_fill_circle(dc, CALIBRATION_WIDTH, CALIBRATION_HEIGHT, 4);

                break;

 

            case CALIBRATION_STEP_RIGHTTOP:

                rtgui_dc_draw_hline(dc, calibration_ptr->width - 2 * CALIBRATION_WIDTH,

                    calibration_ptr->width, CALIBRATION_HEIGHT);

                rtgui_dc_draw_vline(dc, calibration_ptr->width - CALIBRATION_WIDTH, 0, 2 * CALIBRATION_HEIGHT);

                RTGUI_WIDGET_FOREGROUND(widget) = red;

                rtgui_dc_fill_circle(dc, calibration_ptr->width - CALIBRATION_WIDTH, CALIBRATION_HEIGHT, 4);

                break;

 

            case CALIBRATION_STEP_LEFTBOTTOM:

                rtgui_dc_draw_hline(dc, 0, 2 * CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT);

                rtgui_dc_draw_vline(dc, CALIBRATION_WIDTH, calibration_ptr->height - 2 * CALIBRATION_HEIGHT, calibration_ptr->height);

                RTGUI_WIDGET_FOREGROUND(widget) = red;

                rtgui_dc_fill_circle(dc, CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT, 4);

                break;

 

            case CALIBRATION_STEP_RIGHTBOTTOM:

                rtgui_dc_draw_hline(dc, calibration_ptr->width - 2 * CALIBRATION_WIDTH,

                    calibration_ptr->width, calibration_ptr->height - CALIBRATION_HEIGHT);

                rtgui_dc_draw_vline(dc, calibration_ptr->width - CALIBRATION_WIDTH, calibration_ptr->height - 2 * CALIBRATION_HEIGHT, calibration_ptr->height);

                RTGUI_WIDGET_FOREGROUND(widget) = red;

                rtgui_dc_fill_circle(dc, calibration_ptr->width - CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT, 4);

                break;

 

            case CALIBRATION_STEP_CENTER:

                rtgui_dc_draw_hline(dc, calibration_ptr->width/2 - CALIBRATION_WIDTH, calibration_ptr->width/2 + CALIBRATION_WIDTH, calibration_ptr->height/2);

                rtgui_dc_draw_vline(dc, calibration_ptr->width/2, calibration_ptr->height/2 - CALIBRATION_HEIGHT, calibration_ptr->height/2 + CALIBRATION_HEIGHT);

                RTGUI_WIDGET_FOREGROUND(widget) = red;

                rtgui_dc_fill_circle(dc, calibration_ptr->width/2, calibration_ptr->height/2, 4);

                break;

        }

        rtgui_dc_end_drawing(dc);

    }

        break;

 

    case RTGUI_EVENT_COMMAND:

        {

            struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;

 

            switch (ecmd->command_id)

            {

            case TOUCH_WIN_UPDATE:

                rtgui_widget_update((struct rtgui_widget*)widget);

                break;

            case TOUCH_WIN_CLOSE:

                rtgui_win_close(RTGUI_WIN(widget));

                break;

            }

        }

        return RT_TRUE;

 

    default:

        rtgui_win_event_handler(widget, event);

    }

 

    return RT_FALSE;

}

 

void calibration_entry(void* parameter)

{

    struct rtgui_app *application;

    rtgui_win_t* win;

    struct rtgui_rect rect;

 

    application = rtgui_app_create(rt_thread_self(), "cali_app");

    if (application == RT_NULL)

    {

        return;

    }

   

    // LCD屏幕分辨率

    rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &rect);

 

    /* set screen rect */

    calibration_ptr->width = rect.x2;

    calibration_ptr->height = rect.y2;

 

    /* create calibration window */

    win = rtgui_win_create(RT_NULL,

        "calibration", &rect, RTGUI_WIN_STYLE_NO_TITLE | RTGUI_WIN_STYLE_NO_BORDER);

    if (win == RT_NULL)

    {

            rt_kprintf("calibration_win create fail!\r\n");

            return;

    }

 

    calibration_ptr->wid = win;

    rtgui_object_set_event_handler(RTGUI_OBJECT(win), calibration_event_handler);

    rtgui_win_show(win, RT_TRUE);

   

    rtgui_app_destroy(application);

   

    /* set calibration data */

    rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION_DATA, &calibration_ptr->data);

 

    /* recover to normal */

    rt_device_control(calibration_ptr->device, RT_TOUCH_NORMAL, RT_NULL);

 

    /* release memory */

    rt_free(calibration_ptr);

    calibration_ptr = RT_NULL;

   

}

 

void calibration_init()

{

    rt_device_t device;

 

    device = rt_device_find("touch");

    if (device == RT_NULL) return; /* no this device */

 

    calibration_ptr = (struct calibration_session*)rt_malloc(sizeof(struct calibration_session));

    rt_memset(calibration_ptr, 0, sizeof(struct calibration_data));

    calibration_ptr->device = device;

 

    // 置校准回函数,入校准状

    rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION, (void*)calibration_data_post);

 

    calibration_ptr->tid = rt_thread_create("cali", calibration_entry, RT_NULL,

        2048, 20, 5);

    if (calibration_ptr->tid != RT_NULL) rt_thread_startup(calibration_ptr->tid);

}

 

#ifdef RT_USING_FINSH

#include <finsh.h>

void calibration()

{

    calibration_init();

}

FINSH_FUNCTION_EXPORT(calibration, perform touch calibration);

#endif

 

 

2、  《贪吃蛇》例程

Step1: 在bsp\simulator\rtgui_demo\snake下有两个.c文件和一个.h文件,添加到stm32f10x项目中。

Step2: 在application.c中rt_init_thread_entry()函数的最后,添加calibration_init();

 

Step3: 在calibration.c中calibration_entry()函数的最后,添加snake_main(),在触摸屏校准完成后,进入贪吃蛇程序。

 

Step4: 贪吃蛇程序当前只支持键盘操作,我们还没驱动键盘,要使用触摸屏操作,要添加处理事件(红色部分为添加的代码):

static void snake_mouse_handler(struct rtgui_widget *widget, rtgui_event_t *event)

{

         struct rtgui_event_mouse *emouse;

         rt_uint32_t x, y;

 

         emouse = (struct rtgui_event_mouse *) event;

 

         if ((emouse->button & RTGUI_MOUSE_BUTTON_UP) == RTGUI_MOUSE_BUTTON_UP)

         {

                   x = lattice_rect.x1 + (LATTICE_SIZE * second_node.x);

                   y = (lattice_size_y - 1) - second_node.y;

                   y = lattice_rect.y1 + (LATTICE_SIZE * y);

 

                   if (run_state == SNAKE_DIR_UP || run_state == SNAKE_DIR_DOWN)

                   {

                            if (emouse->x > x + LATTICE_SIZE)

                            {

                                     run_state = SNAKE_DIR_RIGHT;

                            }

                            else

                            {

                                     run_state = SNAKE_DIR_LEFT;

                            }

                   }

                   else

                   {

                            if (emouse->y > y + LATTICE_SIZE)

                            {

                                     run_state = SNAKE_DIR_DOWN;

                            }

                            else

                            {

                                     run_state = SNAKE_DIR_UP;

                            }

                   }

         }

}

 

static rt_bool_t event_handler(struct rtgui_object *object, rtgui_event_t *event)

{

    struct rtgui_widget *widget = RTGUI_WIDGET(object);

 

    rt_kprintf("event_handler\r\n");

 

    if (event->type == RTGUI_EVENT_PAINT)

    {

        rt_kprintf("RTGUI_EVENT_PAINT\r\n");

        rtgui_win_event_handler((struct rtgui_object *)object, event);

        snake_draw(widget);

        rtgui_timer_start(timer);

    }

    else if (event->type == RTGUI_EVENT_SHOW)

    {

        rt_kprintf("RTGUI_EVENT_SHOW\r\n");

        rtgui_win_event_handler((struct rtgui_object *)object, event);

        snake_draw(widget);

        rtgui_timer_start(timer);

    }

    else if (event->type == RTGUI_EVENT_HIDE)

    {

        rt_kprintf("RTGUI_EVENT_HIDE\r\n");

        rtgui_win_event_handler((struct rtgui_object *)object, event);

        rtgui_timer_stop(timer);

    }

    else if (event->type == RTGUI_EVENT_WIN_DEACTIVATE)

    {

        rt_kprintf("RTGUI_EVENT_WIN_DEACTIVATE\r\n");

        rtgui_win_event_handler((struct rtgui_object *)object, event);

        rtgui_timer_stop(timer);

    }

    else if (event->type == RTGUI_EVENT_KBD)

    {

        rtgui_win_event_handler((struct rtgui_object *)object, event);

        snake_handler(widget, event);

    }

         else if (event->type == RTGUI_EVENT_MOUSE_BUTTON)

         {

                   rtgui_win_event_handler((struct rtgui_object *)object, event);

                   snake_mouse_handler(widget, event);

         }

    else

    {

        rt_kprintf("event->type:%d\r\n", event->type);

 

Step5: 添加文字标题(可选),下图选中代码为新增

 

Step6: 编译,下载运行