触摸屏输入

  • 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;

  1. - 时间:![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)
  2. - ![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)
  3. - input_manager中需要实现几个函数:
  4. - 提供给下层程序注册的函数InputOprRegister()
  5. - 统一的初始化函数InputOprInit()
  6. - 提供查询有哪些输入ShowInputOpr()
  7. <a name="6F0ql"></a>
  8. # 轮询方式
  9. - stdin.c
  10. ```c
  11. #include <input_manager.h>
  12. /* 声明输入操作对象中要实现的几个函数 */
  13. static int StdinDevInit(void);
  14. static int StdinDevExit(void);
  15. static int StdinGetInputEvent(PT_InputEvent ptInputEvent);
  16. /* 定义输入操作对象 */
  17. static T_InputOpr g_tStdinOpr = {
  18. .name = "stdin",
  19. .DeviceInit = StdinDevInit,
  20. .DeviceExit = StdinDevExit,
  21. .GetInputEvent = StdinGetInputEvent,
  22. }
  23. /* 实现输入操作对象中要实现的几个函数 */
  24. //放在后面
  25. /* 注册结构体(向上层input_manager提供的函数) */
  26. int StdinInit(void)
  27. {
  28. return RegisterInputOpr(&g_tStdinOpr);
  29. }
  • scanf函数无法立刻返回,它会休眠直到有数据输入并回车
  • 在stdin上以非阻塞的方式获得输入(stdin nonblock)

    1. #include <termios.h>
    2. #include <unistd.h>
    3. /* 在入口函数中,修改输入模式为非阻塞 */
    4. static int StdinDevInit(void)
    5. {
    6. struct termios tTTYState;
    7. //get the terminal state
    8. tcgetattr(STDIN_FILENO, &tTTYState);
    9. //turn off canonical mode
    10. tTTYState.c_lflag &= ~ICANON;
    11. //minimum of number input read
    12. tTTYState.c_cc[VMIN] = 1; /* 只要终端有一个数据就立刻返回 */
    13. //set the terminal attributes
    14. tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); /* 设置 */
    15. return 0;
    16. }
    17. /* 在出口函数中恢复输入模式 */
    18. static int StdinDevExit(void)
    19. {
    20. struct termios tTTYState;
    21. //get the terminal state
    22. tcgetattr(STDIN_FILENO, &tTTYState);
    23. //turn on canonical mode
    24. tTTYState.c_lflag |= ICANON;
    25. //set the terminal attributes
    26. tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState); /* 设置 */
    27. return 0;
    28. }
  • StdinGeytInputEvent()

    1. static int StdinGetInputEvent(PT_InputEvent ptInputEvent)
    2. {
    3. /* 如果有数据就读取、处理、返回
    4. * 如果没有数据,立刻返回错误,不等待
    5. */
    6. /* select,poll可以参考 unix环境高级编程 */
    7. struct timeval tTV;
    8. fd_set tFDs;
    9. char c;
    10. tTV.tv_sec = 0;
    11. tTV.tv_usec = 0;
    12. FD_ZERO(&tFDs);
    13. FD_SET(STDIN_FILENO, &tFDs); //STDIN_FILENO is 0
    14. select(STDIN_FILENO+1, &tFDs, NULL, NULL, &tTV);
    15. if( FD_ISSET(STDIN_FILENO, &tFDs) ) //有数据
    16. {
    17. /* 处理数据 */
    18. ptInputEvent->iType = INPUT_TYPE_STDIN;
    19. gettimeofday(&ptInputEvent->iTime, NULL);
    20. c = fgetc(stdin);
    21. if(c == 'u'){
    22. ptInputEvent->iVal = INPUT_VALUE_UP;
    23. }else if(c == 'n'){
    24. ptInputEvent->iVal = INPUT_VALUE_DOWN;
    25. }else if(c == 'q'){
    26. ptInputEvent->iVal = INPUT_VALUE_EXIT;
    27. }else{
    28. ptInputEvent->iVal = INPUT_VALUE_UNKNOW;
    29. }
    30. }else
    31. {
    32. return -1;
    33. }
    34. return 0;
    35. }
  • 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); }

  1. - 对触摸屏的使用,需要参考tslib
  2. ```c
  3. static int g_iXres,g_iYres;
  4. int TouchScreenDevInit(void)
  5. {
  6. char *pcTSName = NULL;
  7. if( (pcTSName = getenv("TSLIB_TSDEVICE")) != NULL)
  8. {
  9. g_tTSDev = = ts_open(pcTSName, 1); /* 以非阻塞方式打开 */
  10. }else
  11. {
  12. g_tTSDev = = ts_open("/dev/event0", 1); /* 默认打开event0 */
  13. }
  14. if(!g_tTSDev)
  15. {
  16. DBG_PRINT("ts_open error\n");
  17. return -1;
  18. }
  19. /* 配置 */
  20. if( ts_config(g_tTSDev) )
  21. {
  22. DBG_PRINT("ts_config error\n");
  23. return -1;
  24. }
  25. /* 获取X/Y分辨率 */
  26. if ( GetDispResolution(&g_iXres, &g_iYres) )
  27. {
  28. return -1;
  29. }
  30. return 0;
  31. }
  32. int TouchScreenDevExit(void)
  33. {
  34. return 0;
  35. }
  • 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){

    1. DBG_PRINT("ts_read error");
    2. return -1;

    } / 处理数据 / if( isOutOf500ms(&tPreTime, &tSamp.tv) ) {

    1. /* 如果此次触摸事件发生的时间距上次事件发生事件超过500ms,才认为是一次输入 */
    2. tPreTime = tSamp.tv;
    3. ptInputEvent->iType = tSamp.tv;
    4. ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;
    5. if(tSamp.y < g_iYres/3)
    6. {
    7. ptInputEvent->iVal = INPUT_VALUE_UP;
    8. }else if(tSamp.y > g_iYres/3 * 2)
    9. {
    10. ptInputEvent->iVal = INPUT_VALUE_DOWN;
    11. }else
    12. {
    13. ptInputEvent->iVal = INPUT_VALUE_UNKNOW;
    14. }

    }else {

    1. 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;

  1. return (iNowMs > iPreMs + 500);

} ```

  • 触摸屏点一下会得到多个数据

  • 启动开发板后安装各种触摸屏驱动程序等等

  • 搭建运行环境:2.6.22.6内核看第2期视频触摸屏章节,3.4.2内核看第2期视频毕业班里的相关章节

  • 轮询方式, CPU占用率很高

  • 要用标准输入,必须要让程序位于前台

  • telnetd

  • image.png
  • image.png