本节主要介绍LCD触摸屏控制芯片TSC2046驱动的移植,同时展示一个简单的应用示例。

TSC2046为SPI接口触摸屏控制芯片,因此本质上讲,它是个SPI设备驱动。eCos中,编写SPI设备驱动是非常方便的,一般情况下只需要按照datasheet实现其SPI读写时序即可。

eCos源码中没有现成的触摸屏芯片驱动,但令人高兴的是,在一个开源的eCos工程中,有现成的TSC2046驱动,我们可以把它移植过来。

拷贝目录和修改文件

这个开源工程详见eCos论坛中的精华帖子:[开源工程] 在MINI STM32开发板上运行eCos系统

把这个开源工程源码目录:“devs/touch/”下的cortexm和spi拷贝到我们工程的对应目录中。如下图所示。

image

如果你介意,再把其中的一些文件名、CDL文件中的板名称、包名称、选项名称等等改为你想要的名称。但一个别忘记的是,记得修改触摸屏支持的LCD尺寸值。

配置

修改好后,在你的target中添加相应包:

image

配置SPI

image

image

注意:别忘记了添加FILE IO包。

修改驱动

TSC2046的驱动分为平台部分和芯片驱动部分。具体的架构,应该比较容易看得懂。这里讲个TSC2046驱动的修改。

虽然是同样型号的芯片,但不知道为什么,拿过来直接使用却不行,虽然点击触摸屏,应用程序中读取到的x,y值有反应,但却有问题。后面仔细调试了下,发觉SPI读取上有点出入,然后x,y值的计算也有点差异。

下面是调整后的代码(read_ts()函数):

static short
read_ts(int axis)
{
//	short res;

    cyg_spi_device *spi_device = (cyg_spi_device *) ts_dev.priv;
//  const cyg_uint8 tx_buf[1] = { axis | TSC_START | TSC_MODE_12_BIT | TSC_PD0 | TSC_DFR};
//  cyg_uint8 rx_buf[2];

    // Implement the read operation as a multistage SPI transaction.
    cyg_spi_transaction_begin(spi_device);
/*
    cyg_spi_transaction_transfer(spi_device, true,
                                 1, tx_buf, NULL, false);
    cyg_spi_transaction_transfer(spi_device, true, 2, NULL,
                                 rx_buf, false);
*/
    cyg_uint8 tx[8] = {0};
    cyg_uint8 rx[8] = {0};
    tx[0] = (axis | TSC_START | TSC_MODE_12_BIT | TSC_PD0 | TSC_DFR);
    cyg_spi_transaction_transfer(spi_device, true, 4, tx, rx, false);

    cyg_spi_transaction_end(spi_device);

//  res = ( rx_buf[0] << 4 ) + (( rx_buf[1] & 0xF0 ) >> 4);

    cyg_uint16 r = 0;
    r = rx[1];
    r <<= 8;
    r += rx[2];
    r >>= 3;/* 注意这里的处理 */
/*
    diag_printf("--- %d, %03d, %03d, %d : %d, %d, %d, %d --- r = %d ---\n",
        rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7], r);
*/
    return  (short)r;

//  return res;
}

调整的地方:

  1. 原来,x,y值计算采用spi的读取值0和1,但通过打印读取到的SPI值发现,在我的板子上,x,y值计算应采用1和2的值;
  2. 本来,TSC2046是12bit采用,计算的时候原应右移4big,但在安富莱的触摸屏例子程序上发现右移的是3bit,所以计算x,y值有点差异;

上面都是在我的板子实际调试过的。

应用示例

这个应用示例是结合前面2节介绍的LCD应用示例的。

#define STRING1(_a_) # _a_
#define STRING(_a_) STRING1(_a_)

// The colours used by this test code. Default to the standard palette
// but if running on a true colour display then adjust.
static cyg_ucount32 colours[16]  = {
    CYG_FB_DEFAULT_PALETTE_BLACK,
    CYG_FB_DEFAULT_PALETTE_BLUE,
    CYG_FB_DEFAULT_PALETTE_GREEN,
    CYG_FB_DEFAULT_PALETTE_CYAN,
    CYG_FB_DEFAULT_PALETTE_RED,
    CYG_FB_DEFAULT_PALETTE_MAGENTA,
    CYG_FB_DEFAULT_PALETTE_BROWN,
    CYG_FB_DEFAULT_PALETTE_LIGHTGREY,
    CYG_FB_DEFAULT_PALETTE_DARKGREY,
    CYG_FB_DEFAULT_PALETTE_LIGHTBLUE,
    CYG_FB_DEFAULT_PALETTE_LIGHTGREEN,
    CYG_FB_DEFAULT_PALETTE_LIGHTCYAN,
    CYG_FB_DEFAULT_PALETTE_LIGHTRED,
    CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA,
    CYG_FB_DEFAULT_PALETTE_YELLOW,
    CYG_FB_DEFAULT_PALETTE_WHITE
};

#define BLACK        colours[0x00]
#define BLUE         colours[0x01]
#define GREEN        colours[0x02]
#define CYAN         colours[0x03]
#define RED          colours[0x04]
#define MAGENTA      colours[0x05]
#define BROWN        colours[0x06]
#define LIGHTGREY    colours[0x07]
#define DARKGREY     colours[0x08]
#define LIGHTBLUE    colours[0x09]
#define LIGHTGREEN   colours[0x0A]
#define LIGHTCYAN    colours[0x0B]
#define LIGHTRED     colours[0x0C]
#define LIGHTMAGENTA colours[0x0D]
#define YELLOW       colours[0x0E]
#define WHITE        colours[0x0F]

