Сообщение от true71
|
Я с МикроПаскаля для пик16-18 пример разбирал. Правда, он тоже кривоватый, но начальный толчок даст. Разберетесь.
|
нее, это не то
у меня тот же пример из библиотеки Microchip есть, только с ним какие-то проблемы: события нажатия или отжатия формируются через раз. Частоту опроса повышал, не помогает
вот код, может кто подскажет как сделать правильно?
файл main.c:
.....
int main (void)
{
....
InitTouch();
while (1)
{
TouchMenu();
......
}
return 1;
}
файл TouchScreen.c:
#ifndef _TOUCHSCREEN_H
#define _TOUCHSCREEN_H
#include "TouchScreen.h"
#include "pictures.h"
#include ‹p24Fxxxx.h›
// ADC Status
#define TOUCH_ADC_DONE AD1CON1bits.DONE
#define ADC_XPOS 3 // 3 канал АЦП
#define ADC_YPOS 4 // 4 канал АЦП
// Y port definitions
#define ADPCFG_XPOS AD1PCFGbits.PCFG3
#define LAT_XPOS LATBbits.LATB3
#define LAT_XNEG LATBbits.LATB5
#define TRIS_XPOS TRISBbits.TRISB3
#define TRIS_XNEG TRISBbits.TRISB5
// X port definitions
#define ADPCFG_YPOS AD1PCFGbits.PCFG4
#define LAT_YPOS LATBbits.LATB4
#define LAT_YNEG LATBbits.LATB2
#define TRIS_YPOS TRISBbits.TRISB4
#define TRIS_YNEG TRISBbits.TRISB2
// Default calibration values
#define YMINCAL 0x0070
#define YMAXCAL 0x0370
#define XMINCAL 0x007A
#define XMAXCAL 0x0350
//////////////////////// GLOBAL VARIABLES ////////////////////////////
#define PRESS_THRESHOULD 256 // between 0-0x03ff the lesser this value the lighter the screen must be pressed
// Max/Min ADC values for each derection
volatile unsigned short _calXMin = XMINCAL;
volatile unsigned short _calXMax = XMAXCAL;
volatile unsigned short _calYMin = YMINCAL;
volatile unsigned short _calYMax = YMAXCAL;
// Current ADC values for X and Y channels
volatile short adcX = 0;
volatile short adcY = 0;
extern volatile char run;
typedef enum
{
SET_X,
RUN_X,
GET_X,
CHECK_X,
SET_Y,
RUN_Y,
GET_Y,
CHECK_Y,
SET_VALUES
} TOUCH_STATES;
typedef enum
{
EVENT_INVALID = 0, // An invalid event.
EVENT_MOVE, // A move event.
EVENT_PRESS, // A press event.
EVENT_STILLPRESS, // A continuous press event.
EVENT_RELEASE, // A release event.
} INPUT_DEVICE_EVENT;
typedef struct
{
unsigned uiEvent; // The generic events for input device.
short param1; // Parameter 1 meaning is dependent on the type of input device.
short param2; // Parameter 2 meaning is dependent on the type of input device.
} GOL_MSG;
volatile TOUCH_STATES state = SET_X;
/************************************************** *******************
* Macros: ADCGetX()
* Overview: returns ADC value for x direction if touch screen is pressed
* and 0 if not
************************************************** ******************/
#define ADCGetX() adcX
#define ADCGetY() adcY
#define GetMaxX() 127
#define GetMaxY() 159
void TouchProcessTouch(void);
extern void DisplayPicture (unsigned short PictureAddress, unsigned char width, unsigned char height, unsigned char x_offset, unsigned char y_offset, int frames_count);
// Touch Screen timer ISR
void __attribute__((interrupt, shadow, auto_psv)) _T4Interrupt(void)
{
TouchProcessTouch();
IFS1bits.T4IF = 0; // Clear flag
}
void TouchProcessTouch(void)
{
static short tempX, tempY;
short temp;
switch (state)
{
case SET_VALUES:
if (!TOUCH_ADC_DONE)
break;
if ((unsigned short) PRESS_THRESHOULD ‹ (unsigned short) ADC1BUF0)
{
adcX = 0;
adcY = 0;
}
else
{
adcX = tempX;
adcY = tempY;
}
state = SET_X;
case SET_X:
AD1CHS = ADC_XPOS; // switch ADC channel
TRIS_XPOS = 1;
TRIS_YPOS = 1;
TRIS_XNEG = 1;
LAT_YNEG = 0;
TRIS_YNEG = 0;
AD1CON1bits.SAMP = 1; // run conversion
state = CHECK_X;
break;
case CHECK_X:
case CHECK_Y:
if (!TOUCH_ADC_DONE)
break;
if ((unsigned short) PRESS_THRESHOULD › (unsigned short) ADC1BUF0)
{
if (state == CHECK_X)
{
LAT_YPOS = 1;
TRIS_YPOS = 0;
tempX = 0;
state = RUN_X;
}
else
{
LAT_XPOS = 1;
TRIS_XPOS = 0;
tempY = 0;
state = RUN_Y;
}
}
else
{
adcX = 0;
adcY = 0;
state = SET_X;
break;
}
case RUN_X:
case RUN_Y:
AD1CON1bits.SAMP = 1;
state = (state == RUN_X) ? GET_X : GET_Y;
// no break needed here since the next state is either GET_X or GET_Y
case GET_X:
case GET_Y:
if (!TOUCH_ADC_DONE)
break;
temp = ADC1BUF0;
if (state == GET_X)
{
if (temp != tempX)
{
tempX = temp;
state = RUN_X;
break;
}
}
else
{
if (temp != tempY)
{
tempY = temp;
state = RUN_Y;
break;
}
}
if (state == GET_X)
TRIS_YPOS = 1;
else
TRIS_XPOS = 1;
AD1CON1bits.SAMP = 1;
state = (state == GET_X) ? SET_Y : SET_VALUES;
break;
case SET_Y:
if (!TOUCH_ADC_DONE)
break;
if ((unsigned short) PRESS_THRESHOULD ‹ (unsigned short) ADC1BUF0)
{
adcX = 0;
adcY = 0;
state = SET_X;
break;
}
AD1CHS = ADC_YPOS; // switch ADC channel
TRIS_XPOS = 1;
TRIS_YPOS = 1;
LAT_XNEG = 0;
TRIS_XNEG = 0;
TRIS_YNEG = 1;
AD1CON1bits.SAMP = 1; // run conversion
state = CHECK_Y;
break;
default:
state = SET_X;
}
}
void InitTouch()
{
// Initialize ADC
AD1CON3 = 0x1FFF; // 31 Tad auto-sample, Tad = 256*Tcy
// inputs are analog
ADPCFG_XPOS = 0;
ADPCFG_YPOS = 0;
T4CON = 0; // Timer reset
IFS1bits.T4IF = 0; // Reset Timer4 interrupt flag
IPC6bits.T4IP = 4; // Timer4 Interrupt priority level=4
T4CONbits.TCKPS = 0; // Timer1 Input Clock Prescale Select bits = 1:8
T4CONbits.TCS = 0;
TMR4 = 0x0000;
PR4 = 0x0a1f; // Чем меньше, тем быстрее опрос
AD1CON1bits.ADON = 1;
}
// x coordinate
short TouchGetX(void)
{
unsigned long result, p1,p2,p3;
result = ADCGetX();
if (result › _calXMin)
{
p1 = adcX;
p2 = _calXMin;
p3 = _calXMax;
result = GetMaxX() * (p1 - p2) / (p3 - p2);
result = GetMaxX() - result; // FLAP
return (result);
}
else
{
return (0);
}
}
// y coordinate
short TouchGetY(void)
{
unsigned long result, p1,p2,p3;
result = ADCGetY();
if (result › _calYMin)
{
p1 = adcY;
p2 = _calYMin;
p3 = _calYMax;
result = GetMaxY() * (p1 - p2) / (p3 - p2);
return (result);
}
else
{
return (0);
}
}
void TouchGetMsg(GOL_MSG *pMsg)
{
static short prevX = 0;
static short prevY = 0;
short touch_x, touch_y;
touch_x = TouchGetX();
touch_y = TouchGetY();
pMsg-›uiEvent = EVENT_INVALID;
if (touch_x == 0)
{
touch_y = 0;
}
else
{
if (touch_y == 0)
touch_x = 0;
}
// удерживается нажатой область
if ((prevX == touch_x) && (prevY == touch_y) && (touch_x != 0) && (touch_y != 0))
{
pMsg-›uiEvent = EVENT_STILLPRESS;
pMsg-›param1 = touch_x;
pMsg-›param2 = touch_y;
return;
}
if ((prevX != 0) || (prevY != 0))
{
if ((touch_x != 0) && (touch_y != 0))
{
// Move - перемещается палец, сюда можно добавить в какую сторону и на сколько перемещается
pMsg-›uiEvent = EVENT_MOVE;
}
else
{
// Released - палец отпущен
pMsg-›uiEvent = EVENT_RELEASE;
pMsg-›param1 = prevX;
pMsg-›param2 = prevY;
prevX = touch_x;
prevY = touch_y;
return;
}
}
else
{
if ((touch_x != 0) && (touch_y != 0))
{
// Pressed - палец нажат после "молчания" (были нули) тачскрина
pMsg-›uiEvent = EVENT_PRESS;
}
else
{
// No message - нет нажатия
pMsg-›uiEvent = EVENT_INVALID;
}
}
pMsg-›param1 = touch_x;
pMsg-›param2 = touch_y;
prevX = touch_x;
prevY = touch_y;
}
// обработка тачскрина
void GOLMsg(GOL_MSG *pMsg)
{
if(pMsg-›uiEvent == EVENT_RELEASE)
{
//return;
DisplayPicture(0x54,1); // кнопка отжата
}
else if(pMsg-›uiEvent == EVENT_PRESS)
{
if (((2 ‹ pMsg-›param1) && (pMsg-›param1 ‹ 126)) && (pMsg-›param2 ‹ 143) && (114 ‹ pMsg-›param2))
{
DisplayPicture(0x40,1); // кнопка нажата
}
}
}
void TouchMenu(void)
{
GOL_MSG msg; // GOL message structure to interact with GOL (тачскрин)
TouchGetMsg(&msg); // Get message from touch screen
GOLMsg(&msg); // обработка тачскрина
}
// включить тачскрин
void TouchON(void)
{
IEC1bits.T4IE = 1; // Enable Timer4 interrupt
T4CONbits.TON = 1;
}
// выключить тачскрин
void TouchOFF(void)
{
IEC1bits.T4IE = 0; // Enable Timer4 interrupt
T4CONbits.TON = 0;
}
#endif // #if defined (USE_RESISTIVE_TOUCH)