打印
[活动专区]

【AT-START-F407测评】+LCD+XPT2046+画板

[复制链接]
850|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
下面开始调试XPT2046触摸芯片,同样用SPI1,具体代码配置,查看上一个例子。
配置XPT2046的CS和IRQ引脚:
void xpt2046_port_init(void)
{

        GPIO_InitType GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB, ENABLE);  
        //SD_CS XPT2046_CS
        GPIO_InitStructure.GPIO_Pins = XPT2046_CS_PIN|SD_CS_PIN;                            
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
        GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

  //XPT2046_IRQ
        GPIO_InitStructure.GPIO_Pins = XPT2046_IRQ_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_PU;//
        GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;        
        GPIO_Init(XPT2046_IRQ_GPIO, &GPIO_InitStructure);

        //触摸和SD均失能
        __SD_CS_SET();
        //__XPT2046_CS_SET();
}
XPT2046读写一样定义SPI1:
#define __XPT2046_WRITE_BYTE(__DATA)       SPI1ReadWriteByte(__DATA)
XPT2046其他函数:
uint8_t xpt2046_write_byte(uint8_t chData)
{
    return __XPT2046_WRITE_BYTE(chData);
}


void xpt2046_init(void)
{
        uint16_t hwXpos, hwYpos;
               
        __XPT2046_CS_SET();

        xpt2046_read_xy(&hwXpos, &hwYpos);
}


uint16_t xpt2046_read_ad_value(uint8_t chCmd)
{
    uint16_t hwData = 0;
   
    __XPT2046_CS_CLR();
    xpt2046_write_byte(chCmd);
    hwData = xpt2046_write_byte(0x00);
    hwData <<= 8;
    hwData |= xpt2046_write_byte(0x00);
    hwData >>= 4;
   __XPT2046_CS_SET();
   
    return hwData;
}

#define READ_TIMES  5
#define LOST_NUM    1
uint16_t xpt2046_read_average(uint8_t chCmd)
{
    uint8_t i, j;
    uint16_t hwbuffer[READ_TIMES], hwSum = 0, hwTemp;

    for (i = 0; i < READ_TIMES; i ++) {
        hwbuffer[i] = xpt2046_read_ad_value(chCmd);
    }
    for (i = 0; i < READ_TIMES - 1; i ++) {
        for (j = i + 1; j < READ_TIMES; j ++) {
            if (hwbuffer[i] > hwbuffer[j]) {
                hwTemp = hwbuffer[i];
                hwbuffer[i] = hwbuffer[j];
                hwbuffer[j] = hwTemp;
            }
        }
    }
    for (i = LOST_NUM; i < READ_TIMES - LOST_NUM; i ++) {
        hwSum += hwbuffer[i];
    }
    hwTemp = hwSum / (READ_TIMES - 2 * LOST_NUM);

    return hwTemp;
}


void xpt2046_read_xy(uint16_t *phwXpos, uint16_t *phwYpos)
{
        *phwXpos = xpt2046_read_average(0xD0);
        *phwYpos = xpt2046_read_average(0x90);
}


#define ERR_RANGE 50
bool xpt2046_twice_read_xy(uint16_t *phwXpos, uint16_t *phwYpos)
{
        uint16_t hwXpos1, hwYpos1, hwXpos2, hwYpos2;

        xpt2046_read_xy(&hwXpos1, &hwYpos1);
        xpt2046_read_xy(&hwXpos2, &hwYpos2);

        if (((hwXpos2 <= hwXpos1 && hwXpos1 < hwXpos2 + ERR_RANGE) || (hwXpos1 <= hwXpos2 && hwXpos2 < hwXpos1 + ERR_RANGE))
        && ((hwYpos2 <= hwYpos1 && hwYpos1 < hwYpos2 + ERR_RANGE) || (hwYpos1 <= hwYpos2 && hwYpos2 < hwYpos1 + ERR_RANGE))) {
                *phwXpos = (hwXpos1 + hwXpos2) / 2;
                *phwYpos = (hwYpos1 + hwYpos2) / 2;
                return true;
        }

        return false;
}
触摸应用的函数touch文件的代码,包含触摸检测,校准检测,画板程序及一个清空按键:
#include "touch.h"
#include "lcd.h"
#include "XPT2046.h"
#include <stdlib.h>
#include <math.h>
#include "at32_board.h"

tp_dev_t s_tTouch;


void tp_init(void)
{
        xpt2046_init();
}

