[活动专区] 【AT-START-F407测评】+LCD+XPT2046+画板

[复制链接]
 楼主| qjp1988113 发表于 2021-3-2 15:21 | 显示全部楼层 |阅读模式
下面开始调试XPT2046触摸芯片,同样用SPI1,具体代码配置,查看上一个例子。
配置XPT2046的CS和IRQ引脚:
  1. void xpt2046_port_init(void)
  2. {

  3.         GPIO_InitType GPIO_InitStructure;

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

  10.   //XPT2046_IRQ
  11.         GPIO_InitStructure.GPIO_Pins = XPT2046_IRQ_PIN;
  12.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_PU;//
  13.         GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;        
  14.         GPIO_Init(XPT2046_IRQ_GPIO, &GPIO_InitStructure);

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


  5. void xpt2046_init(void)
  6. {
  7.         uint16_t hwXpos, hwYpos;
  8.                
  9.         __XPT2046_CS_SET();

  10.         xpt2046_read_xy(&hwXpos, &hwYpos);
  11. }


  12. uint16_t xpt2046_read_ad_value(uint8_t chCmd)
  13. {
  14.     uint16_t hwData = 0;
  15.    
  16.     __XPT2046_CS_CLR();
  17.     xpt2046_write_byte(chCmd);
  18.     hwData = xpt2046_write_byte(0x00);
  19.     hwData <<= 8;
  20.     hwData |= xpt2046_write_byte(0x00);
  21.     hwData >>= 4;
  22.    __XPT2046_CS_SET();
  23.    
  24.     return hwData;
  25. }

  26. #define READ_TIMES  5
  27. #define LOST_NUM    1
  28. uint16_t xpt2046_read_average(uint8_t chCmd)
  29. {
  30.     uint8_t i, j;
  31.     uint16_t hwbuffer[READ_TIMES], hwSum = 0, hwTemp;

  32.     for (i = 0; i < READ_TIMES; i ++) {
  33.         hwbuffer[i] = xpt2046_read_ad_value(chCmd);
  34.     }
  35.     for (i = 0; i < READ_TIMES - 1; i ++) {
  36.         for (j = i + 1; j < READ_TIMES; j ++) {
  37.             if (hwbuffer[i] > hwbuffer[j]) {
  38.                 hwTemp = hwbuffer[i];
  39.                 hwbuffer[i] = hwbuffer[j];
  40.                 hwbuffer[j] = hwTemp;
  41.             }
  42.         }
  43.     }
  44.     for (i = LOST_NUM; i < READ_TIMES - LOST_NUM; i ++) {
  45.         hwSum += hwbuffer[i];
  46.     }
  47.     hwTemp = hwSum / (READ_TIMES - 2 * LOST_NUM);

  48.     return hwTemp;
  49. }


  50. void xpt2046_read_xy(uint16_t *phwXpos, uint16_t *phwYpos)
  51. {
  52.         *phwXpos = xpt2046_read_average(0xD0);
  53.         *phwYpos = xpt2046_read_average(0x90);
  54. }


  55. #define ERR_RANGE 50
  56. bool xpt2046_twice_read_xy(uint16_t *phwXpos, uint16_t *phwYpos)
  57. {
  58.         uint16_t hwXpos1, hwYpos1, hwXpos2, hwYpos2;

  59.         xpt2046_read_xy(&hwXpos1, &hwYpos1);
  60.         xpt2046_read_xy(&hwXpos2, &hwYpos2);

  61.         if (((hwXpos2 <= hwXpos1 && hwXpos1 < hwXpos2 + ERR_RANGE) || (hwXpos1 <= hwXpos2 && hwXpos2 < hwXpos1 + ERR_RANGE))
  62.         && ((hwYpos2 <= hwYpos1 && hwYpos1 < hwYpos2 + ERR_RANGE) || (hwYpos1 <= hwYpos2 && hwYpos2 < hwYpos1 + ERR_RANGE))) {
  63.                 *phwXpos = (hwXpos1 + hwXpos2) / 2;
  64.                 *phwYpos = (hwYpos1 + hwYpos2) / 2;
  65.                 return true;
  66.         }

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

  7. tp_dev_t s_tTouch;


  8. void tp_init(void)
  9. {
  10.         xpt2046_init();
  11. }

  12. void tp_draw_touch_point(uint16_t hwXpos, uint16_t hwYpos, uint16_t hwColor)
  13. {
  14.         lcd_draw_line(hwXpos - 12, hwYpos, hwXpos + 13, hwYpos, hwColor);
  15.         lcd_draw_line(hwXpos, hwYpos - 12, hwXpos, hwYpos + 13, hwColor);
  16.         lcd_draw_point(hwXpos + 1, hwYpos + 1, hwColor);
  17.         lcd_draw_point(hwXpos - 1, hwYpos + 1, hwColor);
  18.         lcd_draw_point(hwXpos + 1, hwYpos - 1, hwColor);
  19.         lcd_draw_point(hwXpos - 1, hwYpos - 1, hwColor);
  20.         lcd_draw_circle(hwXpos, hwYpos, 6, hwColor);
  21. }

  22. void tp_draw_big_point(uint16_t hwXpos, uint16_t hwYpos, uint16_t hwColor)
  23. {
  24.         lcd_draw_point(hwXpos, hwYpos, hwColor);
  25.         lcd_draw_point(hwXpos + 1, hwYpos, hwColor);
  26.         lcd_draw_point(hwXpos, hwYpos + 1, hwColor);
  27.         lcd_draw_point(hwXpos + 1, hwYpos + 1, hwColor);
  28. }

  29. void tp_show_info(uint16_t hwXpos0, uint16_t hwYpos0,
  30.                      uint16_t hwXpos1, uint16_t hwYpos1,
  31.                      uint16_t hwXpos2, uint16_t hwYpos2,
  32.                      uint16_t hwXpos3, uint16_t hwYpos3, uint16_t hwFac)
  33. {

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

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

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

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

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

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

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

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

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

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

  53. uint8_t tp_scan(uint8_t chCoordType)
  54. {
  55.         if (!(__XPT2046_IRQ_READ())) {
  56.                 if (chCoordType) {
  57.                         xpt2046_twice_read_xy(&s_tTouch.hwXpos, &s_tTouch.hwYpos);
  58.                 } else if (xpt2046_twice_read_xy(&s_tTouch.hwXpos, &s_tTouch.hwYpos)) {
  59.                         //s_tTouch.hwXpos = 0.066 * s_tTouch.hwXpos + (-12);//s_tTouch.fXfac * s_tTouch.hwXpos + s_tTouch.iXoff;
  60.                         //s_tTouch.hwYpos = (-0.089) * s_tTouch.hwYpos + (352);//s_tTouch.fYfac * s_tTouch.hwYpos + s_tTouch.iYoff;
  61.                         s_tTouch.hwXpos = s_tTouch.fXfac * s_tTouch.hwXpos + s_tTouch.iXoff;
  62.                         s_tTouch.hwYpos = s_tTouch.fYfac * s_tTouch.hwYpos + s_tTouch.iYoff;
  63.                 }
  64.                 if (0 == (s_tTouch.chStatus & TP_PRESS_DOWN)) {
  65.                         s_tTouch.chStatus = TP_PRESS_DOWN | TP_PRESSED;
  66.                         s_tTouch.hwXpos0 = s_tTouch.hwXpos;
  67.                         s_tTouch.hwYpos0 = s_tTouch.hwYpos;
  68.                 }

  69.         } else {
  70.                 if (s_tTouch.chStatus & TP_PRESS_DOWN) {
  71.                         s_tTouch.chStatus &= ~(1 << 7);
  72.                 } else {
  73.                         s_tTouch.hwXpos0 = 0;
  74.                         s_tTouch.hwYpos0 = 0;
  75.                         s_tTouch.hwXpos = 0xffff;
  76.                         s_tTouch.hwYpos = 0xffff;
  77.                 }
  78.         }

  79.         return (s_tTouch.chStatus & TP_PRESS_DOWN);
  80. }


  81. void tp_adjust(void)
  82. {       
  83.         uint8_t  cnt = 0;
  84.         uint16_t hwTimeout = 0, d1, d2, pos_temp[4][2];
  85.         uint32_t tem1, tem2;
  86.         float fac;                               

  87.         lcd_clear_screen(WHITE);
  88.         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.",
  89.                                         16, RED);
  90.         tp_draw_touch_point(20, 20, RED);
  91.         s_tTouch.chStatus = 0;
  92.         s_tTouch.fXfac = 0;
  93.         while (1) {
  94.                 tp_scan(1);
  95.                 if((s_tTouch.chStatus & 0xC0) == TP_PRESSED) {       
  96.                         hwTimeout = 0;
  97.                         s_tTouch.chStatus &= ~(1 << 6);
  98.                                                                              
  99.                         pos_temp[cnt][0] = s_tTouch.hwXpos;
  100.                         pos_temp[cnt][1] = s_tTouch.hwYpos;
  101.                         cnt ++;          
  102.                         switch(cnt) {                          
  103.                                 case 1:                                                 
  104.                                         tp_draw_touch_point(20, 20, WHITE);
  105.                                         tp_draw_touch_point(LCD_WIDTH - 20, 20, RED);
  106.                                         break;
  107.                                 case 2:
  108.                                         tp_draw_touch_point(LCD_WIDTH - 20, 20, WHITE);
  109.                                         tp_draw_touch_point(20, LCD_HEIGHT - 20, RED);
  110.                                         break;
  111.                                 case 3:
  112.                                         tp_draw_touch_point(20, LCD_HEIGHT - 20, WHITE);
  113.                                         tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, RED);
  114.                                         break;
  115.                                 case 4:       
  116.                                         tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[1][0]));//x1-x2
  117.                                         tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[1][1]));//y1-y2
  118.                                         tem1*=tem1;
  119.                                         tem2*=tem2;
  120.                                         tem1+=tem2;
  121.                                         d1=sqrt(tem1);

  122.                                         tem1=abs((int16_t)(pos_temp[2][0]-pos_temp[3][0]));//x3-x4
  123.                                         tem2=abs((int16_t)(pos_temp[2][1]-pos_temp[3][1]));//y3-y4
  124.                                         tem1*=tem1;
  125.                                         tem2*=tem2;
  126.                                         tem1+=tem2;
  127.                                         d2=sqrt(tem1);
  128.                                         fac=(float)d1/d2;
  129.                                         if(fac<0.95f||fac>1.05f||d1==0||d2==0) {
  130.                                                 cnt=0;
  131.                                                 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);  
  132.                                                 delay_ms(1000);
  133.                                                 lcd_fill_rect(96, 240, 24, 16, WHITE);
  134.                                                 tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
  135.                                                 tp_draw_touch_point(20, 20, RED);
  136.                                                 continue;
  137.                                         }

  138.                                         tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[2][0]));//x1-x3
  139.                                         tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[2][1]));//y1-y3
  140.                                         tem1*=tem1;
  141.                                         tem2*=tem2;
  142.                                         tem1+=tem2;
  143.                                         d1=sqrt(tem1);//

  144.                                         tem1=abs((int16_t)(pos_temp[1][0]-pos_temp[3][0]));//x2-x4
  145.                                         tem2=abs((int16_t)(pos_temp[1][1]-pos_temp[3][1]));//y2-y4
  146.                                         tem1*=tem1;
  147.                                         tem2*=tem2;
  148.                                         tem1+=tem2;
  149.                                         d2=sqrt(tem1);//
  150.                                         fac=(float)d1/d2;
  151.                                         if(fac<0.95f||fac>1.05f) {
  152.                                                 cnt=0;
  153.                                                 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   
  154.                                                 delay_ms(1000);
  155.                                                 lcd_fill_rect(96, 240, 24, 16, WHITE);
  156.                                                 tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
  157.                                                 tp_draw_touch_point(20, 20, RED);
  158.                                                 continue;
  159.                                         }//
  160.                                                                   
  161.                                         tem1=abs((int16_t)(pos_temp[1][0]-pos_temp[2][0]));//x1-x3
  162.                                         tem2=abs((int16_t)(pos_temp[1][1]-pos_temp[2][1]));//y1-y3
  163.                                         tem1*=tem1;
  164.                                         tem2*=tem2;
  165.                                         tem1+=tem2;
  166.                                         d1=sqrt(tem1);//

  167.                                         tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[3][0]));//x2-x4
  168.                                         tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[3][1]));//y2-y4
  169.                                         tem1*=tem1;
  170.                                         tem2*=tem2;
  171.                                         tem1+=tem2;
  172.                                         d2=sqrt(tem1);//
  173.                                         fac=(float)d1/d2;
  174.                                         if(fac<0.95f||fac>1.05f) {
  175.                                                 cnt=0;       
  176.                                                 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   
  177.                                                 delay_ms(1000);
  178.                                                 lcd_fill_rect(96, 240, 24, 16, WHITE);
  179.                                                 tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
  180.                                                 tp_draw_touch_point(20, 20, RED);
  181.                                                 continue;
  182.                                         }

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

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

  187.                                        
  188.                                         if(abs(s_tTouch.fXfac) > 2 || abs(s_tTouch.fYfac) > 2) {
  189.                                                 cnt=0;
  190.                                             tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, WHITE);
  191.                                                 tp_draw_touch_point(20, 20, RED);                                                               
  192.                                                 lcd_display_string(40, 26, (const uint8_t *)"TP Need readjust!", 16, RED);
  193.                                                 continue;
  194.                                         }
  195.                                         lcd_clear_screen(WHITE);
  196.                                         lcd_display_string(35, 110, (const uint8_t *)"Touch Screen Adjust OK!", 16, BLUE);
  197.                                         delay_ms(1000);
  198.                                         lcd_clear_screen(WHITE);  
  199.                                         return;                                 
  200.                         }
  201.                 }
  202.                 delay_ms(10);
  203.                 if (++ hwTimeout >= 1000) {
  204.                         break;
  205.                 }
  206.         }
  207. }


  208. void tp_dialog(void)
  209. {
  210.         lcd_clear_screen(WHITE);
  211.         lcd_display_string(LCD_WIDTH - 40, 0, (const uint8_t *)"CLEAR", 16, BLUE);
  212. }

  213. void tp_draw_board(void)
  214. {
  215.         tp_scan(0);
  216.         if (s_tTouch.chStatus & TP_PRESS_DOWN) {
  217.                 if (s_tTouch.hwXpos < LCD_WIDTH && s_tTouch.hwYpos < LCD_HEIGHT) {
  218.                         if (s_tTouch.hwXpos > (LCD_WIDTH - 40) && s_tTouch.hwYpos < 16) {
  219.                                 tp_dialog();
  220.                         } else {
  221.                                 tp_draw_big_point(s_tTouch.hwXpos, s_tTouch.hwYpos, RED);
  222.                         }
  223.                 }
  224.         }
  225. }


