触摸屏输入
- tslib库
```c
define INPUT_TYPE_STDIN 0
define INPUT_TYPE_TOUCHSCREEN 1
define INPUT_VALUE_UP 0 //上翻
define INPUT_VALUE_DOWN 1 //下翻
define INPUT_VALUE_EXIT 2 //退出
define INPUT_VALUE_UNKNOW 3 //未知
/ 抽象出输入事件 / typedef strut InputEvent{ struct timeval tTime; / 时间 / int iType; / 输入事件类别, stdin/ts… / int iVal; / 输入的值,0/1/2 / }T_InputEvent, *PT_InputEvent;
/ 抽象出一个输入操作的结构体 / typedef struct InputOpr{ char name; int (DeviceInit)(void); int (DeviceExit)(void); int (GetInputEvent)(PT_InputEvent ptInputEvent); / 获取输入事件 / struct InputOpr ptNext; }T_InputOpr, PT_InputOpr;
- 时间:- - input_manager中需要实现几个函数:- 提供给下层程序注册的函数InputOprRegister()- 统一的初始化函数InputOprInit()- 提供查询有哪些输入ShowInputOpr()<a name="6F0ql"></a># 轮询方式- stdin.c```c#include <input_manager.h>/* 声明输入操作对象中要实现的几个函数 */static int StdinDevInit(void);static int StdinDevExit(void);static int StdinGetInputEvent(PT_InputEvent ptInputEvent);/* 定义输入操作对象 */static T_InputOpr g_tStdinOpr = {.name = "stdin",.DeviceInit = StdinDevInit,.DeviceExit = StdinDevExit,.GetInputEvent = StdinGetInputEvent,}/* 实现输入操作对象中要实现的几个函数 *///放在后面/* 注册结构体(向上层input_manager提供的函数) */int StdinInit(void){return RegisterInputOpr(&g_tStdinOpr);}
- scanf函数无法立刻返回,它会休眠直到有数据输入并回车
在stdin上以非阻塞的方式获得输入(stdin nonblock)
#include <termios.h>#include <unistd.h>/* 在入口函数中,修改输入模式为非阻塞 */static int StdinDevInit(void){struct termios tTTYState;//get the terminal statetcgetattr(STDIN_FILENO, &tTTYState);//turn off canonical modetTTYState.c_lflag &= ~ICANON;//minimum of number input readtTTYState.c_cc[VMIN] = 1; /* 只要终端有一个数据就立刻返回 *///set the terminal attributestcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); /* 设置 */return 0;}/* 在出口函数中恢复输入模式 */static int StdinDevExit(void){struct termios tTTYState;//get the terminal statetcgetattr(STDIN_FILENO, &tTTYState);//turn on canonical modetTTYState.c_lflag |= ICANON;//set the terminal attributestcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); /* 设置 */return 0;}
StdinGeytInputEvent()
static int StdinGetInputEvent(PT_InputEvent ptInputEvent){/* 如果有数据就读取、处理、返回* 如果没有数据,立刻返回错误,不等待*//* select,poll可以参考 unix环境高级编程 */struct timeval tTV;fd_set tFDs;char c;tTV.tv_sec = 0;tTV.tv_usec = 0;FD_ZERO(&tFDs);FD_SET(STDIN_FILENO, &tFDs); //STDIN_FILENO is 0select(STDIN_FILENO+1, &tFDs, NULL, NULL, &tTV);if( FD_ISSET(STDIN_FILENO, &tFDs) ) //有数据{/* 处理数据 */ptInputEvent->iType = INPUT_TYPE_STDIN;gettimeofday(&ptInputEvent->iTime, NULL);c = fgetc(stdin);if(c == 'u'){ptInputEvent->iVal = INPUT_VALUE_UP;}else if(c == 'n'){ptInputEvent->iVal = INPUT_VALUE_DOWN;}else if(c == 'q'){ptInputEvent->iVal = INPUT_VALUE_EXIT;}else{ptInputEvent->iVal = INPUT_VALUE_UNKNOW;}}else{return -1;}return 0;}
select函数和poll函数是一样的
touchscreen.c ```c
include
/ 参考tslib里的ts_print.c, 里面实现打印触摸屏转换成LCD坐标的数据 /
static struct tsdev g_tTSDev; / 定义输入操作对象 / static T_InputOpr g_tTouchScreenOpr = { .name = “touchscreen”, .DeviceInit = TouchScreenDevInit, .DeviceExit = TouchScreenDevExit, .GetInputEvent = TouchScreenGetInputEvent, }; / 提供注册结构体函数供上层input_manager使用 / int TouchScreenInit(void) { return RegisterInputOpr(&g_tTouchScreenOpr); }
- 对触摸屏的使用,需要参考tslib```cstatic int g_iXres,g_iYres;int TouchScreenDevInit(void){char *pcTSName = NULL;if( (pcTSName = getenv("TSLIB_TSDEVICE")) != NULL){g_tTSDev = = ts_open(pcTSName, 1); /* 以非阻塞方式打开 */}else{g_tTSDev = = ts_open("/dev/event0", 1); /* 默认打开event0 */}if(!g_tTSDev){DBG_PRINT("ts_open error\n");return -1;}/* 配置 */if( ts_config(g_tTSDev) ){DBG_PRINT("ts_config error\n");return -1;}/* 获取X/Y分辨率 */if ( GetDispResolution(&g_iXres, &g_iYres) ){return -1;}return 0;}int TouchScreenDevExit(void){return 0;}
TouchScreenGetInputEvent() ```c int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent) { struct ts_sample tSamp; / 采样值 / int iRet; static struct timeval tPreTime;
iRet = ts_read(g_tTSDev, &tSamp, 1); if(iRet < 0){
DBG_PRINT("ts_read error");return -1;
} / 处理数据 / if( isOutOf500ms(&tPreTime, &tSamp.tv) ) {
/* 如果此次触摸事件发生的时间距上次事件发生事件超过500ms,才认为是一次输入 */tPreTime = tSamp.tv;ptInputEvent->iType = tSamp.tv;ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;if(tSamp.y < g_iYres/3){ptInputEvent->iVal = INPUT_VALUE_UP;}else if(tSamp.y > g_iYres/3 * 2){ptInputEvent->iVal = INPUT_VALUE_DOWN;}else{ptInputEvent->iVal = INPUT_VALUE_UNKNOW;}
}else {
return -1;
}
return 0; }
/ 判断和上一次事件的事件是否超过了500ms / static int isOutOf500ms(struct timeval ptPreTime, struct timeval ptNowTime) { int iPreMs, iNowMs; iPreMs = ptPreTime->tv_sec 1000 + ptPreTime->tv_usec / 1000; iNowMs = ptNowTime->tv_sec 1000 + ptNowTime->tv_usec / 1000;
return (iNowMs > iPreMs + 500);
} ```
触摸屏点一下会得到多个数据
启动开发板后安装各种触摸屏驱动程序等等
搭建运行环境:2.6.22.6内核看第2期视频触摸屏章节,3.4.2内核看第2期视频毕业班里的相关章节
轮询方式, CPU占用率很高
要用标准输入,必须要让程序位于前台
telnetd


