|
|
View previous topic :: View next topic |
Author |
Message |
Bcox
Joined: 09 Oct 2007 Posts: 17 Location: Windsor, CT
|
Looking for touch screen controller |
Posted: Thu Jan 10, 2008 2:57 pm |
|
|
Hello all,
I have found discussions about this but no luck with code. I am implementing a 128x64 KS0108 glcd with a 4-wire resistive touch screen. I would like to control this directly from the PIC without using an external touchscreen controller. Has anyone successfully implemented this before? Any tips or code to share before I begin working on this project? I will be using the 18F4520 chip. Thanks for your help! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
bwhiten
Joined: 26 Nov 2003 Posts: 151 Location: Grayson, GA
|
App Notes |
Posted: Thu Jan 10, 2008 7:15 pm |
|
|
The mTouch is the method I'm using instead of a true Touch Screen LCD. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Fri Jan 11, 2008 9:15 am |
|
|
I've done this. It's a bit tricky, but certainly possible. It involves a lot of changing bits from high to low and in and out of high-z mode. I also used the weak pullups on port b to determine whether anything was pushed, or not. The processor was a PIC16F877A. As you can see, the setting of the various bits is done via a case/switch construction, which was the only way I could keep the various states logically in my head!
The touch screen was wired with the vertical "potentiometer" between porta.3 and portb.4, and the horizontal "potentiometer" between porta.1 and portb.3. The sequence is to set each "pot" in turn with one end pulled high and one low. Meanwhile for the other "pot" you set both ends high-z and read the A/D converter (which has to get its input from one of those pins, obviously). I do some mathematical processing of the data, which you can ignore, though you'll probably have to do some similar stuff. It involves offsetting and scaling the data, and it's not as elegant as it could be, but I quit tinkering with it as soon as it was working right.
The routine needs to be called frequently enough that you get smooth motion of the cursor, but it needs to allow time between calls for the A/D to do a conversion. I just relied on timing and never checked the A/D done bit. The variable "ad_state" needs to be static or global, unless this is part of main().
Edited to say that in my application, what was wanted was a way to determine the location of a "tap" on the screen. A reading is made when the variable "dct", which is incremented once per pass, reaches 132, and then not again until there's been an interval of no contact. You'd need to make some changes if the objective is to track motion.
Code: |
static int ad_state, dct, hold_y;
if (++ad_state >= 8)
ad_state = 0;
switch(ad_state)
{
case 0:
adcon0 = 0x81 + (1 << 3); // Set up ch 1
bit_clear(trisa, 3); // Make pin 5 an output (low)
bit_clear(trisb, 4); // Make pin 37 an output
bit_set(portb, 4); // Pin 37 is high
bit_set(trisa, 1); // Make pin 3 an input (AD ch 1)
bit_set(trisb, 3); // Make pin 36 high-Z
break;
case 1:
bit_set(adcon0, 2); // Start A/D for ch 1
break;
case 2:
hold_y = adresh; // A/D for ch 1 (vertical)
if (hold_y < 0x10)
hold_y = 0;
else
hold_y -= 0x10;
if (hold_y > 239)
hold_y = 239;
adcon0 = 0x81 + (3 << 3); // Read ch 3 for first time
bit_clear(trisa, 1); // Make pin 3 an output (low)
bit_clear(trisb, 3); // Make pin 36 an output
bit_clear(portb, 3); // Pin 36 is low
bit_set(trisb, 4); // Pin 37 is high-Z
bit_clear(rbpu); // Port B pullups on, this pulls up 37 and thus 5 also
bit_set(trisa, 3); // Make pin 5 an input (AD ch 3)
break;
case 3:
bit_set(adcon0, 2); // Start A/D for ch 3
break;
case 4:
if (adresh > 0x80) // Ch 3 reading
{ // No contact, force repeat of states 3 and 4
ad_state = 2; // Next state is 3
dct = 0;
break;
}
bit_set(portb, 3); // Pin 36 is high
bit_set(rbpu); // Port B pullups off
break;
case 5:
bit_set(adcon0, 2); // Start A/D for ch 3
break;
case 6:
if (adresh < 0x10)
i = 0;
else
i = adresh - 0x10;
if (i >= 0xD0)
i = 0xCF;
if (dct == 0)
{
ypos = hold_y;
xpos = i;
}
else
{
ypos += hold_y;
if (dct < 92)
xpos += i;
}
if (dct == 132) // Mathematically xpos = (x * 92) / 128
{ // Ypos = (y * 132) / 128
if (bit_test(xpos, 7))
xhi++;
if (bit_test(ypos, 7))
yhi++;
xpos <<= 1; // Divide by 128
xpos >>= 8;
ypos <<= 1;
ypos >>= 8;
xpos <<= 2;
ypos <<= 1;
xpos += 10;
ypos += 10;
}
if (dct < 133)
dct++;
adcon0 = 0x81 + 0; // Set up ch 0
break;
case 7:
bit_set(adcon0, 2); // Start A/D for ch 0, but not used at present
break;
// case 8: // Not using case 8 at present
// ch0 = adresh - 0x37; // Read channel 0 (speed pot)
break;
} |
|
|
|
Bcox
Joined: 09 Oct 2007 Posts: 17 Location: Windsor, CT
|
|
Posted: Fri Jan 11, 2008 10:07 am |
|
|
Thank you for your help and info. It gives me a good starting place. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|