0

I successfully used a HAL library to drive a TFT ili9341 LCD with xpt2046 touch driver and tried drawing a line on the LCD by touching the LCD and the code was perfectly accurate then I rewrote the code with registers. the touch is not accurate now and when I touch the LCD the line shows up at a point far from the place which is touched I attached the code. what might be the problem? the pins are defined with maximum frequency.

    #include "ILI9341_Touchscreen.h"
#include "stm32f10x.h"
#include "main.h"
 
//Internal Touchpad command, do not call directly
uint16_t TP_Read(void)
{
    uint8_t i = 16;
    uint16_t value = 0;
 
    while(i > 0x00)
    {
        value <<= 1;
 
                
               TP_CLK_PORT->BSRR=TP_CLK_PIN;
               TP_CLK_PORT->BRR=TP_CLK_PIN;
            
        
                    if ((TP_MISO_PORT->IDR&TP_MISO_PIN)!=0)
        {
            value++;
        }
 
        i--;
    };
 
    return value;
}
 
//Internal Touchpad command, do not call directly
void TP_Write(uint8_t value)
{
    uint8_t i = 0x08;
 
        TP_CLK_PORT->BRR=TP_CLK_PIN;
    
    while(i > 0)
    {
        if((value & 0x80) != 0x00)
        {
                        
                    TP_MOSI_PORT->BSRR=TP_MOSI_PIN;
        }
        else
        {
                        TP_MOSI_PORT->BRR=TP_MOSI_PIN;
        }
 
        value <<= 1;
                TP_CLK_PORT->BSRR=TP_CLK_PIN;
                TP_CLK_PORT->BRR=TP_CLK_PIN;        
        i--;
    };
}
 
 
 
//Read coordinates of touchscreen press. Position[0] = X, Position[1] = Y
uint8_t TP_Read_Coordinates(uint16_t Coordinates[2])
{
        TP_CLK_PORT->BSRR=TP_CLK_PIN;       
        TP_MOSI_PORT->BSRR=TP_MOSI_PIN;         
      TP_CS_PORT->BSRR=TP_CS_PIN;
 
    
    
    uint32_t avg_x, avg_y = 0;      
        uint16_t rawx, rawy = 0;    
        uint32_t calculating_x, calculating_y = 0;
    
    uint32_t samples = NO_OF_POSITION_SAMPLES;
    uint32_t counted_samples = 0;
 
        
    TP_CS_PORT->BRR=TP_CS_PIN;
 
    
    while((samples > 0)&&((TP_IRQ_PORT->IDR)& TP_IRQ_PIN) == 0)
    {           
        TP_Write(CMD_RDY);
 
                rawy = TP_Read();   
                avg_y += rawy;
                calculating_y += rawy;
 
                
        TP_Write(CMD_RDX);
        rawx = TP_Read();
                avg_x += rawx;
                calculating_x += rawx;
        samples--;
                counted_samples++;
    };
        
        TP_CS_PORT->BSRR=TP_CS_PIN;
 
        
        if((counted_samples == NO_OF_POSITION_SAMPLES)&&((TP_IRQ_PORT->IDR)&TP_IRQ_PIN) == 0)
        {
        
        calculating_x /= counted_samples;
        calculating_y /= counted_samples;
        
        rawx = calculating_x;
        rawy = calculating_y;       
        
        rawx *= -1;
        rawy *= -1;
        
        //CONVERTING 16bit Value to Screen coordinates
    // 65535/273 = 240!
        // 65535/204 = 320!
    Coordinates[0] = ((240 - (rawx/X_TRANSLATION)) - X_OFFSET)*X_MAGNITUDE;
        Coordinates[1] = ((rawy/Y_TRANSLATION)- Y_OFFSET)*Y_MAGNITUDE;
        
        return TOUCHPAD_DATA_OK;            
        }
        else
        {
            Coordinates[0] = 0;
            Coordinates[1] = 0;
            return TOUCHPAD_DATA_NOISY;
        }
}
 
