Skip to main content
ilyus
Senior II
April 1, 2022
Solved

STM32F746-Disco I2C Touch Panel ID replying with 0x00 CMSIS-only

STM32F746-Disco

Capacitive Touch Panel FT5336

STM32CubeIDE, Windows 10

CMSIS-only

I'm developing my first I2C driver for STM32F746 using CMSIS-only, and I've decided it would be great to test my I2C skills on built-in capacitive touch panel FT5336. I used ST-provided ft5336.c/.h to get register addresses (since FT5336 datasheet actually doesn't have them). So obviously my first thing to try is to read Chip ID register.

Initially, I've developed DMA driver for it (yeah I can do DMA but still haven't tried I2C), but as I was running into an issue, I made a step back and went full blocking way. Interestingly enough, the results were identical.

What I do:

I write slave address in write mode (ACK), followed by ID register (NACK).

Then I give it a little pause (~30us, well above datasheet ~10us for start setup; tried different).

Then I write slave address in read mode (ACK), and receive 0x00 (NACK).

I've carefully examined my signal with oscilloscope and logic analyzer, made sure timings are correct and all. I can write (master send) as much as I want (including with DMA), but I'm failing at reading, it seems. I'm not sure on what side the error is. Obviously, the panel works if I run TouchGFX project on it. I looked at TouchGFX-generated code in case I see something there, but I didn't find anything that would stand out to me. I don't have any other I2C-device at hand to test it with.

I2C3 setup:

void i2c_setup(I2C_TypeDef *I2C) {
 
	I2C->CR1 &= ~I2C_CR1_PE; //make sure the peripheral is off
 
	/*
	 * Analog filter enables, digital noise filter disabled
	 * Interrupts disabled
	 * */
	I2C->CR1 = 0x00; //reset
	I2C->CR1 |= (0x00 << I2C_CR1_ANFOFF_Pos) | (0x00 << I2C_CR1_DNF_Pos);
 
	/*
	 * Set WRITE mode
	 * 7-bit mode (ADD10=0)
	 * Load 7-bit Slave Address
	 */
	I2C->CR2 = 0x00; //reset
	I2C->CR2 |= (0x00 << I2C_CR2_RD_WRN_Pos) | (FT5336_I2C_SLAVE_ADDRESS << I2C_CR2_SADD_Pos);
 
	/*
	 * TIMING
	 * 100kHz I2C
	 * */
	I2C->TIMINGR = 0x00; //reset
	I2C->TIMINGR |= (0x06 << I2C_TIMINGR_PRESC_Pos) | (0x02 << I2C_TIMINGR_SCLDEL_Pos) | (0x00 << I2C_TIMINGR_SDADEL_Pos) | (0x1E << I2C_TIMINGR_SCLH_Pos)
			| (0x2A << I2C_TIMINGR_SCLL_Pos);
 
	I2C->CR1 |= I2C_CR1_PE; //activate peripheral
 
}
void i2c_sendByte(uint8_t data, I2C_TypeDef *I2C) {
	I2C->CR2 &= ~I2C_CR2_NBYTES; //make sure number of bytes to transmit is cleared
	I2C->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos); //set number of bytes to send to 1
	I2C->CR2 |= I2C_CR2_AUTOEND; //stop bit after sent byte
	I2C->CR2 &= ~I2C_CR2_RD_WRN; //master requests write transfer
	while (!(I2C->ISR & I2C_ISR_TXE)); //wait while transmit data register is empty (just in case, whatever)
	//Slave address set in setup
	I2C->TXDR = data;
	I2C->CR2 |= I2C_CR2_START; //set start bit
}
 
void i2c_receiveByte(uint8_t *data, I2C_TypeDef *I2C) {
	I2C->CR2 &= ~I2C_CR2_NBYTES; //make sure number of bytes to transmit is cleared
	I2C->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos); //set number of bytes to 1
	I2C->CR2 |= I2C_CR2_AUTOEND; //stop bit after sent byte
	I2C->CR2 |= I2C_CR2_RD_WRN; //master requests write transfer
 
	I2C->CR2 |= I2C_CR2_START; //set start bit
	while (!(I2C->ISR & I2C_ISR_RXNE)); //wait while receive data register is not empty
	*data = I2C->RXDR;
}

