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.

Interfacing with Capacitive Touch Screen FT5306

Hello, I'm having trouble getting data from the touch screen FT5306. This chip comes pre-assembled with other components, where the interface pins consists of 6 pins in the following order: VDD, GND, SCL, SDA, INT, and RESET. This post does overlap with my previous post, but the previous post mainly concerned with the I2C connection (which I have got some confirmation that my setup and waveform seems fine; I will have 100% confirmation Monday when I get access to an oscilloscope). The main difference with this post is that I have updated my code to reflect the example codes given in the datasheet, as well as on other sites. Yet, I'm still reading back values of 0. I wanted to make sure if my code is properly setting up I2C and communicating with the touch screen. 

From my research, I've come to the conclusion that to access the registers containing the values in the touch screen, I need to send the byte matching the address of the register from master to slave, then perform a read to retrieve the value of the register that I specified. Consecutive reads after this will retrieve the values of subsequent registers. This behavior can be seen from the sample code in this datasheet on page 15, and in this forum in reply #6.
  

Here is my initialization code for the I2C module on the launchpad:

void initTouchPanel()
{
	//
	// Enable the peripherals to be used.
	//
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);

	//
	// Waits for peripherals to be ready.
	//
	while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0) &&
			!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOL) &&
			!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));

	//
	// Configure PB2 and PB3 for I2C
	//
    MAP_GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    MAP_GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    //
    // Select I2C function for PB2 and PB3
    //
    MAP_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    MAP_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

	//
	// Configure pin PL4 as input. (Remember to change to PL6 later)
	//
	MAP_GPIOPinTypeGPIOInput(GPIO_PORTL_BASE, GPIO_PIN_4);

	//
	// Configure pin PL5 as output. (Remember to change to PL7 later)
	//
	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_5);

	//
	// Drive PL5 HIGH.
	//
	MAP_GPIOPinWrite(GPIO_PORTL_BASE, GPIO_PIN_5, 0x20);
}

This function reads in 30 values from the touch screen (based on the sample code in the datasheet):

