touch.zip

driver touchpad-a rezystancyjnego - AD7843

Załączam dwa przykłady, może coś pomogą

  • touch.zip
    • demo.c
    • touch.h
    • HowTo Touch screen.doc
    • touch.c


Pobierz plik - link do postu

touch.zip > demo.c

#include " touch.h "
#include " s1d13700.h "
#include " glcd.h "

void add_button(unsigned int xpos, unsigned int ypos, PGM_VOID_P txt)
{
point_t p1,p2;
p1.x= p2.x = xpos;
p1.y= p2.y = ypos;
if (glcd_text_widthP(txt) & lt; 40) p2.x +=40;
else p2.x= xpos+ glcd_text_widthP(txt)+8;

p2.y= ypos+glcd_FontHeight+4;
lcd_layer(BTN_LAYER);
lcd_print_rect(p1, p2);
lcd_layer(TXT_LAYER);
glcd_textP(txt,0,CENTER_VIEW,xpos+2, ypos+2,0);
add_area(p1, p2);
}

void clear_buttons(void)
{
clear_areas();
lcd_clrscrn(BTN_LAYER); // clears Layer : BTN_LAYER
lcd_clrscrn(TXT_LAYER); // clears Layer : TXT_LAYER
}

void calibrate_touchscreen(void)
{
static const char txt_touch1[] PROGMEM = { " TOUCH KALIBRIERUNG " };
static const char txt_touch2[] PROGMEM = { " Bitte berühre das Fadenkreuz " };
static const char txt_speichern[] PROGMEM = { " Daten speichern ? " };
static const char txt_ja[] PROGMEM = { " Ja " };
static const char txt_nein[] PROGMEM = { " Nein " };
static const char txt_gespeichert[] PROGMEM = { " gespeichert .... " };

point_t p1, p2;
// draw cross at position 1
p1.x = 20;
p1.y = 20;
lcd_print_cross(p1, 10, 10); // prints a cross onto the display position
glcd_select_font(F_LARGE); // this function specifys the font for writing text onto the display
glcd_textP(txt_touch1,0,LEFT_VIEW,50,100,0); // this function writes a graphical text onto the display
glcd_textP(txt_touch2,0,LEFT_VIEW,60,0,0); // this function writes a graphical text onto the display

clear_settings(); // enable capturing adc values
capture_point(1); // capture first point for x and y position
lcd_clrscrn(1);
delay_ms(300);
glcd_textP(txt_touch1,0,LEFT_VIEW,50,100,0); // this function writes a graphical text onto the display
glcd_textP(txt_touch2,0,LEFT_VIEW,0,217,0); // this function writes a graphical text onto the display

// draw cross at position 2
p2.x = PIXELX - 20;
p2.y = PIXELY - 20;
lcd_print_cross(p2, 10, 10); // prints a cross onto the display position

capture_point(2); // capture second point
lcd_clrscrn(1); // clears the display screen
calc_config(p1, p2); // calculates parameters for scale and offset of touch screen
glcd_textP(txt_speichern,0,LEFT_VIEW,80,100,0);// thsi function writes a graphical text onto the display
clear_areas(); // clears the touch areas which has been defined
add_button(100,130 ,txt_ja); // adds a button with a rectangle on the screen and the text
add_button(170,130, txt_nein); // adds a button with a rectangle on the screen and the text
delay_ms(1000); // delay function 1 second
int8_t res=capture_area() ; // captures a voltage for x and y
clear_buttons(); // clears buttons and the displayed rectangles and text
if (res== 1)
{

glcd_textP(txt_gespeichert,0,LEFT_VIEW,80,120,0);// this function writes a graphical text onto the display
save_touch_settings(); // writes settings to EEPROM
delay_ms(500);
lcd_clrscrn(TXT_LAYER);
}
lcd_clrscrn(0); // clears all layers of display screen
}


