Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
LittlevGL_LVGL
RT-Thread Studio
触摸屏
RT-Thread Studio使用记录(九)LittlevGL2RTT触摸屏
发布于 2021-01-30 10:10:10 浏览:2920
订阅该版
[RT-Thread Studio使用记录(一)点亮led](https://club.rt-thread.org/ask/article/2519.html) [RT-Thread Studio使用记录(二)pwm呼吸灯](https://club.rt-thread.org/ask/article/2520.html) [RT-Thread Studio使用记录(三)flash挂载文件系统](https://club.rt-thread.org/ask/article/2521.html) [RT-Thread Studio使用记录(四)SD-Card 挂载文件系统](https://club.rt-thread.org/ask/article/2526.html) [RT-Thread Studio使用记录(五)USB 虚拟串口](https://club.rt-thread.org/ask/article/2524.html) [RT-Thread Studio使用记录(六)ESP8266网络设备](https://club.rt-thread.org/ask/article/2527.html) [RT-Thread Studio使用记录(七)STemWin](https://club.rt-thread.org/ask/article/2529.html) [RT-Thread Studio使用记录(八)LittlevGL2RTT](https://club.rt-thread.org/ask/article/2530.html) [RT-Thread Studio使用记录(九)LittlevGL2RTT触摸屏](https://club.rt-thread.org/ask/article/2531.html) [RT-Thread Studio使用记录(十)LittlevGL2RTT 贪吃蛇](https://club.rt-thread.org/ask/article/2534.html) [RT-Thread Studio使用记录(十一)LittlevGL2RTT 贪吃蛇+俄罗斯方块](https://club.rt-thread.org/ask/article/2544.html) 本章使用 RT-Thread 的 LittlevGL2RTT 软件包。基于正点原子的触摸屏驱动程序,修改为适配 LittlevGL2RTT 的驱动,运行 LittlevGL2RTT 的例程。 1、 打开 CubeMX 配置文件,配置 SPI1 选项。删除生成的 main.c 及 stm32f4xx_it.c ,注释掉 stm32f4xx_fal_msp.c 中的 ' #include "main.h" ',并添加 ' #include "drv_common.c" '。 ![cube-config.png](https://oss-club.rt-thread.org/uploads/20210130/5dbed560c94be9e0ea9d3632d9f54f54.png) ![原理图.png](https://oss-club.rt-thread.org/uploads/20210130/eee31ae9c0a64b72c99ca9ccf7287ad5.png) 2、 在 drivers 文件夹下,新建 xpt2046.h 和 xpt2046.c 两个文件。参考正点原子的触摸屏驱动,修改程序如下: ``` #ifndef __XPT2046_H__ #define __XPT2046_H__ #include
#define TP_PRES_DOWN 0x80 //触摸屏被按下 #define TP_CATH_PRES 0x40 //有触摸屏按下了 #define RT_TOUCH_NORMAL 0 #define RT_TOUCH_CALIBRATION_DATA 1 #define RT_TOUCH_CALIBRATION 2 #define TOUCH_READ_TIMES 5 //触摸屏控制器 typedef struct { void (*init)(void); //初始化触摸屏控制器 rt_uint8_t (*scan)(rt_uint8_t); //扫描触摸屏。 0,屏幕坐标;1,物理坐标 void (*adjust)(void); //触摸屏校准 rt_uint16_t x0; //原始坐标(第一次按下时的坐标) rt_uint16_t y0; rt_uint16_t x; //当前坐标(此次扫描时触摸屏的坐标) rt_uint16_t y; rt_uint8_t sta; //笔的状态 //b7:按下1 / 松开0; //b6:0,没有按键按下;1,有按键按下. ////////////////////////触摸屏校准参数///////////////////////// float xfac; float yfac; short xoff; short yoff; //新增参数,当触摸屏的左右上下完全颠倒时需要用到 //touchtype=0的时候,适合左右为X坐标,上下为Y坐标的屏幕. //touchtype=1的时候,适合左右为Y坐标,上下为X坐标的屏幕. rt_uint8_t touchtype; }_m_tp_dev; extern _m_tp_dev tp_dev; //触摸屏控制器 #endif /* APPLICATIONS_XPT2046_H_ */ ``` ``` /* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-12-31 mgcheng the first version */ #include
#include "rtdevice.h" #include "board.h" #include "math.h" #include "xpt2046.h" #include "drv_lcd.h" #include "stdio.h" #include "lvgl.h" #define DBG_TAG "xpt2046" #define DBG_LVL DBG_LOG #include
#define T_IRQ GET_PIN(C, 4) #define T_CS GET_PIN(A, 4) #define T_SCK GET_PIN(A, 5) #define T_DIN GET_PIN(A, 6) #define T_DOUT GET_PIN(A, 7) #define TOUCH_ERR_RANGE 50 //误差范围 //#define XPT2046_USING_SPI //是否只用 spi 通信 rt_uint8_t TOUCH_X_CMD = 0x90; rt_uint8_t TOUCH_Y_CMD = 0xD0; #ifdef XPT2046_USING_SPI static void MX_SPI1_Init(void); #endif static rt_uint8_t XPT2046_scan(rt_uint8_t tp); static void XPT2046_adjust(void); static rt_uint8_t XPT2046_read_xy(rt_uint16_t *x_value, rt_uint16_t *y_value); _m_tp_dev tp_dev= { #ifdef XPT2046_USING_SPI MX_SPI1_Init, #else NULL, #endif XPT2046_scan, XPT2046_adjust, 0, 0, 0, 0, 0, -0.126874, -0.073548, 501, 282, 1, }; #ifdef XPT2046_USING_SPI SPI_HandleTypeDef hspi1; /** * @brief SPI1 Initialization Function * @param None * @retval None */ static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ HAL_SPI_MspInit(&hspi1); /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } #endif static void XPT2046_GPIO_Init(void) { rt_pin_mode(T_CS, PIN_MODE_OUTPUT); rt_pin_mode(T_IRQ, PIN_MODE_INPUT_PULLUP); #ifdef XPT2046_USING_SPI MX_SPI1_Init(); #else rt_pin_mode(T_SCK, PIN_MODE_OUTPUT); rt_pin_mode(T_DIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(T_DOUT, PIN_MODE_OUTPUT); #endif // rt_pin_attach_irq(T_IRQ, PIN_IRQ_MODE_FALLING, XPT2046_get_date, RT_NULL); // rt_pin_irq_enable(T_IRQ, PIN_IRQ_ENABLE); XPT2046_read_xy(&tp_dev.x, &tp_dev.y); } //SPI写数据 //向触摸屏 IC 写入 1byte 数据 //num: 要写入的数据 void TP_Write_Byte(rt_uint8_t num) { rt_uint8_t count=0,i=180; for(count=0;count<8;count++) { if(num&0x80) rt_pin_write(T_DOUT, 1); else rt_pin_write(T_DOUT, 0); num<<=1; rt_pin_write(T_SCK, 0); while(i--); rt_pin_write(T_SCK, 1); //上升沿有效 } } //SPI 读数据 //从触摸屏 IC 读取 adc 值 //CMD: 指令(X/Y) //返回值:读到的数据 rt_uint16_t TP_Read_AD(rt_uint8_t CMD) { rt_uint8_t count=0,i=250; rt_uint16_t Num=0; rt_pin_write(T_SCK, 0);//TCLK=0; //先拉低时钟 rt_pin_write(T_DOUT, 0);//TDIN=0; //拉低数据线 rt_pin_write(T_CS, 0);//TCS=0; //选中触摸屏 IC TP_Write_Byte(CMD);//发送命令字 while(i--); rt_pin_write(T_SCK, 0);//TCLK=0; i=250; while(i--); rt_pin_write(T_SCK, 1);//TCLK=1; //给一个时钟,清除 BUSY i=250; while(i--); rt_pin_write(T_SCK, 0);//TCLK=0; for(count=0;count<16;count++)//读出16位数据,只有高12位有效 { Num<<=1; rt_pin_write(T_SCK, 0);//TCLK=0; //下降沿有效 i=250; while(i--); rt_pin_write(T_SCK, 1);//TCLK=1; if(rt_pin_read(T_DIN))Num++; } Num>>=4; //只有高12位有效 rt_pin_write(T_CS, 1);//TCS=1; //释放片选 return(Num); } /************************************************************************** * Function Name : TOUCH_ReadData * Description : 采样物理坐标值 * Input : cmd:选择要读取是 X 轴还是 Y 轴的命令,读取 X 轴的命令为:0xD0。而读取 Y 轴的命令 为:0x90 * Output : None * Return : 读取到的物理坐标值 **************************************************************************/ static rt_uint16_t XPT2046_read_data(rt_uint8_t cmd) { rt_uint8_t i,j; rt_uint8_t read_temp[2] = {0}; rt_uint8_t write_temp[2] = {0}; rt_uint16_t read_value[TOUCH_READ_TIMES], value; rt_uint32_t total_value; /* 读取 TOUCH_READ_TIMES 次触摸值 */ for(i=0; i
>= 3; //spi右移3位,io操作右移4位 rt_pin_write(T_CS, PIN_HIGH); #else read_value[i] = TP_Read_AD(cmd); #endif } // rt_pin_write(T_CS, PIN_HIGH); /* 滤波处理 */ /* 首先从大到小排序 */ for(i=0; i<(TOUCH_READ_TIMES - 1); i++) { for(j=i+1; j
1.05 || d1==0 || d2==0)//不合格 { cnt = 0; XPT2046_draw_touch_point((const char*)&back_color, lcddev.width-20,lcddev.height-20); //清除点4 XPT2046_draw_touch_point((const char*)&pixel, 20,20); //画点1 // TP_Adj_Info_Show(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);//显示数据 continue; } tem1 = abs(pos_temp[0][0] - pos_temp[2][0]);//x1-x3 tem2 = abs(pos_temp[0][1] - pos_temp[2][1]);//y1-y3 tem1 *= tem1; tem2 *= tem2; d1 = sqrt(tem1 + tem2);//得到2、3的距离 tem1 = abs(pos_temp[1][0] - pos_temp[3][0]);//x2-x4 tem2 = abs(pos_temp[1][1] - pos_temp[3][1]);//y2-y4 tem1 *= tem1; tem2 *= tem2; d2 = sqrt(tem1 + tem2);//得到1、4的距离 fac = (float)d1 / d2; if(fac<0.95 || fac>1.05)//不合格 { cnt = 0; XPT2046_draw_touch_point((const char*)&back_color, lcddev.width-20,lcddev.height-20); //清除点4 XPT2046_draw_touch_point((const char*)&pixel, 20,20); //画点1 // TP_Adj_Info_Show(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);//显示数据 continue; } //正确了 //对角线相等 tem1 = abs(pos_temp[1][0] - pos_temp[2][0]);//x1-x3 tem2 = abs(pos_temp[1][1] - pos_temp[2][1]);//y1-y3 tem1 *= tem1; tem2 *= tem2; d1 = sqrt(tem1 + tem2);//得到2、3的距离 tem1 = abs(pos_temp[0][0] - pos_temp[3][0]);//x2-x4 tem2 = abs(pos_temp[0][1] - pos_temp[3][1]);//y2-y4 tem1 *= tem1; tem2 *= tem2; d2 = sqrt(tem1 + tem2);//得到1、4的距离 fac = (float)d1 / d2; if(fac<0.95 || fac>1.05)//不合格 { cnt = 0; XPT2046_draw_touch_point((const char*)&back_color, lcddev.width-20,lcddev.height-20); //清除点4 XPT2046_draw_touch_point((const char*)&pixel, 20,20); //画点1 // TP_Adj_Info_Show(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);//显示数据 continue; }//正确了 //计算结果 // TP_Adj_Info_Show(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);//ÏÔʾÊý¾Ý tp_dev.xfac = (float)(lcddev.width - 40) / (pos_temp[1][0] - pos_temp[0][0]);//得到xfac tp_dev.xoff = (lcddev.width - tp_dev.xfac * (pos_temp[1][0] + pos_temp[0][0])) / 2;//得到xoff tp_dev.yfac = (float)(lcddev.height - 40) / (pos_temp[2][1] - pos_temp[0][1]);//得到yfac tp_dev.yoff = (lcddev.height - tp_dev.yfac * (pos_temp[2][1] + pos_temp[0][1])) / 2;//得到yoff if(abs(tp_dev.xfac)>2 || abs(tp_dev.yfac)>2)//触摸屏和预设的相反了 { cnt = 0; XPT2046_draw_touch_point((const char*)&back_color, lcddev.width-20,lcddev.height-20); //清除点4 XPT2046_draw_touch_point((const char*)&pixel, 20,20); //画点1 tp_dev.touchtype = !tp_dev.touchtype;//修改触屏类型 if(tp_dev.touchtype)//X,Y方向与屏幕相反 { TOUCH_X_CMD = 0X90; TOUCH_Y_CMD = 0XD0; }else //X,Y方向与屏幕相同 { TOUCH_X_CMD = 0XD0; TOUCH_Y_CMD = 0X90; } continue; } LCD_Clear(back_color);//清屏 rt_thread_delay(1000); XPT2046_save_adjdata(); LCD_Clear(back_color);//清屏 return;//矫正完成 } } rt_thread_delay(10); outtime++; if(outtime>1000) { // TP_Get_Adjdata(); break; } } } static bool touch_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { static rt_uint16_t last_x = 0; static rt_uint16_t last_y = 0; if(tp_dev.sta & TP_PRES_DOWN)//触摸按下了 //(touch_state == 1) { data->point.x = tp_dev.x; data->point.y = tp_dev.y; data->state = LV_INDEV_STATE_PR; last_x = data->point.x; last_y = data->point.y; touch_state = 0; // rt_kprintf("x0: %d, y0: %d ;, touch: %d ", tp_dev.x, tp_dev.y, touch_state); } else { data->point.x = last_x; data->point.y = last_y; data->state = LV_INDEV_STATE_REL; // rt_kprintf("x1: %d, y1: %d , touch: %d \r\n", last_x, last_y); } return RT_EOK; } static void xpt2046_thread_entry(void *parameter) { lv_indev_drv_t indev_drv; XPT2046_GPIO_Init(); // XPT2046_adjust(); rt_thread_mdelay(500); //等待其他模块初始化完成 lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = touch_read; lv_indev_drv_register(&indev_drv); for(;;) { if(XPT2046_scan(0)) { // touch_state = 1; // XPT2046_save_adjdata(); } rt_thread_mdelay(30); } } #define XPT2046_THREAD_PRIORITY 20 #define XPT2046_THREAD_STACK_SIZE 1024 #define XPT2046_THREAD_TIMELICE 5 ALIGN(RT_ALIGN_SIZE) static rt_uint8_t xpt2046_thread_stack[ XPT2046_THREAD_STACK_SIZE ]; int xpt2046_init(void) { static struct rt_thread xpt2046_thread; rt_err_t result; result = rt_thread_init(&xpt2046_thread, "xpt2046", xpt2046_thread_entry, RT_NULL, (rt_uint8_t*)&xpt2046_thread_stack[0], XPT2046_THREAD_STACK_SIZE, XPT2046_THREAD_PRIORITY, XPT2046_THREAD_TIMELICE); if(RT_EOK == result) { rt_thread_startup(&xpt2046_thread); } return RT_EOK; } //INIT_APP_EXPORT(xpt2046_init); ``` 3、在 main 函数中调用 xpt2046_init() ![main.png](https://oss-club.rt-thread.org/uploads/20210131/30f2c43f8ba48f2ddebde57564d4ad0f.png) 4、编译,下载。 ![效果.gif](https://oss-club.rt-thread.org/uploads/20210130/b8d288e37c5602f8efe62476870887f8.gif)
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
mgcheng
这家伙很懒,什么也没写!
文章
12
回答
2
被采纳
0
关注TA
发私信
相关文章
1
rt_thread studio 啥时候能用呢
2
RT_Thread使用反馈帖子
3
RTT studio 下的 AT指令问题。
4
什么时候RTT Sdudio支持Ubuntu,Deepin和UOS操作系统
5
rt thread Studio 关于J-LINK下载问题
6
RT-Thread studio 调试设置问题
7
RTT-Studio 如何设置调试配置参数?
8
rt_thread studio 软件包配置
9
RT-Studio目前只能开发STM32的项目吗?
10
rtt studio 生成hex名字修改
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
19
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
6
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
5
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部