This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS7846 ADC VALUES NOT CORRECT

Other Parts Discussed in Thread: ADS7846, TSC2046E, TSC2046

Hi e2e,

We have a customer starting a new design based on the ADS7846.  They have the following questions:

What is the 12 bit output data format from the AD7846?

 To get the 12 bits the AD7846 must be read twice.

The 2 8-bit bytes contain the 12 bits converted value but I don’t see anything that shows how the 12 bits are arranged.

(In the code attached I’ve taken a guess (divide by 8) but I not sure if I’m right.)

 

The code below is an attempt to implement the flowchart in FIGURE 10 in the Touch Screen Controller Tips pdf.

The PENIRQ interrupt is working fine every time the screen is touched the code goes to the interrupt function.

However the X and Y values I’m getting do not seem correct.

 

What values should I expect for X and Y  when the touchscreen is touched in the following positions?

UPPER LEFT        (0.0)

UPPER RIGHT     (3FF,0)

LOWER LEFT       (0,3FF)

LOWER RIGHT    (3FF,3FF)

( I think I should be getting values close to those in the parentheses) 

 

Another question, in the flowchart why is 0x00 1st sent to the AD7846 and then the control byte 0xD0 or 0x90?

If you can see anywhere that I’ve gone astray please let me know.

 

Once I start getting valid X and Y values I’ll start on calibration.

 

Code example

2746.ADS7846 Code.txt
typedef  union
{
                unsigned int ival;
                unsigned char  ucval[2];
}              uisval;

uisval     tsx;         //TOUCH SCREEN X
uisval     tsy;         //TOUCH SCREEN Y
uisval     temp1;
uisval     temp2;

//COUNTERS FOR HOW MANY TIMES X AND Y ARE READ
char myvalue = 0x00;
char myvalue1 = 0x00;

//INTERRUPT WHEN PENIRQ GOES LOW
ISR(INT4_vect)  
{
int i;

                EIMSK = 0x00;
                tsx.ival = 0;
                tsy.ival = 0;
                temp1.ival = 0xFFFF;
                temp2.ival = 0;
                myvalue = 0;
                myvalue1 = 0;
                
                PORTB &= 0xFE;                //Enable Touch Interface CS = LOW
                while(temp1.ival != temp2.ival)
                {
                                temp2.ival = temp1.ival;
                    //temp1.ucval[1] = spi_transfer(0xD0);                             // Write Command Measure X-Position 
                                temp1.ucval[1] = spi_transfer(0x00);                      // Read ADC data X-Position (7-bit byte High) data: 0ddddddd           (bit) 
                                temp1.ucval[0] = spi_transfer(0xD0);                     // Read ADC data X-Position (7-bit byte High) data: 0ddddddd           (bit) 
                                myvalue++;                                                                                                                                        
                }
                tsx.ival = temp1.ival;

                temp1.ival = 0xFFFF;
                temp2.ival = 0;

                while(temp1.ival != temp2.ival)
                {
                                temp2.ival = temp1.ival;
                    //temp1.ucval[1] = spi_transfer(0x90);                              // Write Command Measure X-Position 
                                temp1.ucval[1] = spi_transfer(0x00);                      // Read ADC data y-Position (7-bit byte High) data: 0ddddddd           (bit) 
                                temp1.ucval[0] = spi_transfer(0x90);                      // Read ADC data y-Position (7-bit byte High) data: 0ddddddd           (bit) 
                                myvalue1++;                                                                                                                                      
                }
                tsy.ival = temp1.ival;
                PORTB |= 0x01;                                 // Disable Touch Interface CS = HIGH

                tsx.ival = tsx.ival/8;
                tsy.ival = tsy.ival/8;
                EIMSK = 0x10;
}

Thanks for your help.

John Wiemeyer

 

  • Hi John,

    First, if your customer is starting a new design based on ADS7846, I would recommend that your customer use TSC2046E instead of ADS7846. The TSC2046E is the next-generation version of the ADS7846 4-wire touch screen controller, 100% pin-compatible with the existing ADS7846, and drops into the same socket.

    Second,  if you look a look at the Figure 9 in its datasheet, you can find the 11th bit is the MSB and the 1st bit is the LSB. 

    To help your customer understand how to read the 12-bit X&Y coordinates from ADS7846 / TSC2046E, here is some example code, which is based on the timing in Figure 9: 

    void tsc2046_get_position(unsigned int* px_pos, unsigned int* py_pos)
    {
          // Get X position
          *px_pos = SendCommand(CMD_X_POSITION);

         // Get Y position
         *py_pos = SendCommand(CMD_Y_POSITION);

        // Switch to full power mode
        SendCommand(CMD_ENABLE_PENIRQ);
    }

    #define ADS_CTRL_PD0                              (1 << 0)    // PD0
    #define ADS_CTRL_PD1                              (1 << 1)    // PD1
    #define ADS_CTRL_DFR                              (1 << 2)   // SER/DFR
    #define ADS_CTRL_EIGHT_BITS_MOD      (1 << 3)    // Mode
    #define ADS_CTRL_START                         (1 << 7)    // Start Bit
    #define ADS_CTRL_SWITCH_SHIFT          4               // Address setting

    // Get X position command
    #define CMD_Y_POSITION        ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1)

    // Get Y position command
    #define CMD_X_POSITION        ((5 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1)

    // Enable penIRQ
    #define CMD_ENABLE_PENIRQ         ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START)

    static unsigned int SendCommand(unsigned char bCmd)
    {
    int i;
    AT91S_SPI *spi = BOARD_TSC_SPI_BASE;
    unsigned int uResult = 0;
    //unsigned int uTimeout = 0;
    // (volatile declaration needed for code optimisation by compiler)
    volatile unsigned char bufferRX[3];
    volatile unsigned char bufferTX[3];

    bufferRX[0] = 0;
    bufferRX[1] = 0;
    bufferRX[2] = 0;

    bufferTX[0] = bCmd;
    bufferTX[1] = 0;
    bufferTX[2] = 0;

    PIO_Clear(pinNss);
    // Send command
    i = 0;
    while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    spi->SPI_TDR = bufferTX[i] | SPI_PCS(BOARD_TSC_NPCS);
    while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);

    // wait until the BUSY pin becomes low
    while (PIO_Get(pinBusy) == 1);

    while ((spi->SPI_SR & AT91C_SPI_RDRF) == 0);
    bufferRX[i] = spi->SPI_RDR & 0xFFFF;

    // Read data
    for (i = 1; i < 3; i++)
    {
    while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    spi->SPI_TDR = bufferTX[i] | SPI_PCS(BOARD_TSC_NPCS);
    while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);

    while ((spi->SPI_SR & AT91C_SPI_RDRF) == 0);
    bufferRX[i] = spi->SPI_RDR & 0xFFFF;
    }
    PIO_Set(pinNss);

    uResult = ((unsigned int)bufferRX[1] << 8) | (unsigned int)bufferRX[2];
    uResult = uResult >> 4;

    return uResult;
    }

    Andy