zoukankan      html  css  js  c++  java
  • stm32 触摸屏 XPT2046

    引脚功能描述
    1

    控制字的控制位命令
    1

    控制字节各位描述
    1

    单端模式输入配置
    1

    差分模式输入配置
    1

    时序
    前8个时钟用来通过DIN引脚输入控制字节,接着的12个时钟周期将完成真正的模数转换,剩下的3个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)

    1

    举例
    1
    2
    3

    #define TOUCH_READ_TIMES    40 //读取次数
    #define TOUCH_ERR_RANGE 20 //误差范围
    
    #define TOUCH_X_CMD 0xD0 //读取X轴
    #define TOUCH_Y_CMD 0x90 //读取Y轴
    #define TOUCH_Continue_Read 0xFF
    #define TOUCH_X_MAX 4000 //X最大值
    #define TOUCH_X_MIN 100 //X最小值
    #define TOUCH_Y_MAX 4000 //Y最大值
    #define TOUCH_Y_MIN 100 //X最小值
    
    #define LCD_CALx_MIN (10) //校准点最小值X
    #define LCD_CALx_MAX (tftlcd_data.width - LCD_CALx_MIN) //校准点最大值X
    #define LCD_CALy_MIN (10) //校准点最小值Y
    #define LCD_CALy_MAX (tftlcd_data.height - LCD_CALy_MIN) //校准点最大值Y
    
    #define LCD_CAL_X   (LCD_CALx_MAX - LCD_CALx_MIN) //方框的宽度
    #define LCD_CAL_Y   (LCD_CALy_MAX - LCD_CALy_MIN) //方框的高度
    
    #define TOUCH_CAL_OK        'Y' //校准OK标志
    #define TOUCH_CAL_ADDR  200  //校准参数在at24c02的保存地址
    
    typedef struct
    {
        u8 flag; 
        short xoffset;
        short yoffset; 
        float xFactor;
        float yFactor;
    } calibrate_t;
    
    calibrate_t calibrate = {0};
    
    u16 touchX;
    u16 touchY;
    
    void TOUCH_init()
    {
        GPIO_InitTypeDef gpioa = 
        {
            GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7,
            GPIO_Speed_50MHz,
            GPIO_Mode_AF_PP
        };
    
        GPIO_InitTypeDef gpiod6 = 
        {
            GPIO_Pin_6,
            GPIO_Speed_50MHz,
            GPIO_Mode_Out_PP
        };
        GPIO_InitTypeDef gpiod7 = 
        {
            GPIO_Pin_7,
            GPIO_Speed_50MHz,
            GPIO_Mode_IPU
        };
    
        SPI_InitTypeDef spi = 
        {
            SPI_Direction_2Lines_FullDuplex,
            SPI_Mode_Master, //0x0104
            SPI_DataSize_8b,
            SPI_CPOL_High,
            SPI_CPHA_2Edge,
            SPI_NSS_Soft,
            SPI_BaudRatePrescaler_256,
            SPI_FirstBit_MSB,
            7
        };
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
    
        GPIO_Init(GPIOA, &gpioa);
        GPIO_Init(GPIOD, &gpiod6);
        GPIO_Init(GPIOD, &gpiod7);
    
        SPI_Init(SPI1, &spi); //初始化SPI
    
        SPI_Cmd(SPI1, ENABLE); //使能SPI
    }
    
    u16 TOUCH_read(u16 cmd)
    {
        u8 i = 0, j = 0;
        u16 tmp;
        u16 value[TOUCH_READ_TIMES] = {0};
        u32 total_value = 0;
    
        SPI1_SetSpeed(SPI_BaudRatePrescaler_32); //设置SPI速度
    
        for(i = 0; i < TOUCH_READ_TIMES; i++) //读取次数
        {
            TOUCH_CS = 0;
    
            SPI1_read_write(cmd);
    
            value[i] = SPI1_read_write(TOUCH_Continue_Read) << 8; //详见时序
            value[i] |= SPI1_read_write(TOUCH_Continue_Read);
            value[i] >>= 3;
    
            TOUCH_CS = 1;
        }
    
        for (i = 0; i < TOUCH_READ_TIMES; i++) //排序
        {
            for (j = i + 1; j < TOUCH_READ_TIMES; j++)
            {
                if (value[i] < value[j])
                {
                    tmp = value[i];
                    value[i] = value[j];
                    value[j] = tmp;
                }
            }
        }
    
        for (i = 1; i < TOUCH_READ_TIMES - 1; i++) //去掉一个最大值,一个最小值
        {
            total_value += value[i];
        }
    
        total_value /= (TOUCH_READ_TIMES - 2); //求平均值
    
        return total_value;
    }
    
    u8 TOUCH_readXY(u16 *x, u16 *y)
    {
        u16 valueX1, valueY1, valueX2, valueY2;
    
        valueX1 = TOUCH_read(TOUCH_X_CMD); //读取触摸值
        valueY1 = TOUCH_read(TOUCH_Y_CMD);
        valueX2 = TOUCH_read(TOUCH_X_CMD);
        valueY2 = TOUCH_read(TOUCH_Y_CMD);
    
        *x = valueX1 > valueX2 ? (valueX1 - valueX2) : (valueX2 - valueX1); 
        *y = valueY1 > valueY2 ? (valueY1 - valueY2) : (valueY2 - valueY1);
        if((*x > TOUCH_ERR_RANGE) || (*y > TOUCH_ERR_RANGE)) //判断容错范围
        {
            return 0xFF;
        }
    
        *x = (valueX1 + valueX2) / 2;
        *y = (valueY1 + valueY2) / 2;
    
        if((*x < TOUCH_X_MIN || *x > TOUCH_X_MAX) || //判断边界范围
            (*y < TOUCH_Y_MIN || *y > TOUCH_Y_MAX))
        {
            return 0xFF;
        }
    
        return 0;
    }
    
    void TOUCH_start_calibrate(u16 x, u16 y, u16 *valueX,u16 *valueY) //开始校准
    {
        u8 i = 0;
    
        LCD_Clear(BACK_COLOR); //清屏
        LCD_DrowSign(x, y, BACK_COLOR); //画十字
    
        while(1)
        {
            if(TOUCH_readXY(valueX, valueY) != 0xFF)
            {
                i++;
                if(i > 10)
                {
                    LCD_DrowSign(x, y, BACK_COLOR);
                    break;
                }
            }
        }
    }
    
    void TOUCH_calibrate()
    {
        u16 px[2], py[2], valueX[4], valueY[4];
        float xFactor = 0, yFactor = 0;
    
        TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MIN, &valueX[0], &valueY[0]); //第一次校准
        delay_ms(500);
    
        TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MAX, &valueX[1], &valueY[1]);
        delay_ms(500);
    
        TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MIN, &valueX[2], &valueY[2]);
        delay_ms(500);
    
        TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MAX, &valueX[3], &valueY[3]);
        delay_ms(500);
    
        //整合成对角的两点
        px[0] = (valueX[0] + valueX[1]) / 2;
        py[0] = (valueY[0] + valueY[2]) / 2;
        px[1] = (valueX[3] + valueX[2]) / 2;
        py[1] = (valueY[3] + valueY[1]) / 2;
    
        //求出比例因子
        xFactor = (float)LCD_CAL_X / (px[1] - px[0]);
        yFactor = (float)LCD_CAL_Y / (py[1] - py[0]); 
    
        //求出偏移量
        calibrate.xoffset = (short)LCD_CALx_MAX - ((float)px[1] * xFactor);
        calibrate.yoffset = (short)LCD_CALy_MAX - ((float)py[1] * yFactor);
    
        calibrate.xFactor = xFactor ;
        calibrate.yFactor = yFactor ;
    
        printf("xoffset %d
    ", calibrate.xoffset);
        printf("yoffset %d
    ", calibrate.yoffset);
        printf("xFactor %f
    ", calibrate.xFactor);
        printf("yFactor %f
    ", calibrate.yFactor);
    
        //保存校准数据到at24c02
        calibrate.flag = TOUCH_CAL_OK;
        at24c02Write_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));   
    }
    
    u8 TOUCH_scan() //查看是否触摸
    {
        u16 valueX;
        u16 valueY; 
    
        if(TOUCH_readXY(&valueX, &valueY) == 0xFF)
        {
            return 0xFF;
        }
    
        //根据物理坐标,计算彩屏坐标
        touchX = valueX * calibrate.xFactor + calibrate.xoffset;
        touchY = valueY * calibrate.yFactor + calibrate.yoffset;
    
        if((touchX > tftlcd_data.width) || (touchY > tftlcd_data.height))
        {
            return 0xFF;
        }
    
        return 0;
    }
    
    int main(void)
    {
        I2C_init();
        TOUCH_init();
    
        at24c02Read_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));
        if(calibrate.flag != TOUCH_CAL_OK) //判断是否已经校准
        {
            TOUCH_calibrate();
        }
        LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");
    
        while(1)
        {
            if(TOUCH_scan() == 0)
            {
                LCD_Fill(touchX-1, touchY-1, touchX+2, touchY+2, FRONT_COLOR); //画粗线
    
                if((touchX > tftlcd_data.width-40) && (touchY < 20))
                {
                    LCD_Fill(0, 0, tftlcd_data.width,tftlcd_data.height, BACK_COLOR); //清屏
                    LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");
                }
            }
        }
    }
  • 相关阅读:
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 344 反转字符串
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709545.html
Copyright © 2011-2022 走看看