触摸屏输入
- 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;
- 时间:![image.png](https://cdn.nlark.com/yuque/0/2021/png/1658545/1615268827235-75314cff-34f2-42bd-877a-3b6006fdd2c5.png#align=left&display=inline&height=31&margin=%5Bobject%20Object%5D&name=image.png&originHeight=61&originWidth=793&size=52278&status=done&style=none&width=396.5)
- ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1658545/1615268851140-528ab58f-b031-450e-8b16-68fbd335ca27.png#align=left&display=inline&height=97&margin=%5Bobject%20Object%5D&name=image.png&originHeight=194&originWidth=1328&size=178199&status=done&style=none&width=664)
- 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 state
tcgetattr(STDIN_FILENO, &tTTYState);
//turn off canonical mode
tTTYState.c_lflag &= ~ICANON;
//minimum of number input read
tTTYState.c_cc[VMIN] = 1; /* 只要终端有一个数据就立刻返回 */
//set the terminal attributes
tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); /* 设置 */
return 0;
}
/* 在出口函数中恢复输入模式 */
static int StdinDevExit(void)
{
struct termios tTTYState;
//get the terminal state
tcgetattr(STDIN_FILENO, &tTTYState);
//turn on canonical mode
tTTYState.c_lflag |= ICANON;
//set the terminal attributes
tcsetattr(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 0
select(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
```c
static 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