int main(void)
{
lcd_init();
if (touch_init(1)==-1) calibrate_touchscreen();
point_t pos1;
while(1==1)
{
if (read_touch()==1)
{
pos1.x=touch_pos.x;
pos1.y=touch_pos.y;
lcd_print_pixel(pos1); // prints one pixel to the pressed display position
}
}
}


touch.zip > touch.h

//************************************************************************
// For 4 wire resistive touch screens
// Functions for reading position of touchscreen press
// uses ADC of Mega Prozessor for calculating the position
// Klaus Meinhardt created 12.01.2008
//************************************************************************
// Declaration of 32 buttons with start point end end point
// Resolution of point is 2 pixel (for screen with maximal 512x512 pixel)
//************************************************************************
#include " S1D13700.h "

// Defines the port and port pins where the resistive touch screen is connected
#define ADC_PORT PORTF
#define TOUCH_Y1 2
#define TOUCH_Y2 0
#define TOUCH_X2 1
#define TOUCH_X1 3


typedef struct
{
unsigned char sleep; // sleep = 1 turns on ADC before and off ADC after read the touch position
unsigned int offset_x; // ADC results for minimum position in x direction
unsigned int offset_y; // ADC results for minimum position in y direction
unsigned int scale_x; // scale factor for calculating x direction
unsigned int scale_y; // scale factor for calculating y direction
} ctouch_t;

extern ctouch_t touch; // configuration data se typedef

typedef struct
{
unsigned char x1, x2, y1, y2;
} button_t;

// a button with its coordinates start to stop is added to the array
// start +------------------------------------+
// | |
// +------------------------------------+stop
// buttons coordinates must be given in Xpixel and Ypixel
// return is button number if possible to add
// return is -1 if no more button can be added
extern signed char add_area(point_t start, point_t stop);
extern void clear_areas(void);
// searches if a given pixel position in pos is defined in button array as Xpixel/2 and Ypixel/2
// return is number of found button
// return is -1 if no button has been found
extern signed char search_areas(void);

// reads the touch pannels adc inputs in x and y direction
// if touchscreen is configered it calculates it screen position in touch_pos structure
extern signed char read_touch(void);

// initializes adc and sets parameter for turning on and off acd every adc read
// adc_off = 1 turns on ADC before and off ADC after read the touch position
extern int8_t touch_init(unsigned char adc_off);
// call function before calibrate touch screen
extern void clear_settings(void);

extern point_t touch_pos; // the result of the x and y position of called function read_touch
extern int8_t capture_area(void);

// function to capture a touch press for calibration
extern void capture_point(uint8_t step);

// calculation of Offset and Scale for calculation of givel ADC value to get the display position in pixel
// pixel_min pointer to structure which hold the ADC values for pressed display position which is in adc_min
// pixel_max pointer to structure which hold the ADC values for pressed display position which is in adc_max
// adc_max pointer to structure wich holds
// adc_min
extern void calc_config( point_t pixel_min, point_t pixel_max);

extern void save_touch_settings(void);


touch.zip > HowTo Touch screen.doc

How to read a touch position from a 4 wire touchscreen

How does a touch screen works:

You can see below the resistor network a touchscreen consist of.

This screen shot is from the ADS7843 touch controller and shows how it
looks like.

when we only look at the y direction of screen we have the following:

You can see some MOSFET. One is switching to 5 volts and the other makes
the ground line.

So on the half of the touch - resistor in x direction we can measure
the voltage produced by the two resistors of touch screen in y
direction.

Its voltage corresponds to the y touch position, and will go from a
little above 0V upt to a little below 5 Volt.

Looks easy, isn't it..

But the touchpannel has got also a relative big capacity in parallel to
the resistors.

That will cause voltage swing on X+ when we put 5 Volts on Y+!

To avoid long times for wainting the voltage goes to its normal value
(resitor divider), we also put a FET on the X+ wire to short the wire
for a certain time.

After this very short time we remove the FET (switch it off) and
measure the voltage with the ADC Pin of the ATMEGA controller.

Here is a scope print of the X+ wire when a touch press is made.