void tp_draw_touch_point(uint16_t hwXpos, uint16_t hwYpos, uint16_t hwColor)
{
        lcd_draw_line(hwXpos - 12, hwYpos, hwXpos + 13, hwYpos, hwColor);
        lcd_draw_line(hwXpos, hwYpos - 12, hwXpos, hwYpos + 13, hwColor);
        lcd_draw_point(hwXpos + 1, hwYpos + 1, hwColor);
        lcd_draw_point(hwXpos - 1, hwYpos + 1, hwColor);
        lcd_draw_point(hwXpos + 1, hwYpos - 1, hwColor);
        lcd_draw_point(hwXpos - 1, hwYpos - 1, hwColor);
        lcd_draw_circle(hwXpos, hwYpos, 6, hwColor);
}

void tp_draw_big_point(uint16_t hwXpos, uint16_t hwYpos, uint16_t hwColor)
{
        lcd_draw_point(hwXpos, hwYpos, hwColor);
        lcd_draw_point(hwXpos + 1, hwYpos, hwColor);
        lcd_draw_point(hwXpos, hwYpos + 1, hwColor);
        lcd_draw_point(hwXpos + 1, hwYpos + 1, hwColor);
}

void tp_show_info(uint16_t hwXpos0, uint16_t hwYpos0,
                     uint16_t hwXpos1, uint16_t hwYpos1,
                     uint16_t hwXpos2, uint16_t hwYpos2,
                     uint16_t hwXpos3, uint16_t hwYpos3, uint16_t hwFac)
{

        lcd_display_string(40, 160, (const uint8_t *)"x1", 16, RED);
        lcd_display_string(40 + 80, 160, (const uint8_t *)"y1", 16, RED);

        lcd_display_string(40, 180, (const uint8_t *)"x2", 16, RED);
        lcd_display_string(40 + 80, 180, (const uint8_t *)"y2", 16, RED);

        lcd_display_string(40, 200, (const uint8_t *)"x3", 16, RED);
        lcd_display_string(40 + 80, 200, (const uint8_t *)"y3", 16, RED);

        lcd_display_string(40, 220, (const uint8_t *)"x4", 16, RED);
        lcd_display_string(40 + 80, 220, (const uint8_t *)"y4", 16, RED);

        lcd_display_string(40, 240, (const uint8_t *)"fac is:", 16, RED);

        lcd_display_num(40 + 24, 160, hwXpos0, 4, 16, RED);
        lcd_display_num(40 + 24 + 80, 160, hwYpos0, 4, 16, RED);

        lcd_display_num(40 + 24, 180, hwXpos1, 4, 16, RED);
        lcd_display_num(40 + 24 + 80, 180, hwYpos1, 4, 16, RED);

        lcd_display_num(40 + 24, 200, hwXpos2, 4, 16, RED);
        lcd_display_num(40 + 24 + 80, 200, hwYpos2, 4, 16, RED);

        lcd_display_num(40 + 24, 220, hwXpos3, 4, 16, RED);
        lcd_display_num(40 + 24 + 80, 220, hwYpos3, 4, 16, RED);

        lcd_display_num(40 + 56, 240, hwFac, 3, 16, RED);
}

uint8_t tp_scan(uint8_t chCoordType)
{
        if (!(__XPT2046_IRQ_READ())) {
                if (chCoordType) {
                        xpt2046_twice_read_xy(&s_tTouch.hwXpos, &s_tTouch.hwYpos);
                } else if (xpt2046_twice_read_xy(&s_tTouch.hwXpos, &s_tTouch.hwYpos)) {
                        //s_tTouch.hwXpos = 0.066 * s_tTouch.hwXpos + (-12);//s_tTouch.fXfac * s_tTouch.hwXpos + s_tTouch.iXoff;
                        //s_tTouch.hwYpos = (-0.089) * s_tTouch.hwYpos + (352);//s_tTouch.fYfac * s_tTouch.hwYpos + s_tTouch.iYoff;
                        s_tTouch.hwXpos = s_tTouch.fXfac * s_tTouch.hwXpos + s_tTouch.iXoff;
                        s_tTouch.hwYpos = s_tTouch.fYfac * s_tTouch.hwYpos + s_tTouch.iYoff;
                }
                if (0 == (s_tTouch.chStatus & TP_PRESS_DOWN)) {
                        s_tTouch.chStatus = TP_PRESS_DOWN | TP_PRESSED;
                        s_tTouch.hwXpos0 = s_tTouch.hwXpos;
                        s_tTouch.hwYpos0 = s_tTouch.hwYpos;
                }

        } else {
                if (s_tTouch.chStatus & TP_PRESS_DOWN) {
                        s_tTouch.chStatus &= ~(1 << 7);
                } else {
                        s_tTouch.hwXpos0 = 0;
                        s_tTouch.hwYpos0 = 0;
                        s_tTouch.hwXpos = 0xffff;
                        s_tTouch.hwYpos = 0xffff;
                }
        }

        return (s_tTouch.chStatus & TP_PRESS_DOWN);
}


