Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADS7843 Touch Screen Controller Assistance

Status
Not open for further replies.

Micro9900

New Member
Hey guys, I could use a bit of help. I'm stuck trying to figure out this controller. I found some sample drivers in the GLCD and touch screen: tutorials, code and infothread. I have tried to break it apart a bit and understand it:

Code:
unsigned short coordXresult;
unsigned short coordYresult;

#define SpiChn	SPI_CHANNEL4

#define Touch_PenIRQ			!PORTDbits.RD11
#define Touch_PenIRQ_TRIS		TRISDbits.TRISD11
#define Touch_PenIRQ_LAT		LATDbits.LATD11

#define	Touch_CS                        LATDbits.LATD8 
#define	Touch_CS_TRIS	       TRISDbits.TRISD8

void Touch_Init(void)		// Initialises the touch screen
{
	Touch_CS = 1;				// Deasserts the CS line.
	//Touch_Busy_TRIS = 1;
	Touch_PenIRQ_TRIS = 1;

        // Initialize SPI hardware module pg. 206/314 of C32 user guide
        // SPI Channel (set to 2), Set uC as Master, clock polarity cotrol, baud rate
        // Try: SPICON_MSTEN|SPICON_CKP|SPICON_MODE8
        // Baud Rate = BR = Fpb/(2*(SPIBRG+1)), Fpb is 1:1 => 80MHz
        // Baud RAte = 80MHz/(2*(2MHz+1))=>20
	//SpiChnOpen(SpiChn, SPI_OPEN_MSTEN|SPI_OPEN_CKP_HIGH|SPI_OPEN_MODE8, 10);	// SpiChn defined in ADS7843.h. Master enabled, framing disabled
        SpiChnOpen(SpiChn, SPICON_MSTEN|SPICON_CKP|SPICON_MODE16|SPICON_ON,20);

	Touch_CS = 0;
        TDelay();
        // See pg. 6 and 9 of 18 in ADS7843 datasheet/ pg.21 of XPT2046
        // S = start bit, A=addressing-input for multiplexer, MODE=selects ADC resolution PD = power down bits for idle
        // Bits 0 -> 7 = S A2 A1 A0 MODE SFR/DFRnot PD1 PD0
	SpiChnPutC(SpiChn, 0b10011100);				// Sends the initialisation byte
	//SpiChnGetC(SpiChn); //<--- ** causes error stall program
	Touch_CS = 1;
}

void ReadTouchXY(void)
{
    unsigned char readX, readY; //rdx2,rdx1
	
		Touch_PenIRQ_TRIS = 0;                          // Sets the PenIRQ to an output
		Touch_PenIRQ_LAT = 0;                           // Drives the PenIRQ low so the diode is not forward biased

		Touch_CS = 0;
                TDelay();                                       // Asserts the CS line and gives a required delay
		SpiChnPutC(SpiChn, 0b11011100);			// Sends the control byte
		SpiChnGetC(SpiChn);                             // Reads the dummy data to clear the receive buffer
		
		SpiChnPutC(SpiChn, 0x00);                       // Sends a dummy byte in order to clock the data out
		readY = SpiChnGetC(SpiChn);                     // Puts the received data into rxd1
		SpiChnPutC(SpiChn, 0b10011100);			// Sends the next control byte to read the other axis
		readX = SpiChnGetC(SpiChn);                     // Reads the lower byte of the first received data

		// The following figure is the result (rxd1 & rxd2) inverted (4096-) - the offset (measured) * the range
		coordYresult = 4096-(readY<<5) + (readX>>3);
		if(coordYresult<Ymin)
                    coordYresult = 0;
		else{
                    coordYresult -= Ymin;
                    coordYresult *= Yrange;}
		if(coordYresult>239)
                    coordYresult = 239;

		SpiChnPutC(SpiChn, 0x00);                       // Sends dummy data
		readY = SpiChnGetC(SpiChn);                     // Places the received data into rxd1
		SpiChnPutC(SpiChn, 0b10011100);			// Sends dummy data
		readX = SpiChnGetC(SpiChn);                     // Places the received data into rxd2

		// The following figure is the result (rxd1 & rxd2) - the offset (measured) * the range
		coordXresult = ((readY<<5) + (readX>>3));
		if(coordXresult<Xmin)
                    coordXresult = 0;
		else {
                    coordXresult -= Xmin;
                    coordXresult *= Xrange;}
		if(coordXresult>319)
                    coordXresult = 319;

		Touch_CS = 1;                                           // Deasserts the chip select line

		Touch_PenIRQ_TRIS = 1;					// Sets the PenIRQ to an input again
	//}
}

I currently have the graphics LCD completely working where I can output lines/colors/images, etc.

The setup I am using is as follows:
____________________________
IDE: MPLAB X using C32
uC: pic32mx795F512H (64pin LQFP) running at 80MHz
Graphics LCD: YX32B 320x240 pixel display module
Touch screen controller:ADS7843

The questions I have are as follows:
____________________________
1. What SPI clock speed should I have? Currently (if you look at the code I posted) I have it configured to 2MHz.

2. I'm looking at the data sheet and the AD2-AD0 lines are bit confusing to me, can anyone clear this up?

3. The display module doesn't have a "busy" pin out? Is it really needed? Currently I am using an external interrupt and using a flag in main to call the function.