As you can see there is also a delay in time when the FET,which shorts
the X+ pin to ground, is opened. In my application there is a maximum
delay time of 20us to measure.

How to we get touch positions from the ATMEGA processor:

Maybe it sounds difficult, but is realy easy.

First we connect the the 4 pins from the ADC to the touch panel.

See this picture:

There is no need to put additional capacitors on the ADC inputs!

Only be shure that the wires are as short as possible and away from
switching sources, to avoid noise.

Here are code samples from my touch.c , touch.h files:

Touch.h :

// Defines the port and port pins where the resistive touch screen is
connected

#define ADC_PORT PORTF

#define TOUCH_Y1 2

#define TOUCH_Y2 0

#define TOUCH_X2 1

#define TOUCH_X1 3

typedef struct

{

unsigned char sleep; // sleep = 1 turns on ADC before and off ADC
after read the touch position

unsigned int offset_x; // ADC results for minimum position in x
direction

unsigned int offset_y; // ADC results for minimum position in y
direction

unsigned int scale_x; // scale factor for calculating x direction

unsigned int scale_y; // scale factor for calculating y direction

} ctouch_t;

extern ctouch_t touch; // configuration data se typedef

typedef struct

{

unsigned char x1, x2, y1, y2;

} button_t;

touch.c:

#define MAXBUTTON 32

#define TS_VERSION 110 // version of Settings Data

point_t touch_pos; // the result of the x and y position of called
function read_touch

point_t adc_min;

ctouch_t touch; // configuration data se typedef

ctouch_t dummy;

uint8_t ee_version __attribute__ ((section ( " .eeprom " )));

ctouch_t ee_touch __attribute__ ((section ( " .eeprom " ))); //
settingsdata from eeprom

button_t buttons[MAXBUTTON]; // Array of buttoncoordinates

uint8_t max_button; // number of declared buttons

int8_t read_touch_settings(void);

// initializes adc and sets parameter for turning on and off acd every
adc read

// adc_off = 1 turns on ADC before and off ADC after read the touch
position

int8_t touch_init(uint8_t adc_off)

{

touch.sleep = adc_off;

/* touch.scale_x = 387;

touch.scale_y = 407;

touch.offset_x = 139;

touch.offset_y = 405; */

a2dInit();

if (touch.sleep) a2dOff();

*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) |
(1 & lt; & lt; TOUCH_Y2); // define all for outputs

return(read_touch_settings());

}

// reads the touch pannels adc inputs in x and y direction

// if touchscreen is configered it calculates it screen position in
touch_pos structure

int8_t read_touch(void)

{

if (touch.sleep) a2dOn();

int8_t result=0;

ADC_PORT |= (1 & lt; & lt; TOUCH_X1); // put 5 volt an TOUCH_X1 and 0V on
TOUCH_X2

_delay_us(100); // delay cause touchpad is like a capacitor

#ifdef AD_ON

*( & ADC_PORT -1) & = ~((1 & lt; & lt; TOUCH_Y1) | (1 & lt; & lt; TOUCH_Y2)); // inputs for
measuring wires

_delay_us(40); // time delay for signal to settle

touch_pos.x = a2dConvert10bit(TOUCH_Y2); // read voltage of X
direction

#else

touch_pos.x = 512;

#endif

ADC_PORT & = ~(1 & lt; & lt; TOUCH_X1); // deactivate pullup

*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) |
(1 & lt; & lt; TOUCH_Y2); // define all for outputs

if (touch_pos.x & gt; touch.offset_x)

{

ADC_PORT |= (1 & lt; & lt; TOUCH_Y1); // put 5 volt an TOUCH_Y1 and 0V on
TOUCH_Y2

_delay_us(100); // delay cause touchpad is like a capacitor

*( & ADC_PORT -1) & = ~((1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2)); // put them as
input port pins again

#ifdef AD_ON

_delay_us(40); // time delay for signal to settle

touch_pos.y = a2dConvert10bit(TOUCH_X2); // read voltage of Y
direction

#else

touch_pos.y=512;

#endif

ADC_PORT & = ~(1 & lt; & lt; TOUCH_Y1); // deactivate pullup

*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) |
(1 & lt; & lt; TOUCH_Y2); // define all for outputs