//Check if Touchpad was pressed. Returns TOUCHPAD_PRESSED (1) or TOUCHPAD_NOT_PRESSED (0)
uint8_t TP_Touchpad_Pressed(void)
{
    if((TP_IRQ_PORT->IDR&TP_IRQ_PIN) == 0)
    {
        return TOUCHPAD_PRESSED;
    }
    else
    {
        return TOUCHPAD_NOT_PRESSED;
    }
}
 

it is only part of the code that is related to touch I didn't bring the part about SPI because that part works fine. I used SPI to communicate with the ili9341 and I am able to draw pixels with the desired color. but for the touch IC, I am using GPIO like this example https://github.com/martnak/STM32-ILI9341

I used macros to rename the pins and the GPIO configuration is in another library which is called by a function in the main

    #include "stm32f10x.h"
 
void GPIO_init(void){
    
RCC->APB2ENR |=(1<<4);
RCC->APB2ENR |=(1<<2);  
GPIOC->CRL &=~0xF00FFFFF; //// Clearing C0 to C4
GPIOC->CRL |= 0x30033834;  //// configuring C0 input floating , C1 , C3, C4 output pushpull C2 input with pull up/pull down 
GPIOC->ODR |=(1<<2); ///    making C2 pull up
GPIOC->CRH &=~0xF0000F; /// clearing C13 and C8
GPIOC->CRH |= 0x300003; // C13 and C8 output push pull
 
}
    #ifndef __MAIN_H
#define __MAIN_H
 
#ifdef __cplusplus
extern "C" {
#endif
 



#include "stm32f10x.h"
 
 
 
void Error_Handler(void);
 
 
 
/* Private defines -----------------------------------------------------------*/
#define DC_Pin (1<<13)
#define DC_GPIO_Port GPIOC
#define T_IRQ_Pin (1<<0)
#define T_IRQ_GPIO_Port GPIOC
#define T_CLK_Pin (1<<1)
#define T_CLK_GPIO_Port GPIOC
#define T_MISO_Pin (1<<2)
#define T_MISO_GPIO_Port GPIOC
#define T_MOSI_Pin (1<<3)
#define T_MOSI_GPIO_Port GPIOC
#define T_CS_Pin (1<<4)
#define T_CS_GPIO_Port GPIOC
#define CS_Pin (1<<7)
#define CS_GPIO_Port GPIOC
#define RST_Pin (1<<8)
#define RST_GPIO_Port GPIOC
 
 
#ifdef __cplusplus
}
#endif
 
#endif 
 
 

    enter code here
salar1991
  • 99
  • 8
  • here is the general idea we take 1000 samples and average them and since the maximum value is 65535 we convert the values of x and y to 240 and 320 which is the screen height and width I don't think it's corrupting the data because the HAL code is working – salar1991 Mar 01 '21 at 16:36
  • CMD_RDY=0X90 CMD_RDX=0XD0 X_OFFSET=13 Y_OFFSET=15 X_MAGNITUDE=1.16 Y_MAGNITUDE=1.16 X_TRANSLATION=273 Y_TRANSLATION=204 – salar1991 Mar 01 '21 at 20:46
  • 1
    You might need a delay between `TP_CLK_PORT->BSRR=TP_CLK_PIN; TP_CLK_PORT->BRR=TP_CLK_PIN;` where you toggle the clock pin to avoid violating the 200ns tCH spec. When you're writing, the `value <<= 1;` line might just give you enough of a delay to avoid violating the 100ns tDS. When reading you're almost certainly violating tDO with no delay between the clock toggle and reading the pin with `if ((TP_MISO_PORT->IDR&TP_MISO_PIN)!=0)`. – brhans Mar 01 '21 at 22:01

1 Answers1

0

I defined a dummy variable a and wrote a++ between

TP_CLK_PORT->BRR=TP_CLK_PIN; and if ((TP_MISO_PORT->IDR&TP_MISO_PIN)!=0)

It works fine now! Thank you!

winny
  • 13,064
  • 6
  • 46
  • 63
salar1991
  • 99
  • 8