因为这个F7探索板上有电容触摸的IC,而且这个直接读取坐标特别方便.用的方案是FT5336,支持5点触摸.走I2C协议.这里要说一个很多人容易犯错的地方.就是关于I2C的初始化.用模拟I2C的可以飘过,对于我这种强迫症党来说,模拟I2C几乎不能接受.这个忠告就是,初始化不要初始化两次,初始化不要初始化两次,初始化不要初始化两次!因为初始化两次,时间浪费可以不说,而且很容易引入不明BUG,真的是不明BUG啊,连官方都没法解释.所以如果你知道就是要用这个I2C,开机后就初始化吧,不要等后来再反复初始化.
为了保证能正确和触摸屏通信,通常还会读取触摸屏的ID地址,因为这个电容触摸,封闭性比较高,因此... 寄存器表不好找.找到也不太准,太气人.当然从官方定义头文件,也能看到很多.
按照官方推荐的做法,读4次ID寄存器,如果还没返回,那肯定是有问题的.
uint16_t ft5336_ReadID(uint16_t DeviceAddr) { volatile uint8_t ucReadId = 0; uint8_t nbReadAttempts = 0; uint8_t bFoundDevice = 0; /* Device not found by default */ /* At maximum 4 attempts to read ID : exit at first finding of the searched device ID */ for(nbReadAttempts = 0; ((nbReadAttempts < 3) && !(bFoundDevice)); nbReadAttempts++) { /* Read register FT5336_CHIP_ID_REG as DeviceID detection */ ucReadId = TS_IO_Read(DeviceAddr, FT5336_CHIP_ID_REG); /* Found the searched device ID ? */ if(ucReadId == FT5336_ID_VALUE) { /* Set device as found */ bFoundDevice = 1; } } /* Return the device ID value */ return (ucReadId); }
其他也很简单,照着移植没几分钟就好了.最重要是CTouch_GetState我自己定义的一个函数,原型如下:
uint8_t CTouch_GetState(TS_StateTypeDef *TS_State);
其实这个结构体,可以理解成所有数据:
typedef struct { uint8_t touchDetected; /*!< Total number of active touches detected at last scan */ uint16_t touchX[FT5336_MAX_DETECTABLE_TOUCH]; /*!< Touch X[0], X[1] coordinates on 12 bits */ uint16_t touchY[FT5336_MAX_DETECTABLE_TOUCH]; /*!< Touch Y[0], Y[1] coordinates on 12 bits */ uint8_t touchWeight[FT5336_MAX_DETECTABLE_TOUCH]; /*!< Touch_Weight[0], Touch_Weight[1] : weight property of touches */ uint8_t touchEventId[FT5336_MAX_DETECTABLE_TOUCH]; /*!< Touch_EventId[0], Touch_EventId[1] : take value of type @ref TS_TouchEventTypeDef */ uint8_t touchArea[FT5336_MAX_DETECTABLE_TOUCH]; /*!< Touch_Area[0], Touch_Area[1] : touch area of each touch */ uint32_t gestureId; /*!< type of gesture detected : take value of type @ref TS_GestureIdTypeDef */ } TS_StateTypeDef;
首先看一下有多少点已经触摸,要存起来.
TS_State->touchDetected = ft5336_TS_DetectTouch(FT5336_I2C_SLAVE_ADDRESS);
如果根本没有触摸点,就不需要反馈.所以,直接return就行,不然的话,就要获取点了.两个需求,一个是获取坐标,一个是获取手势.先说说获取手势,方式如下,很简单:
ft5336_TS_GetGestureID(FT5336_I2C_SLAVE_ADDRESS, &gestureId); /* Remap gesture Id to a TS_GestureIdTypeDef value */ switch(gestureId) { case FT5336_GEST_ID_NO_GESTURE : TS_State->gestureId = GEST_ID_NO_GESTURE; break; case FT5336_GEST_ID_MOVE_UP : TS_State->gestureId = GEST_ID_MOVE_UP; break; case FT5336_GEST_ID_MOVE_RIGHT : TS_State->gestureId = GEST_ID_MOVE_RIGHT; break; case FT5336_GEST_ID_MOVE_DOWN : TS_State->gestureId = GEST_ID_MOVE_DOWN; break; case FT5336_GEST_ID_MOVE_LEFT : TS_State->gestureId = GEST_ID_MOVE_LEFT; break; case FT5336_GEST_ID_ZOOM_IN : TS_State->gestureId = GEST_ID_ZOOM_IN; break; case FT5336_GEST_ID_ZOOM_OUT : TS_State->gestureId = GEST_ID_ZOOM_OUT; break; default : ts_status = TS_ERROR; break; } /* of switch(gestureId) */
然后循环获取坐标:
当然,实际上坐标获取后,可能是不对的,比如镜像了之类的.通过这种方法来修正.
if(tsOrientation == TS_SWAP_NONE) { x[index] = brute_x[index]; y[index] = brute_y[index]; } if(tsOrientation & TS_SWAP_X) { x[index] = 4096 - brute_x[index]; } if(tsOrientation & TS_SWAP_Y) { y[index] = 4096 - brute_y[index]; } if(tsOrientation & TS_SWAP_XY) { y[index] = brute_x[index]; x[index] = brute_y[index]; }
因为是电容触摸,可能触摸的是一个区域,所以还需要这么获取.
/* Get touch info related to the current touch */ ft5336_TS_GetTouchInfo(FT5336_I2C_SLAVE_ADDRESS, index, &weight, &area, &event); /* Update TS_State structure */ TS_State->touchWeight[index] = weight; TS_State->touchArea[index] = area; /* Remap touch event */ switch(event) { case FT5336_TOUCH_EVT_FLAG_PRESS_DOWN : TS_State->touchEventId[index] = TOUCH_EVENT_PRESS_DOWN; break; case FT5336_TOUCH_EVT_FLAG_LIFT_UP : TS_State->touchEventId[index] = TOUCH_EVENT_LIFT_UP; break; case FT5336_TOUCH_EVT_FLAG_CONTACT : TS_State->touchEventId[index] = TOUCH_EVENT_CONTACT; break; case FT5336_TOUCH_EVT_FLAG_NO_EVENT : TS_State->touchEventId[index] = TOUCH_EVENT_NO_EVT; break; default : ts_status = TS_ERROR; break; } /* of switch(event) */
经过一轮循环后,结构体就根据不同的触摸点数赋值了.然后这个结构就有用了.