if (touch_pos.y & gt; touch.offset_y)

{

result =1;

// a touch has been recognized - & gt; calculate the display position if
possible

if ((touch.scale_x != 0) & & (touch.scale_y != 0))

{

if (touch_pos.x & gt; touch.offset_x) touch_pos.x -= touch.offset_x; //
remove adc offset for position 0

else touch_pos.x =0;

if (touch_pos.y & gt; touch.offset_y) touch_pos.y -= touch.offset_y;

else touch_pos.y=0;

touch_pos.x = (unsigned long) touch_pos.x * touch.scale_x /1000;

touch_pos.y = (unsigned long) touch_pos.y * touch.scale_y /1000;

} else result = -1; // calculation not possible

}

}

if (touch.sleep) a2dOff();

return(result);

}

complete source files of touch.c are added to my project files listed
below this document.

This source code is coupled with display messages for calibrating the
touch parameters:

void calibrate_touchscreen(void)

{

static const char txt_touch1[] PROGMEM = { " TOUCH KALIBRIERUNG " };

static const char txt_touch2[] PROGMEM = { " Bitte ber?hre das
Fadenkreuz " };

static const char txt_speichern[] PROGMEM = { " Daten speichern ? " };

static const char txt_ja[] PROGMEM = { " Ja " };

static const char txt_nein[] PROGMEM = { " Nein " };

static const char txt_gespeichert[] PROGMEM = { " gespeichert .... " };



point_t p1, p2;

// draw cross at position 1

p1.x = 20;

p1.y = 20;

lcd_print_cross(p1, 10, 10);

glcd_select_font(F_LARGE);

glcd_textP(txt_touch1,0,LEFT_VIEW,50,100,0);

glcd_textP(txt_touch2,0,LEFT_VIEW,60,0,0);



clear_settings(); // enable capturing adc values

capture_point(1); // capture first point

lcd_clrscrn(1);

delay_ms(300);

glcd_textP(txt_touch1,0,LEFT_VIEW,50,100,0);

glcd_textP(txt_touch2,0,LEFT_VIEW,0,217,0);

// draw cross at position 2

p2.x = PIXELX - 20;

p2.y = PIXELY - 20;

lcd_print_cross(p2, 10, 10);

capture_point(2); // capture second point

lcd_clrscrn(1);

calc_config(p1, p2);

glcd_textP(txt_speichern,0,LEFT_VIEW,80,100,0);

clear_areas();

add_button(100,130 ,txt_ja);

add_button(170,130, txt_nein);

delay_ms(1000);

int8_t res=capture_area() ;

clear_buttons();

if (res== 1)

{



glcd_textP(txt_gespeichert,0,LEFT_VIEW,80,120,0);

save_touch_settings();

delay_ms(500);

lcd_clrscrn(TXT_LAYER);

}

lcd_clrscrn(0);

}

Here are some pictures which shows screen image from calibrating the
touch screen

Beginning with the touch screen calibration :

First display text and cross of position to touch

After position has been touched and saved

NEXT

Display second point

And wait for touching it

Asking for saving scale and offset parameter

to eeprom.

As you can see some dots on the left side, which came when writing the
text with a pen on the touch screen. To avoid this dots to be printed
the measured voltages must be filtered which cost lots of useconds.


touch.zip > touch.c

//************************************************************************
// For 4 wire resistive touch screens
// Functions for reading position of touchscreen press
// uses ADC of Mega Prozessor for calculating the position
// Klaus Meinhardt created 12.01.2008
//************************************************************************
// Declaration of 32 buttons with start point end end point
// Resolution of point is 2 pixel (for screen with maximal 512x512 pixel)
//************************************************************************


#include & lt; util\delay.h & gt;
#include & lt; inttypes.h & gt;
#include & lt; avr/eeprom.h & gt;
#include " a2d.h "
#include " global.h "
#include " touch.h "
#include " s1D13700.h "

#define TOUCH_MIN 10 // Minimum adc reasult for touch press is recognized
#define MAXBUTTON 32
#define TS_VERSION 110 // version of Settings Data

point_t touch_pos; // the result of the x and y position of called function read_touch
point_t adc_min;
ctouch_t touch; // configuration data se typedef
ctouch_t dummy;

uint8_t ee_version __attribute__ ((section ( " .eeprom " )));
ctouch_t ee_touch __attribute__ ((section ( " .eeprom " ))); // settingsdata from eeprom

button_t buttons[MAXBUTTON]; // Array of buttoncoordinates
uint8_t max_button; // number of declared buttons

int8_t read_touch_settings(void);

// initializes adc and sets parameter for turning on and off acd every adc read
// adc_off = 1 turns on ADC before and off ADC after read the touch position
int8_t touch_init(uint8_t adc_off)
{
touch.sleep = adc_off;
/* touch.scale_x = 387;
touch.scale_y = 407;
touch.offset_x = 139;
touch.offset_y = 405; */
a2dInit();
if (touch.sleep) a2dOff();
*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) | (1 & lt; & lt; TOUCH_Y2); // define all for outputs

return(read_touch_settings());
}