How I actually run it all in main.c (removed irrelevant UART pieces that work):

i2c_setup(I2C3);
uint8_t i2c3_id_register;
while (1) {
		while (I2C3->ISR & I2C_ISR_BUSY);
		for (uint32_t i = 0; i < 1000; i++); //lame pause
		i2c_sendByte(0xA8, I2C3);
		while (I2C3->ISR & I2C_ISR_BUSY);
		for (uint32_t i = 0; i < 1000; i++); //lame pause
		i2c_receiveByte(&i2c3_id_register, I2C3);
 
	}

The screenshot if from the logic analyzer, so I actually see what's physically happening on the line, processing the data is not an issue here. Scope gave the same picture. I'm not sure about what I'm doing wrong.

0693W00000LwbKmQAJ.png

This topic has been closed for replies.
ilyus
ilyusBest answer
Senior II
April 5, 2022

Unfortunately, there is no document with FT5336 registers and possible I can deduce basic functionality, such as how to read one data point (Read register 0x02 - number of touches), read coordinate registers afterwards, but I have no way of knowing how to configure it - there is no information of what various configuration registers do and mean, what bits change what, at least not for all of them (there are various misc registers). Pretty much going in with intuition. The datasheet of the FT5336 is on the net, but it has actually everything except the register addresses themselves and what individual bits mean.

To my surprise, I found more information about its specifics (but not all yet) on russian forums, which sometimes link to obscure english forums (and sometimes don't). Will keep digging original ST code, unfortunately, it's split between the files.

Still, it's kinda strange that the datasheet of FT5336 simply doesn't have registers.

Due to my phenomenal googling skills, I have just found this document, can't read it all right now, but a few first registers match (and so do their bits). It does actually seem like register map of the FT5336 (maybe! needs verification! Will keep posted!): https://www.lcd-module.com/fileadmin/eng/pdf/zubehoer/FT5x06_5x16_FTS_AN_CTPM_Ver1_1_application_note.pdf

5 replies

KnarfB
Super User
April 2, 2022

How look the first TouchGFX generated I2C commands on the bus? Do you spot a difference?

hth

KnarfB

ilyus
ilyusAuthor
Senior II
April 2, 2022

Yeah I don't know what I didn't come up with this idea, although I posted this shortly before the end of the day. Will definitely do this on Monday. Could be something on hardware setup side (timing, something else). Will scope and edit it in. Thanks for the (obvious, but forgotten by me) idea!

ilyus
ilyusAuthorBest answer
Senior II
April 5, 2022

Unfortunately, there is no document with FT5336 registers and possible I can deduce basic functionality, such as how to read one data point (Read register 0x02 - number of touches), read coordinate registers afterwards, but I have no way of knowing how to configure it - there is no information of what various configuration registers do and mean, what bits change what, at least not for all of them (there are various misc registers). Pretty much going in with intuition. The datasheet of the FT5336 is on the net, but it has actually everything except the register addresses themselves and what individual bits mean.

To my surprise, I found more information about its specifics (but not all yet) on russian forums, which sometimes link to obscure english forums (and sometimes don't). Will keep digging original ST code, unfortunately, it's split between the files.

Still, it's kinda strange that the datasheet of FT5336 simply doesn't have registers.

Due to my phenomenal googling skills, I have just found this document, can't read it all right now, but a few first registers match (and so do their bits). It does actually seem like register map of the FT5336 (maybe! needs verification! Will keep posted!): https://www.lcd-module.com/fileadmin/eng/pdf/zubehoer/FT5x06_5x16_FTS_AN_CTPM_Ver1_1_application_note.pdf

ilyus
ilyusAuthor
Senior II
April 8, 2022

TouchGFX just doesn't do any ID matching in multiple examples I tried, it never addresses ID register. It goes straight to sampling touches, and the file with registers I found seems to work. I will figure the rest out on my own.