void touchPanelReadData(uint32_t g_ui32SysClock)
{
	uint8_t i = 0;

	uint32_t touch_data_buf[30] = {};

	//
	// Command master to perform a single write.
	//
	touchPnlWrite(g_ui32SysClock, 0x00);

	//
	// Perform error check.
	//
	if (MAP_I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
	{
		UARTprintf("Error = %d\n\n", MAP_I2CMasterErr(I2C0_BASE));
		return;
	}

	//
	// Get touch data.
	//
	for (i = 0; i < 30; ++i)
	{
		//
		// Command master to perform a single read.
		//
		touchPnlRead(g_ui32SysClock);

		//
		// Perform error check.
		//
		if (MAP_I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
		{
			UARTprintf("Error = %d\n\n", MAP_I2CMasterErr(I2C0_BASE));
			return;
		}

		touch_data_buf[i] = MAP_I2CMasterDataGet(I2C0_BASE);
	}

	for (i = 0; i < 30; ++i)
	{
		UARTprintf("touch_data_buf[%d] = %d\n", i, touch_data_buf[i]);
	}
	UARTprintf("\n");
}


These two helper functions perform a single send and single receive:

//*****************************************************************************
//
// Receive one byte from touch panel.
//
//*****************************************************************************
void touchPnlRead(uint32_t g_ui32SysClock)
{
	//
	// Configure and enable master.
	//
	MAP_I2CMasterInitExpClk(I2C0_BASE, g_ui32SysClock, false);

	//
	// Set slave address.
	//
	MAP_I2CMasterSlaveAddrSet(I2C0_BASE, 0x71, true);

	//
	// Initiate master single receive.
	//
	MAP_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

	//
	// Wait for master to finish transaction.
	//
	while (MAP_I2CMasterBusy(I2C0_BASE));
}

//*****************************************************************************
//
// Send one byte to touch panel.
//
//*****************************************************************************
void touchPnlWrite(uint32_t g_ui32SysClock, uint8_t ui8Data)
{
	//
	// Configure and enable master.
	//
	MAP_I2CMasterInitExpClk(I2C0_BASE, g_ui32SysClock, false);

	//
	// Set slave address.
	//
	MAP_I2CMasterSlaveAddrSet(I2C0_BASE, 0x70, false);

	//
	// Place data to be send into FIFO.
	//
	MAP_I2CMasterDataPut(I2C0_BASE, ui8Data);

	//
	// Initiate master single send.
	//
	MAP_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);

	//
	// Wait for master to finish transaction.
	//
	while (MAP_I2CMasterBusy(I2C0_BASE));
}
  • Hello Thomas

    Your code is OK. Only one suggestion:

    MAP_I2CMasterInitExpClk(I2C0_BASE, g_ui32SysClock, false);

    can be kept in a common initialization routine and called just once. No need to call it during every read and write.

    Also be aware of the I2C Bust flag issue in TM4C129x devices (refer to I2C errata)

    Regards
    Amit
  • Hi Amit,

    Thanks for your help with this issue and the last btw. I was wondering if you could think of a reason why I'm just reading in values of 0? It seems to me that from my last post, both my setup, waveform (I will get back to you tomorrow on the closer-up pic of the waveform as you requested from my other post), and code are okay, and I've tested the connections between the pins using a multimeter already and they're all fine. I can't think of what else could be the reason why my code isn't working.

    Thomas
  • Hello Thomas,

    I believe there could be only one condition that a value of 0 is consistently being read for every transaction and that is that the I2C transaction is generating a ADDR NAK

    Regards
    Amit
  • Hi Amit,

    After having some help from a professor on how to use the oscilloscope to show the I2C data, I was able to determine that I was sending the wrong slave address for the read. I had originally thought that I needed to manually change the last bit of the slave address to 1 to make the master perform a read, BUT the function I2CMasterSlaveAddrSet() takes in a bool for its last parameter, which after looking inside the actual definition of the function in i2c.c, I saw that that bool parameter is OR into the address itself after doing a left shift, thereby setting the R/W bit based on the bool bReceive parameter. Thus, both of my read and write function should be sending the address 0x38 (which is then shifted left to become 0x70), but just differ in the bool parameter.

    //*****************************************************************************
    //
    // Receive one byte from touch panel.
    //
    //*****************************************************************************
    void touchPnlRead()
    {
    	//
    	// Set slave address.
    	//
    	MAP_I2CMasterSlaveAddrSet(I2C0_BASE, 0x38, true);
    
    	//
    	// Initiate master single receive.
    	//
    	MAP_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    
    	//
    	// Wait for master to finish transaction.
    	//
    	while (MAP_I2CMasterBusy(I2C0_BASE));
    }
    
    //*****************************************************************************
    //
    // Send one byte to touch panel.
    //
    //*****************************************************************************
    void touchPnlWrite(uint8_t ui8Data)
    {
    	//
    	// Set slave address.
    	//
    	MAP_I2CMasterSlaveAddrSet(I2C0_BASE, 0x38, false);
    
    	//
    	// Place data to be send into FIFO.
    	//
    	MAP_I2CMasterDataPut(I2C0_BASE, ui8Data);
    
    	//
    	// Initiate master single send.
    	//
    	MAP_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    
    	//
    	// Wait for master to finish transaction.
    	//
    	while (MAP_I2CMasterBusy(I2C0_BASE));
    }
    


    And here is what the I2CMasterSlaveAddrSet() function is doing:

    void
    I2CMasterSlaveAddrSet(uint32_t ui32Base, uint8_t ui8SlaveAddr,
                          bool bReceive)
    {
        //
        // Check the arguments.
        //
        ASSERT(_I2CBaseValid(ui32Base));
        ASSERT(!(ui8SlaveAddr & 0x80));
    
        //
        // Set the address of the slave with which the master will communicate.
        //
        HWREG(ui32Base + I2C_O_MSA) = (ui8SlaveAddr << 1) | bReceive;
    }

    Thomas