// reads the touch pannels adc inputs in x and y direction
// if touchscreen is configered it calculates it screen position in touch_pos structure
int8_t read_touch(void)
{
if (touch.sleep) a2dOn();
int8_t result=0;
ADC_PORT |= (1 & lt; & lt; TOUCH_X1); // put 5 volt an TOUCH_X1 and 0V on TOUCH_X2
_delay_us(100); // delay cause touchpad is like a capacitor
#ifdef AD_ON
*( & ADC_PORT -1) & = ~((1 & lt; & lt; TOUCH_Y1) | (1 & lt; & lt; TOUCH_Y2)); // inputs for measuring wires
_delay_us(40); // time delay for signal to settle
touch_pos.x = a2dConvert10bit(TOUCH_Y2); // read voltage of X direction
#else
touch_pos.x = 512;
#endif
ADC_PORT & = ~(1 & lt; & lt; TOUCH_X1); // deactivate pullup
*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) | (1 & lt; & lt; TOUCH_Y2); // define all for outputs
if (touch_pos.x & gt; touch.offset_x)
{
ADC_PORT |= (1 & lt; & lt; TOUCH_Y1); // put 5 volt an TOUCH_Y1 and 0V on TOUCH_Y2
_delay_us(100); // delay cause touchpad is like a capacitor
*( & ADC_PORT -1) & = ~((1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2)); // put them as input port pins again
#ifdef AD_ON
_delay_us(40); // time delay for signal to settle
touch_pos.y = a2dConvert10bit(TOUCH_X2); // read voltage of Y direction
#else
touch_pos.y=512;
#endif
ADC_PORT & = ~(1 & lt; & lt; TOUCH_Y1); // deactivate pullup
*( & ADC_PORT -1) |= (1 & lt; & lt; TOUCH_X1) | (1 & lt; & lt; TOUCH_X2) | (1 & lt; & lt; TOUCH_Y1) | (1 & lt; & lt; TOUCH_Y2); // define all for outputs
if (touch_pos.y & gt; touch.offset_y)
{
result =1;
// a touch has been recognized - & gt; calculate the display position if possible
if ((touch.scale_x != 0) & & (touch.scale_y != 0))
{
if (touch_pos.x & gt; touch.offset_x) touch_pos.x -= touch.offset_x; // remove adc offset for position 0
else touch_pos.x =0;
if (touch_pos.y & gt; touch.offset_y) touch_pos.y -= touch.offset_y;
else touch_pos.y=0;
touch_pos.x = (unsigned long) touch_pos.x * touch.scale_x /1000;
touch_pos.y = (unsigned long) touch_pos.y * touch.scale_y /1000;
} else result = -1; // calculation not possible
}
}
if (touch.sleep) a2dOff();
return(result);
}

