Home › 论坛 › 开发和更新问题 › 织女星开发板通过SPI协议驱动ARDUINO LCD模块(触屏) › 回复于:织女星开发板通过SPI协议驱动ARDUINO LCD模块(触屏)
屏幕校正
选取屏幕四个角上的四个点,将读取的数据存放在一个二维数组中,然后根据计算的factor值判定校准是否成功,如果成功则进入下一步,不成功的话就再来一次。触屏校正代码如下所示:
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(LCD_COLOR_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, LCD_COLOR_RED);
tp_draw_touch_point(20, 20, LCD_COLOR_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, LCD_COLOR_WHITE);
tp_draw_touch_point(LCD_WIDTH - 20, 20, LCD_COLOR_RED);
break;
case 2:
tp_draw_touch_point(LCD_WIDTH - 20, 20, LCD_COLOR_WHITE);
tp_draw_touch_point(20, LCD_HEIGHT - 20, LCD_COLOR_RED);
break;
case 3:
tp_draw_touch_point(20, LCD_HEIGHT - 20, LCD_COLOR_WHITE);
tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, LCD_COLOR_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.95||fac>1.05||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);
lcd_delayms(1000);
tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, LCD_COLOR_WHITE);
tp_draw_touch_point(20, 20, LCD_COLOR_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.95||fac>1.05) {
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);
lcd_delayms(1000);
lcd_fill_rect(96, 240, 24, 16, LCD_COLOR_WHITE);
tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, LCD_COLOR_WHITE);
tp_draw_touch_point(20, 20, LCD_COLOR_RED);
continue;
}
tem1=abs((int16_t)(pos_temp[1][0]-pos_temp[2][0]));//x2-x3
tem2=abs((int16_t)(pos_temp[1][1]-pos_temp[2][1]));//y2-y3
tem1*=tem1;
tem2*=tem2;
tem1+=tem2;
d1=sqrt(tem1);
tem1=abs((int16_t)(pos_temp[0][0]-pos_temp[3][0]));//x1-x4
tem2=abs((int16_t)(pos_temp[0][1]-pos_temp[3][1]));//y1-y4
tem1*=tem1;
tem2*=tem2;
tem1+=tem2;
d2=sqrt(tem1);
fac=(float)d1/d2;
if(fac<0.95||fac>1.05) {
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);
lcd_delayms(1000);
tp_draw_touch_point(LCD_WIDTH - 20, LCD_HEIGHT - 20, LCD_COLOR_WHITE);
tp_draw_touch_point(20, 20, LCD_COLOR_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, LCD_COLOR_WHITE);
tp_draw_touch_point(20, 20, LCD_COLOR_RED);
lcd_display_string(40, 26, (const uint8_t *)"TP Need readjust!", 16, LCD_COLOR_RED);
continue;
}
lcd_clear_screen(LCD_COLOR_WHITE);
lcd_display_string(35, 110, (const uint8_t *)"Touch Screen Adjust OK!", 16, LCD_COLOR_BLUE);
lcd_delayms(1000);
lcd_clear_screen(LCD_COLOR_WHITE);
return;
}
}
lcd_delayms(600);
if (++ hwTimeout >= 6000) {
break;
}
}
}
其中调用到tp_scan()函数,检测是否有触屏并获得物理坐标值,具体实现如下:
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 = 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);
}
触屏效果
最终,实现可以在屏幕上实现绘画和简单的清屏对话
最后展示一下我的简笔画兔子(嘻嘻):
本帖的部分内容参考了XPT2046触摸屏实验过程详解与STM32代码解析和2.8inch TFT Touch Shield用户手册