在main文件中调用:

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

  9.   /* Config LED */
  10.   AT32_Board_Init();
  11.   /* SPIy Config -------------------------------------------------------------*/
  12.   SPI1_Init();

  13.         lcd_port_init();
  14.         lcd_init();
  15.        
  16.         xpt2046_port_init();
  17.         tp_init();

  18.         //触摸校准
  19.         tp_adjust();
  20.         tp_dialog();

  21.   while (1)
  22.   {
  23.                 tp_draw_board();
  24.         }
  25. }
编译测试:
56.jpg
代码:
SPI_LCD _XPT2046 - russa.rar (5.26 MB, 下载次数: 158)


lidi911 发表于 2021-3-3 07:54 来自手机 | 显示全部楼层
不错,谢谢楼主分享。
单片小菜 发表于 2021-3-3 12:50 | 显示全部楼层
感谢楼主的分享,谢谢。
huangcunxiake 发表于 2021-3-3 13:26 | 显示全部楼层
这个操作漂亮;
里面有晴雨 发表于 2021-3-3 15:07 | 显示全部楼层
这个操作很漂亮,就是屏幕上的花不好看。
名字是啥样 发表于 2021-3-4 12:28 | 显示全部楼层
这个花挺漂亮的。
感谢楼主分享。
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

粉丝
快速回复 在线客服 返回列表 返回顶部