// call function before calibrate touch screen
void clear_settings(void)
{
touch.scale_x= touch.scale_y=0;
touch.offset_x=touch.offset_y=0;
}


// function to capture a touch press for calibration
void capture_point(uint8_t step)
{
signed char res;
do
{
res=read_touch();
if (res==-1)
{
for (uint8_t cnt=0;cnt & lt; 50;cnt++) _delay_ms(10); // wait 500ms to stable the signal for accuracy
res=read_touch();
if (step==1)
{
adc_min.x= touch_pos.x;
adc_min.y= touch_pos.y;
}
}
} while (res !=-1);
}


// calculation of Offset and Scale for calculation of givel ADC value to get the display position in pixel
// pixel_min pointer to structure which hold the ADC values for pressed display position which is in adc_min
// pixel_max pointer to structure which hold the ADC values for pressed display position which is in adc_max
// adc_max pointer to structure wich holds
// adc_min
void calc_config( point_t pixel_min, point_t pixel_max)
{
touch.scale_x = (unsigned long) (pixel_max.x - pixel_min.x) *1000/ (touch_pos.x - adc_min.x);
touch.scale_y = (unsigned long) (pixel_max.y - pixel_min.y) *1000/ (touch_pos.y - adc_min.y);

touch.offset_x = adc_min.x - ((unsigned long) pixel_min.x *1000 / touch.scale_x ) ;
// touch.offset_x += ((unsigned long) adc_max- & gt; x* touch.scale_x / 1000)- pixel_max- & gt; x;
// touch.offset_x /= 2;

touch.offset_y = adc_min.y - ((unsigned long) pixel_min.y * 1000/ touch.scale_y );
// touch.offset_y += ((unsigned long) adc_max- & gt; y* touch.scale_y / 1000) - pixel_max- & gt; y;
// touch.offset_y /= 2;

}


void save_touch_settings(void)
{
eeprom_busy_wait();
eeprom_write_byte( & ee_version,TS_VERSION);
eeprom_write_block( & touch, & ee_touch, sizeof(ctouch_t));

}

int8_t read_touch_settings(void)
{
uint8_t version;
if (eeprom_read_byte( & ee_version) == TS_VERSION)
{
eeprom_read_block( & touch, & ee_touch, sizeof(ctouch_t));
return(1);
} else return(-1);
}

// searches if a given pixel position in pos is defined in button array as Xpixel/2 and Ypixel/2
// return is number of found button
// return is -1 if no button has been found
int8_t search_areas(void)
{
uint8_t posx = touch_pos.x/2;
uint8_t posy = touch_pos.y/2;

uint8_t btn=0;
do
{
if ((posx & gt; = buttons[btn].x1) & & (posx & lt; = buttons[btn].x2) & & (posy & gt; = buttons[btn].y1) & & (posy & lt; = buttons[btn].y2)) return(btn+1);
btn++;
} while (btn & lt; max_button);
return(-1);
}


// a button with its coordinates start to stop is added to the array
// start +------------------------------------+
// | |
// +------------------------------------+stop
// buttons coordinates must be given in Xpixel and Ypixel
// return is button number if possible to add
// return is -1 if no more button can be added
int8_t add_area(point_t start, point_t stop)
{
if (max_button & lt; MAXBUTTON)
{
buttons[max_button].x1 = start.x/2;
buttons[max_button].x2 = stop.x/2;
buttons[max_button].y1 = start.y/2;
buttons[max_button].y2 = stop.y/2;
return(max_button++);
} else return(-1);
}

void clear_areas(void)
{
max_button=0;
}

int8_t capture_area(void)
{
int8_t res;
do
{
res = read_touch();
if (res==1)
{
res = search_areas();
if (res & gt; 0) break;
}
} while (res & lt; = 0);
return(res);
}