void tp_adjust(void)
{       
        uint8_t  cnt = 0;
        uint16_t hwTimeout = 0, d1, d2, pos_temp[4][2];
        uint32_t tem1, tem2;
        float fac;                               

        lcd_clear_screen(WHITE);
        lcd_display_string(40, 40, (const uint8_t *)"Please use the stylus click the cross on the screen. The cross will always move until the screen adjustment is completed.",
                                        16, RED);
        tp_draw_touch_point(20, 20, RED);
        s_tTouch.chStatus = 0;
        s_tTouch.fXfac = 0;
        while (1) {
                tp_scan(1);
                if((s_tTouch.chStatus & 0xC0) == TP_PRESSED) {       
                        hwTimeout = 0;
                        s_tTouch.chStatus &= ~(1 << 6);
                                                                             
                        pos_temp[cnt][0] = s_tTouch.hwXpos;
                        pos_temp[cnt][1] = s_tTouch.hwYpos;
                        cnt ++;          
                        switch(cnt) {                          
                                case 1:                                                 
                                        tp_draw_touch_point(20, 20, WHITE);
                                        tp_draw_touch_point(LCD_WIDTH - 20, 20, RED);
                                        break;
                                case 2:
                                        tp_draw_touch_point(LCD_WIDTH - 20, 20, WHITE);
                                        tp_draw_touch_point(20, LCD_HEIGHT - 20, RED);
                                        break;
                                case 3:
                                        tp_draw_touch_point(20, LCD_HEIGHT - 20, WHITE);
                                        tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, RED);
                                        break;
                                case 4:       
                                        tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[1][0]));//x1-x2
                                        tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[1][1]));//y1-y2
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d1=sqrt(tem1);

                                        tem1=abs((int16_t)(pos_temp[2][0]-pos_temp[3][0]));//x3-x4
                                        tem2=abs((int16_t)(pos_temp[2][1]-pos_temp[3][1]));//y3-y4
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d2=sqrt(tem1);
                                        fac=(float)d1/d2;
                                        if(fac<0.95f||fac>1.05f||d1==0||d2==0) {
                                                cnt=0;
                                                tp_show_info(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);  
                                                delay_ms(1000);
                                                lcd_fill_rect(96, 240, 24, 16, WHITE);
                                                tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
                                                tp_draw_touch_point(20, 20, RED);
                                                continue;
                                        }

                                        tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[2][0]));//x1-x3
                                        tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[2][1]));//y1-y3
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d1=sqrt(tem1);//

                                        tem1=abs((int16_t)(pos_temp[1][0]-pos_temp[3][0]));//x2-x4
                                        tem2=abs((int16_t)(pos_temp[1][1]-pos_temp[3][1]));//y2-y4
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d2=sqrt(tem1);//
                                        fac=(float)d1/d2;
                                        if(fac<0.95f||fac>1.05f) {
                                                cnt=0;
                                                tp_show_info(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//??¨o?¨oy?Y   
                                                delay_ms(1000);
                                                lcd_fill_rect(96, 240, 24, 16, WHITE);
                                                tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
                                                tp_draw_touch_point(20, 20, RED);
                                                continue;
                                        }//
                                                                  
                                        tem1=abs((int16_t)(pos_temp[1][0]-pos_temp[2][0]));//x1-x3
                                        tem2=abs((int16_t)(pos_temp[1][1]-pos_temp[2][1]));//y1-y3
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d1=sqrt(tem1);//

                                        tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[3][0]));//x2-x4
                                        tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[3][1]));//y2-y4
                                        tem1*=tem1;
                                        tem2*=tem2;
                                        tem1+=tem2;
                                        d2=sqrt(tem1);//
                                        fac=(float)d1/d2;
                                        if(fac<0.95f||fac>1.05f) {
                                                cnt=0;       
                                                tp_show_info(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//??¨o?¨oy?Y   
                                                delay_ms(1000);
                                                lcd_fill_rect(96, 240, 24, 16, WHITE);
                                                tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
                                                tp_draw_touch_point(20, 20, RED);
                                                continue;
                                        }

                                        s_tTouch.fXfac = (float)(LCD_WIDTH - 40) / (int16_t)(pos_temp[1][0] - pos_temp[0][0]);       
                                        s_tTouch.iXoff = (LCD_WIDTH - s_tTouch.fXfac * (pos_temp[1][0] + pos_temp[0][0])) / 2;

                                        s_tTouch.fYfac = (float)(LCD_HEIGHT - 40) / (int16_t)(pos_temp[2][1] - pos_temp[0][1]);          
                                        s_tTouch.iYoff = (LCD_HEIGHT - s_tTouch.fYfac * (pos_temp[2][1] + pos_temp[0][1])) / 2;

                                       
                                        if(abs(s_tTouch.fXfac) > 2 || abs(s_tTouch.fYfac) > 2) {
                                                cnt=0;
                                            tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
                                                tp_draw_touch_point(20, 20, RED);                                                               
                                                lcd_display_string(40, 26, (const uint8_t *)"TP Need readjust!", 16, RED);
                                                continue;
                                        }
                                        lcd_clear_screen(WHITE);
                                        lcd_display_string(35, 110, (const uint8_t *)"Touch Screen Adjust OK!", 16, BLUE);
                                        delay_ms(1000);
                                        lcd_clear_screen(WHITE);  
                                        return;                                 
                        }
                }
                delay_ms(10);
                if (++ hwTimeout >= 1000) {
                        break;
                }
        }
}


