下面开始调试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)
|
|