4. For calibration I have found this example. Does anyone have any advice as to how to go about calibrating the touch screen?

5. So far, I have the interrupt working where if I press the screen it changes the color. So, this means it should be configured properly. What I am doing now is trying to display the coordinates touched on the graphics LCD. I only get 0 and 249, which makes me believe either the calibration is incorrect for my touch screen or my SPI clock is wrong or something else. Does any one have any foresight as to what may be the problem?

If anyone can answer any of the above questions or clarify the basic communication to the ADS7843 that would really help a lot. As always thank you so much for your time and I appreciate any help/responses. Thank you.

EDIT:
The line with "SPI_OPEN_MODE8" that is commented out does not work I have to use SPICON_MODE16 for some reason. I also changed "unsigned char readX, readY;" to "unsigned short readX, readY;" and I now see the x change, but not the y, it is still stuck at "239."
 
Last edited:
2mhz should be ok..... The first thing you should be doing is displaying the raw data

Readx and Ready.... see what they are first.... the output from the screen may not need to be inverted on the y axis..

What I do is write the value's to the screen ( dead center so I can see ) Then touch everywhere and write down the figures.

Calibration is a bit odd.. I found that the touch panel tilts slightly so linear calibration isn't the best way to go..

I calibrate the dead center then each quarter in turn... This give the best results... ie.. I have 4 calibrations ( 5 point calibration )

If your touch panel doesn't tilt you can get away with 3 points....

One other thing when you press the touch wait 100mS before you read x and y, the ads7843 may do this for you, as the reading settles and changes position.
 
Thanks for the response Ian I really appreciate it. I'll also be sure and wait 100ms before reading the values. I'll try working on it a bit more later today, but your response raised a few questions more questions:

1. From the example I am working off of, I'm a bit confused as to when I actually get the X and the Y data and how it works. I believe it is here:

Code:
                .....
		SpiChnPutC(SpiChn, 0b11011100);			// Sends the control byte
		SpiChnGetC(SpiChn);                             // Reads the dummy data to clear the receive buffer
 
		SpiChnPutC(SpiChn, 0x00);                       // Sends a dummy byte in order to clock the data out
		readY = SpiChnGetC(SpiChn);                     // Puts the received data into rxd1
		SpiChnPutC(SpiChn, 0b10011100);			// Sends the next control byte to read the other axis
		readX = SpiChnGetC(SpiChn);                     // Reads the lower byte of the first received data
               .....

It seems that the AD2-AD0 bytes are changing. In the datasheet these bits are a bit convoluted. According to the above code the first control byte has A2-A0 = 101. Then the next control byte has A2-A0 = 001. I assume that A2-A0 = 101 selects the Y to be read and A2-A0 = 001 selects the X to be read is this correct?

2. When you say "each quarter in turn" do mean also test each corner of the display? Also, once you have these points (center and possibly corners) can you only create an offset by inspection or is there a way to automatically do this procedure based upon a user's touch input? For example upon start up have an initial calibration mode and store the values and calculate the offset and store it for the remainder of its operation.
 
Last edited:
I have never used this touch controller.... I make my own....

From the data sheet A0,1 & 2 are just addresses of the internal registers...

001 = x
101 = y
110 = aux 1
010 = aux 2

You should get a 12 bit response 0 to 4096...

The touch sometimes comes like this
touch.PNG

So I use the middle and then go to all four corners making four different maps.
 
Last edited:
Oh wow, that's cool. Do you use the uC's builtin ADC to do this? Well, I'm stuck with this controller for now, heh. Also, thank you for clearing up the A2-A0, looking back at the data sheet it makes a bit more sense.

Ouch, I can see from the above picture how mechanically the touch screen can sometimes not be properly be placed over the LCD screen, thanks for clearing that up as well. My last question mainly deals with the calibration. Once you get those coordinates what exactly do you do with them? For example, say the center is supposed to be (320/2,240/2) or (160,120) and I read (200,150) which is off by 40 for X and 30 for Y. Do I just add or subtract (in this case) the amount it is off by, and for areas close to the center use that offset (and for the corners use their respective offsets)? Or do I average the offsets of the center and corners and use that as the "overall" offset?
 
Even when it IS placed properly, this can happen..

It can sometimes be a little crooked as well... But to make the most of it I calibrate 4 parts instead of one... This makes it a little more linear..
 
Sorry for the multitude of questions, but once you have the offsets for the middle and corners do you average the collected offsets? In general what is the process used with the five offsets? Thanks again.
 
You need a map function to work out the TRUE pen position

map ( xLeft, yTop, xcentre,ycentre); return point 0,0 to 160,120
map ( xcentre,ycentre, xright, yTop); return point 160,120 to 320,0
map ( xLeft, yBottom, xcentre,ycentre); return point 0,240 to 160,120
map ( xcentre,ycentre, xright, ybottom); return point 160,120 to 320,240

This will give a good linear reading..
 
If I'm not mistaken, how it works is read the X and Y and using if statements check to see if it falls into a certain range and then use one of the map functions that contains an offset for the corresponding range?

For example, if I read in 200,150 for the center when it is supposed to be 160,120. I then check to see which map function I should use and if falls within a certain range I use the center offset that I have stored (subtracts 40 and 30)?
 
Last edited:
Status
Not open for further replies.
Back
Top