void tp_dialog(void)
{
        lcd_clear_screen(WHITE);
        lcd_display_string(LCD_WIDTH - 40, 0, (const uint8_t *)"CLEAR", 16, BLUE);
}

void tp_draw_board(void)
{
        tp_scan(0);
        if (s_tTouch.chStatus & TP_PRESS_DOWN) {
                if (s_tTouch.hwXpos < LCD_WIDTH && s_tTouch.hwYpos < LCD_HEIGHT) {
                        if (s_tTouch.hwXpos > (LCD_WIDTH - 40) && s_tTouch.hwYpos < 16) {
                                tp_dialog();
                        } else {
                                tp_draw_big_point(s_tTouch.hwXpos, s_tTouch.hwYpos, RED);
                        }
                }
        }
}


在main文件中调用:

int main(void)
{
        /*!< At this stage the microcontroller clock setting is already configured,
         this is done through SystemInit() function which is called from startup
         file (startup_at32f403_xx.s) before to branch to application main.
         To reconfigure the default setting of SystemInit() function, refer to
         system_at32f4xx.c file
        */     

  /* Config LED */
  AT32_Board_Init();
  /* SPIy Config -------------------------------------------------------------*/
  SPI1_Init();

        lcd_port_init();
        lcd_init();
       
        xpt2046_port_init();
        tp_init();

        //触摸校准
        tp_adjust();
        tp_dialog();

  while (1)
  {
                tp_draw_board();
        }
}
编译测试:

代码:
SPI_LCD _XPT2046 - russa.rar (5.26 MB)


使用特权

评论回复
沙发
lidi911| | 2021-3-3 07:54 | 只看该作者
不错,谢谢楼主分享。

使用特权

评论回复
板凳
单片小菜| | 2021-3-3 12:50 | 只看该作者
感谢楼主的分享,谢谢。

使用特权

评论回复
地板
huangcunxiake| | 2021-3-3 13:26 | 只看该作者
这个操作漂亮;

使用特权

评论回复
5
里面有晴雨| | 2021-3-3 15:07 | 只看该作者
这个操作很漂亮,就是屏幕上的花不好看。

使用特权

评论回复
6
名字是啥样| | 2021-3-4 12:28 | 只看该作者
这个花挺漂亮的。
感谢楼主分享。

使用特权

评论回复
7
ipman| | 2021-3-4 17:42 | 只看该作者
这个函数让系统失去实时性了,如果改进下,应该更逼真。
       
unsigned int SPI1ReadWriteByte(unsigned char tx_data)
{
                /* Wait for SPIy Tx buffer empty */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TE) == RESET);

    /* Send SPIy data */
    SPI_I2S_TxData(SPI1,tx_data);

    /* Wait for SPIy data reception */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RNE) == RESET);
    /* Read SPIy received data */
    return SPI_I2S_RxData(SPI1);       
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