本节主要介绍LCD触摸屏控制芯片TSC2046驱动的移植,同时展示一个简单的应用示例。
TSC2046为SPI接口触摸屏控制芯片,因此本质上讲,它是个SPI设备驱动。eCos中,编写SPI设备驱动是非常方便的,一般情况下只需要按照datasheet实现其SPI读写时序即可。
eCos源码中没有现成的触摸屏芯片驱动,但令人高兴的是,在一个开源的eCos工程中,有现成的TSC2046驱动,我们可以把它移植过来。
拷贝目录和修改文件
这个开源工程详见eCos论坛中的精华帖子:[开源工程] 在MINI STM32开发板上运行eCos系统
把这个开源工程源码目录:“devs/touch/”下的cortexm和spi拷贝到我们工程的对应目录中。如下图所示。
如果你介意,再把其中的一些文件名、CDL文件中的板名称、包名称、选项名称等等改为你想要的名称。但一个别忘记的是,记得修改触摸屏支持的LCD尺寸值。
配置
修改好后,在你的target中添加相应包:
配置SPI
注意:别忘记了添加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; }
调整的地方:
- 原来,x,y值计算采用spi的读取值0和1,但通过打印读取到的SPI值发现,在我的板子上,x,y值计算应采用1和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; } }
存在问题
- 当前的TSC2046驱动,触摸LCD屏时,虽然可以在LCD上显示一个红色的小方块,但触摸的位置与红色方块的显示位置不一致。这个还需要调整。
- 驱动没有做滤波处理,应用示例中,稍微做了个平均值处理,在实际中显示是不够的。
» 文章出处:
reille博客—http://velep.com
, 如果没有特别声明,文章均为reille博客原创作品
» 郑重声明:
原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)
推荐阅读相关文章:
- stm32移植ecos系列文章归档
- stm32移植ecos #13,redboot引导启动flash中的应用程序映像文件(下)
- stm32移植ecos #12,redboot引导启动flash中的应用程序映像文件(上)
- stm32移植ecos #11,使用自己的模板(Template)
- stm32移植ecos #10,移植ecos并成功运行helloworld程序,烧写到内部flash直接运行helloworld程序
- stm32移植ecos #9,移植ecos并成功运行helloworld程序,使用redboot引导运行内存中的helloworld程序
- stm32移植ecos #8,移植ecos并成功运行helloworld程序,编译链接生成helloworld程序
- stm32移植ecos #7,移植ecos并成功运行helloworld程序,配置编译生成静态链接库文件
串口打印效率很低,GDB调起来也不是太爽,主要还是没个好的IDE,不人性化
你挺速度的。我最近在弄uboot,GCC开发的东西还是挺难用的
现在是想把一些驱动弄好,然后想把这个stm32平台做稳定,不知道可实现否,呵呵!
u-boot我有移植啊,挺容易的。其实,GCC开发并不像你想得这么难用
有好的工具推荐吗,特别是在调试这块
我主要的调试方法的就是打印调试,据说GDB调试不错哦