#define FRAMEBUF fb0

#define DEPTH   CYG_FB_DEPTH(FRAMEBUF)
#define WIDTH   CYG_FB_WIDTH(FRAMEBUF)
#define HEIGHT  CYG_FB_HEIGHT(FRAMEBUF)

#define GRID_X_SIZE             400
#define GRID_Y_SIZE             240
#define GRID_ABSOLUTE_X_POS     1
#define GRID_ABSOLUTE_Y_POS     19
#define GRID_STEP               25
#define MAX_X                   (GRID_X_SIZE + GRID_ABSOLUTE_X_POS)
#define MAX_Y                   (GRID_Y_SIZE + GRID_ABSOLUTE_Y_POS)

static void
reset_colours_to_true(void)
{
#if (CYG_FB_FLAGS0_TRUE_COLOUR & CYG_FB_FLAGS0(FRAMEBUF))
    int i;

    for (i = 0; i < 16; i++) {
        colours[i] = CYG_FB_MAKE_COLOUR(FRAMEBUF,
                                        cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
//      diag_printf("colours[%02d] = 0x%06X\n", i, colours[i]);
    }
#endif
}

#include <unistd.h>
#include <fcntl.h>

static int touch_screen_read(short *px, short *py, int *pb, int pd_fd)
{
    /* read a data point */
    short data[4];
    int bytes_read;

    bytes_read = read(pd_fd, data, sizeof(data));
    if (bytes_read != sizeof(data)) {
        return 0;
    }

    *px = data[1];
    *py = data[2];

    *pb = (data[0] ? 0x01 : 0);

    if(! *pb ) {
      return 3;          /* only have button data */
    } else {
      return 2;          /* have full set of data */
    }

    return  0;
}

static void touch_screen_thread(cyg_addrword_t data)
{
    int   pd_fd;
    short px = 0, py = 0;
    int   pb;
    int   ipx = 0, ipy = 0;
    int   cnt = 0;

    pd_fd = open("/dev/ts", O_RDONLY | O_NONBLOCK);
    if (pd_fd < 0) {
       return;
    }

    while (1) {
        // Read all and average
        while (touch_screen_read(&px, &py, &pb, pd_fd)) {
            cnt++;
            ipx += px;
            ipy += py;
        }
        if (cnt) {
            px = ipx / cnt;
            py = ipy / cnt;

            // Draw square from the pencil position
            if (pd_fd) {
                CYG_FB_FILL_BLOCK(FRAMEBUF, px, py, 4, 4, RED);
                diag_printf("=== Pen is down, px = %d, py = %d\n", px, py);
            }
        }

        APPL_OS_MSLEEP(500);
        cnt = 0; ipx = 0; ipy = 0;
    }
}

void lcd_init(void * data)
{
    int i;

    if (CYG_FB_ON(FRAMEBUF)) {
        diag_printf("Open frambuf %s failed!\n", STRING(FRAMEBUF));
        return;
    }

    diag_printf("Frame buffer %s, ", STRING(FRAMEBUF));
    diag_printf("Depth %d, width %d\n", DEPTH, WIDTH);

    // 打开背光
    cyg_fb_ioctl_backlight backlight;
    backlight.fbbl_current = 1;
    i = sizeof(backlight);
    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_BACKLIGHT_SET, &backlight, &i);

    if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_TRUE_COLOUR) {
        reset_colours_to_true();
    }

    // 白色背景
    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0, WIDTH, HEIGHT, WHITE);

    // 画一条横线
    CYG_FB_WRITE_HLINE(FRAMEBUF, 5, 20, 100, RED);

    // 填充一个区域
    CYG_FB_FILL_BLOCK(FRAMEBUF, 5, 30, 100, 20, YELLOW);

    // 一条竖线
    CYG_FB_WRITE_VLINE(FRAMEBUF, 1, 1, 100, BLUE);

    // 一条竖线
    CYG_FB_WRITE_VLINE(FRAMEBUF, 120, 1, 100, GREEN);

    static bool init = false;
    if (init == false) {
    /* Create touch screen thread */
    cyg_thread_create(6,    /* Priority */
                      touch_screen_thread,
                      0,
                      "Touch screen thread",
                      LCD_TS_thread_stack,
                      sizeof(LCD_TS_thread_stack),
                      &LCD_TS_thread_handle,
                      &LCD_TS_thread_block);
    cyg_thread_resume(LCD_TS_thread_handle);/* Starting thread */

    init = true;
    }

}

存在问题

  1. 当前的TSC2046驱动,触摸LCD屏时,虽然可以在LCD上显示一个红色的小方块,但触摸的位置与红色方块的显示位置不一致。这个还需要调整。
  2. 驱动没有做滤波处理,应用示例中,稍微做了个平均值处理,在实际中显示是不够的。
» 文章出处: reille博客—http://velep.com , 如果没有特别声明,文章均为reille博客原创作品
» 郑重声明: 原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)
分享到:

  5 Responses to “stm32移植ecos #21,触摸屏tsc2046驱动移植”

  1. 串口打印效率很低,GDB调起来也不是太爽,主要还是没个好的IDE,不人性化

  2. 你挺速度的。我最近在弄uboot,GCC开发的东西还是挺难用的

Leave a Reply to reille Cancel reply

(必须)

(我会替您保密的)(必须)

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

   
© 2012 velep.com | reille blog | 管理| 粤ICP备15065318号-2| 谷歌地图| 百度地图| Suffusion theme|Sayontan Sinha

无觅相关文章插件,快速提升流量