Урок 72
Часть 3
Touch panel FT5336
В предыдущей части занятия мы закончили писать функцию инициализации тачскрина, а также начали писать код процесса отслеживания различных действий TS.
Теперь нам нужна будет функция определения координат действия. Добавим её после функции TS_DetectTouch и напишем в её теле сначала несколько локальных переменных
//----------------------------------------
void TS_GetXY(uint16_t DeviceAddr, uint16_t *X, uint16_t *Y)
{
volatile uint8_t ucReadData = 0;
static uint16_t coord;
uint8_t regAddressXLow = 0;
uint8_t regAddressXHigh = 0;
uint8_t regAddressYLow = 0;
uint8_t regAddressYHigh = 0;
}
//----------------------------------------
Добавим в функцию условие
uint8_t regAddressYHigh = 0;
if(ft5336_handle.currActiveTouchIdx < ft5336_handle.currActiveTouchNb)
{
}
}
В этом условии мы проверяем, что у нас не закончились идентификаторы действий с TS.
Далее в теле условия добавим переключатель switch для реакции на вариант действия
if(ft5336_handle.currActiveTouchIdx < ft5336_handle.currActiveTouchNb)
{
switch(ft5336_handle.currActiveTouchIdx)
{
}
}
Таких вариантов может быть не 5, а 10. У нас будет 5, так как в макросе количества максимальных действий TS у нас стоит 5. Но видимо для дальнейшего развития, а может быть в каких-то моделях это уже есть, регистров для хранения координат действия существует 10 видов. Каждый вид регистров состоит из четырёх регистров. Одна пара — для горизонтальной координаты, другая пара — для вертикальной, так как координата может быть более 256, поэтому на неё отводится 2-байтное хранилище — старший и младший байты. Поэтому вариантов у нас будет 10, как и в примере из репозитория
switch(ft5336_handle.currActiveTouchIdx)
{
case 0 :
regAddressXLow = FT5336_P1_XL_REG;
regAddressXHigh = FT5336_P1_XH_REG;
regAddressYLow = FT5336_P1_YL_REG;
regAddressYHigh = FT5336_P1_YH_REG;
break;
case 1 :
regAddressXLow = FT5336_P2_XL_REG;
regAddressXHigh = FT5336_P2_XH_REG;
regAddressYLow = FT5336_P2_YL_REG;
regAddressYHigh = FT5336_P2_YH_REG;
break;
case 2 :
regAddressXLow = FT5336_P3_XL_REG;
regAddressXHigh = FT5336_P3_XH_REG;
regAddressYLow = FT5336_P3_YL_REG;
regAddressYHigh = FT5336_P3_YH_REG;
break;
case 3 :
regAddressXLow = FT5336_P4_XL_REG;
regAddressXHigh = FT5336_P4_XH_REG;
regAddressYLow = FT5336_P4_YL_REG;
regAddressYHigh = FT5336_P4_YH_REG;
break;
case 4 :
regAddressXLow = FT5336_P5_XL_REG;
regAddressXHigh = FT5336_P5_XH_REG;
regAddressYLow = FT5336_P5_YL_REG;
regAddressYHigh = FT5336_P5_YH_REG;
break;
case 5 :
regAddressXLow = FT5336_P6_XL_REG;
regAddressXHigh = FT5336_P6_XH_REG;
regAddressYLow = FT5336_P6_YL_REG;
regAddressYHigh = FT5336_P6_YH_REG;
break;
case 6 :
regAddressXLow = FT5336_P7_XL_REG;
regAddressXHigh = FT5336_P7_XH_REG;
regAddressYLow = FT5336_P7_YL_REG;
regAddressYHigh = FT5336_P7_YH_REG;
break;
case 7 :
regAddressXLow = FT5336_P8_XL_REG;
regAddressXHigh = FT5336_P8_XH_REG;
regAddressYLow = FT5336_P8_YL_REG;
regAddressYHigh = FT5336_P8_YH_REG;
break;
case 8 :
regAddressXLow = FT5336_P9_XL_REG;
regAddressXHigh = FT5336_P9_XH_REG;
regAddressYLow = FT5336_P9_YL_REG;
regAddressYHigh = FT5336_P9_YH_REG;
break;
case 9 :
regAddressXLow = FT5336_P10_XL_REG;
regAddressXHigh = FT5336_P10_XH_REG;
regAddressYLow = FT5336_P10_YL_REG;
regAddressYHigh = FT5336_P10_YH_REG;
break;
default :
break;
}
В данных вариантах мы записали номера регистров, соответствующих номеру (индексу) действия (или пальца) в соответствующие переменные.
Далее выходим из переключателя switch (но не из условия) и читаем данные из регистров, хранящих значения координат, а затем заносим эти данные в 16-битные переменные, а после этого инкрементируем (наращиваем на 1) индекс действия
break;
}
ucReadData = TS_IO_Read(DeviceAddr, regAddressXLow);
coord = (ucReadData & FT5336_TOUCH_POS_LSB_MASK) >> FT5336_TOUCH_POS_LSB_SHIFT;
ucReadData = TS_IO_Read(DeviceAddr, regAddressXHigh);
coord |= ((ucReadData & FT5336_TOUCH_POS_MSB_MASK) >> FT5336_TOUCH_POS_MSB_SHIFT) << 8;
*X = coord;
ucReadData = TS_IO_Read(DeviceAddr, regAddressYLow);
coord = (ucReadData & FT5336_TOUCH_POS_LSB_MASK) >> FT5336_TOUCH_POS_LSB_SHIFT;
ucReadData = TS_IO_Read(DeviceAddr, regAddressYHigh);
coord |= ((ucReadData & FT5336_TOUCH_POS_MSB_MASK) >> FT5336_TOUCH_POS_MSB_SHIFT) << 8;
*Y = coord;
ft5336_handle.currActiveTouchIdx++; /* next call will work on next touch */
}
}
Функция готова, вернёмся в функцию TS_GetState в наш добавленный цикл и теперь в теле данного цикла вызовем только что написанную функцию определения координат для соответствующего номера действия, записав тем самым координаты в соответствующие переменные
for(index=0; index < TS_State->touchDetected; index++)
{
TS_GetXY(TS_I2C_ADDRESS, &(brute_x[index]), &(brute_y[index]));
}
Затем в этом же цикле запишем эти координаты уже в другие переменные, сделав поправку на ориентацию
TS_GetXY(TS_I2C_ADDRESS, &(brute_x[index]), &(brute_y[index]));
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];
}
}
Произведём ещё некоторые поправки и усреднения и запишем координаты в соответствующие поля структуры статуса TS
x[index] = brute_y[index];
x_diff = x[index] > _x[index]? (x[index] - _x[index]): (_x[index] - x[index]);
y_diff = y[index] > _y[index]? (y[index] - _y[index]): (_y[index] - y[index]);
if ((x_diff + y_diff) > 5)
{
_x[index] = x[index];
_y[index] = y[index];
}
TS_State->touchX[index] = x[index];
TS_State->touchY[index] = y[index];
}
}
}
После функции TS_IO_Write добавим ещё одну функцию для сбора некоторой информации из TS
//----------------------------------------
void TS_GetTouchInfo(uint16_t DeviceAddr,
uint32_t touchIdx,
uint32_t * pWeight,
uint32_t * pArea,
uint32_t * pEvent)
{
volatile uint8_t ucReadData = 0;
uint8_t regAddressXHigh = 0;
uint8_t regAddressPWeight = 0;
uint8_t regAddressPMisc = 0;
}
//----------------------------------------
Добавим в данную функцию условие проверки валидности индекса действия
uint8_t regAddressPMisc = 0;
if(touchIdx < ft5336_handle.currActiveTouchNb)
{
}
}
В теле условия добавим определение индекса
if(touchIdx < ft5336_handle.currActiveTouchNb)
{
switch(touchIdx)
{
}
}
Ну, и по аналогии написания предыдущей функции пробежимся по всем 10 возможным вариантам (хотя физически у нас их 5) и запишем идентификаторы регистров определённых видов действий (сила нажатия, область нажатия, вид события) в соответствующие переменные
switch(touchIdx)
{
case 0 :
regAddressXHigh = FT5336_P1_XH_REG;
regAddressPWeight = FT5336_P1_WEIGHT_REG;
regAddressPMisc = FT5336_P1_MISC_REG;
break;
case 1 :
regAddressXHigh = FT5336_P2_XH_REG;
regAddressPWeight = FT5336_P2_WEIGHT_REG;
regAddressPMisc = FT5336_P2_MISC_REG;
break;
case 2 :
regAddressXHigh = FT5336_P3_XH_REG;
regAddressPWeight = FT5336_P3_WEIGHT_REG;
regAddressPMisc = FT5336_P3_MISC_REG;
break;
case 3 :
regAddressXHigh = FT5336_P4_XH_REG;
regAddressPWeight = FT5336_P4_WEIGHT_REG;
regAddressPMisc = FT5336_P4_MISC_REG;
break;
case 4 :
regAddressXHigh = FT5336_P5_XH_REG;
regAddressPWeight = FT5336_P5_WEIGHT_REG;
regAddressPMisc = FT5336_P5_MISC_REG;
break;
case 5 :
regAddressXHigh = FT5336_P6_XH_REG;
regAddressPWeight = FT5336_P6_WEIGHT_REG;
regAddressPMisc = FT5336_P6_MISC_REG;
break;
case 6 :
regAddressXHigh = FT5336_P7_XH_REG;
regAddressPWeight = FT5336_P7_WEIGHT_REG;
regAddressPMisc = FT5336_P7_MISC_REG;
break;
case 7 :
regAddressXHigh = FT5336_P8_XH_REG;
regAddressPWeight = FT5336_P8_WEIGHT_REG;
regAddressPMisc = FT5336_P8_MISC_REG;
break;
case 8 :
regAddressXHigh = FT5336_P9_XH_REG;
regAddressPWeight = FT5336_P9_WEIGHT_REG;
regAddressPMisc = FT5336_P9_MISC_REG;
break;
case 9 :
regAddressXHigh = FT5336_P10_XH_REG;
regAddressPWeight = FT5336_P10_WEIGHT_REG;
regAddressPMisc = FT5336_P10_MISC_REG;
break;
default :
break;
}
Выйдем из switch (не из условия) и запросим данные значения, обратившись в соответствующие регистры по шине I2C и запишем эти значения по адресам входящих аргументов функции для дальнейшего их использования после выхода из неё
break;
}
ucReadData = TS_IO_Read(DeviceAddr, regAddressXHigh);
* pEvent = (ucReadData & FT5336_TOUCH_EVT_FLAG_MASK) >> FT5336_TOUCH_EVT_FLAG_SHIFT;
ucReadData = TS_IO_Read(DeviceAddr, regAddressPWeight);
* pWeight = (ucReadData & FT5336_TOUCH_WEIGHT_MASK) >> FT5336_TOUCH_WEIGHT_SHIFT;
ucReadData = TS_IO_Read(DeviceAddr, regAddressPMisc);
* pArea = (ucReadData & FT5336_TOUCH_AREA_MASK) >> FT5336_TOUCH_AREA_SHIFT;
}
Фунция закончена.
Перейдём в файл ft5336.h и добавим перечисление идентификаторов событий TS
}TS_StatusTypeDef;
//------------------------------------------
typedef enum
{
TOUCH_EVENT_NO_EVT = 0x00, /*!< Touch Event : undetermined */
TOUCH_EVENT_PRESS_DOWN = 0x01, /*!< Touch Event Press Down */
TOUCH_EVENT_LIFT_UP = 0x02, /*!< Touch Event Lift Up */
TOUCH_EVENT_CONTACT = 0x03, /*!< Touch Event Contact */
TOUCH_EVENT_NB_MAX = 0x04 /*!< max number of touch events kind */
} TS_TouchEventTypeDef;
//------------------------------------------
Вернёмся в файл ft5336.c и вызовем только что написанную нами функцию в функции TS_GetState и запишем после вызова из возвращённых адресов значения в соответствующие поля статуса TS
TS_State->touchY[index] = y[index];
TS_GetTouchInfo(TS_I2C_ADDRESS, index, &weight, &area, &event);
TS_State->touchWeight[index] = weight;
TS_State->touchArea[index] = area;
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;
}
}
В следующей части занятия мы закончим писать функцию определения всех статусов TS и воспользуемся ей на практике, добавив определённый код для теста в бесконечном цикле.
Предыдущая часть Программирование МК STM32 Следующая часть
Техническая документация на драйвер TS FT5336
Отладочную плату можно приобрести здесь STM32F746G-DISCOVERY
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий