ADC触摸屏编程_测试
itomcoil 2025-04-29 01:22 9 浏览
来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)
作者:韦东山
本文字数:5890,阅读时长:4.5分钟
第018课 ADC和触摸屏 第011节_触摸屏编程_测试
发现程序有bug,点击坐标一次,程序就完成执行,我们需要修改触摸屏文件tsib.c
static double g_kx;
static double g_ky;
static int g_ts_xc, g_ts_yc;
static int g_lcd_xc, g_lcd_yc;
static int g_ts_xy_swap = 0;
static unsigned int fb_base;
static int xres, yres, bpp;
void get_calibrate_point_data(int lcd_x, int lcd_y, int *px, int *py)
{
int pressure;
int x, y;
fb_disp_cross(lcd_x, lcd_y, 0xffffff);
/* 等待点击 */
do {
//如果pressure一直是0的话我们丢掉这些数据
ts_read_raw(&x, &y, &pressure);
} while (pressure == 0);
//让后再次读
do {
*px = x;
*py = y;
ts_read_raw(&x, &y, &pressure);
printf("get raw data: x = %08d, y = %08d\n\r", x, y);
} while (pressure);
printf("return raw data: x = %08d, y = %08d\n\r", *px, *py);
/* 直到松开才返回 */
fb_disp_cross(lcd_x, lcd_y, 0);
}
修改touchcreen.c文件添加压力值相关信息
//定义压力值全局变量
static int g_ts_pressure;
void report_ts_xy(int x, int y, int pressure);
//发现不能画线,修改 ts_read
//我们需要判断触摸笔是按下还是松开,需要添加压力值参数
/*
* 读TS原始数据, 转换为LCD坐标
* 我们需要加上压力值lcd_pressure
*/
int ts_read(int *lcd_x, int *lcd_y, int *lcd_pressure)
{
int ts_x, ts_y, ts_pressure;
int tmp_x, tmp_y;
//添加压力值参数
ts_read_raw(&ts_x, &ts_y, &ts_pressure);
if (g_ts_xy_swap)
{
swap_xy(&ts_x, &ts_y);
}
/* 使用公式计算 */
tmp_x = g_kx * (ts_x - g_ts_xc) + g_lcd_xc;
tmp_y = g_ky * (ts_y - g_ts_yc) + g_lcd_yc;
//如果值超出了LCD范围返回-1
if (tmp_x < 0 || tmp_x >= xres || tmp_y < 0 || tmp_y >= yres)
return -1;
*lcd_x = tmp_x;
*lcd_y = tmp_y;
//压力值等于全局变量ts_pressure
*lcd_pressure = ts_pressure;
return 0;
}
void ts_read_raw(int *px, int *py, int *ppressure)
{
while (g_ts_data_valid == 0);
*px = g_ts_x;
*py = g_ts_y;
*ppressure = g_ts_pressure;
g_ts_data_valid = 0;
}
//我们需要report上报压力值数据
void report_ts_xy(int x, int y, int pressure)
{
//printf("x = %08d, y = %08d\n\r", x, y);
if (g_ts_data_valid == 0)
{
g_ts_x = x;
g_ts_y = y;
g_ts_pressure = pressure;
g_ts_data_valid = 1;
}
}
void Isr_Tc(void)
{
//printf("ADCUPDN = 0x%x, ADCDAT0 = 0x%x, ADCDAT1 = 0x%x, ADCTSC = 0x%x\n\r", ADCUPDN, ADCDAT0, ADCDAT1, ADCTSC);
if (ADCDAT0 & (1<<15))
{
//printf("pen up\n\r");
enter_wait_pen_down_mode();
//如果松开就上报数据xy坐标00 压力值0
report_ts_xy(0, 0, 0);
}
else
{
//printf("pen down\n\r");
/* 进入"自动测量"模式 */
enter_auto_measure_mode();
/* 启动ADC */
ADCCON |= (1<<0);
}
}
void Isr_Adc(void)
{
int x = ADCDAT0;
int y = ADCDAT1;
static int adc_cnt = 0;
static int adc_x = 0;
static int adc_y = 0;
if (!(x & (1<<15))) /* 如果仍然按下才打印 */
{
#if 0
x &= 0x3ff;
y &= 0x3ff;
//printf("x = %08d, y = %08d\n\r", x, y);
//当我得到触电数据以后,如果当前仍是按下状态,会上报XY坐标值并且上报压力值,压力值等于1
report_ts_xy(x, y, 1);
/* 启动定时器以再次读取数据 */
ts_timer_enable();
#endif
//防止数据在最后出现很大的误差
/* 第1次启动ADC后:
* a. 要连续启动N次, 获得N个数据, 求平均值并上报
* b. 得到N次数据后, 再启动TIMER
*/
//我们直接累加
adc_x += (x & 0x3ff);
adc_y += (y & 0x3ff);
adc_cnt++;
//我们取16的话右移4位比较容易操作
if (adc_cnt == 16)
{
//右移4位
adc_x >>= 4;
adc_y >>= 4;
//上报
report_ts_xy(adc_x, adc_y, 1);
//恢复到初始值0
adc_cnt = 0;
adc_x = 0;
adc_y = 0;
/* 启动定时器以再次读取数据 */
ts_timer_enable();
}
else
{
/* 否则再次启动ADC */
/* 进入"自动测量"模式 */
enter_auto_measure_mode();
/* 启动ADC */
ADCCON |= (1<<0);
}
}
else
{
adc_cnt = 0;
adc_x = 0;
adc_y = 0;
ts_timer_disable();
enter_wait_pen_down_mode();
//如果数据转换完之前再次松开,这里我也会上报数据,0,0,0
report_ts_xy(0, 0, 0);
}
enter_wait_pen_up_mode();
}
那么我们的tslib.c中
void get_calibrate_point_data(int lcd_x, int lcd_y, int *px, int *py)
{
int pressure;
int x, y;
fb_disp_cross(lcd_x, lcd_y, 0xffffff);
/* 等待点击 */
do {
//读取ts坐标值也加上压力值
ts_read_raw(&x, &y, &pressure);
//直到压力等于0的时候才返回
} while (pressure == 0);
do {
*px = x;
*py = y;
//压力值存在的情况下表示按下状态,就一直读取数据
ts_read_raw(&x, &y, &pressure);
printf("get raw data: x = %08d, y = %08d\n\r", x, y);
} while (pressure);
//打印坐标值
printf("return raw data: x = %08d, y = %08d\n\r", *px, *py);
/* 直到松开才返回 */
//我们操作完成后消除 +
fb_disp_cross(lcd_x, lcd_y, 0);
}
//我们确定校准为什么不对,我们校准涉及 原始数据 校准公式
//我们把公式使用函数来表示
int get_lcd_x_frm_ts_x(int ts_x)
{
return g_kx * (ts_x - g_ts_xc) + g_lcd_xc;
}
int get_lcd_y_frm_ts_y(int ts_y)
{
return g_ky * (ts_y - g_ts_yc) + g_lcd_yc;
}
void ts_calibrate(void)
{
int a_ts_x, a_ts_y;
int b_ts_x, b_ts_y;
int c_ts_x, c_ts_y;
int d_ts_x, d_ts_y;
int e_ts_x, e_ts_y;
/* X轴方向 */
int ts_s1, ts_s2;
int lcd_s;
/* Y轴方向 */
int ts_d1, ts_d2;
int lcd_d;
/* 获得LCD的参数: fb_base, xres, yres, bpp */
get_lcd_params(&fb_base, &xres, &yres, &bpp);
/* 对于ABCDE, 循环: 显示"+"、点击、读ts原始值 */
/* A(50, 50) */
get_calibrate_point_data(50, 50, &a_ts_x, &a_ts_y);
/* B(xres-50, 50) */
get_calibrate_point_data(xres-50, 50, &b_ts_x, &b_ts_y);
/* C(xres-50, yres-50) */
get_calibrate_point_data(xres-50, yres-50, &c_ts_x, &c_ts_y);
/* D(50, yres-50) */
get_calibrate_point_data(50, yres-50, &d_ts_x, &d_ts_y);
/* E(xres/2, yres/2) */
get_calibrate_point_data(xres/2, yres/2, &e_ts_x, &e_ts_y);
/* 确定触摸屏数据XY是否反转 */
g_ts_xy_swap = is_ts_xy_swap(a_ts_x, a_ts_y, b_ts_x, b_ts_y);
if (g_ts_xy_swap)
{
/* 对调所有点的XY坐标 */
swap_xy(&a_ts_x, &a_ts_y);
swap_xy(&b_ts_x, &b_ts_y);
swap_xy(&c_ts_x, &c_ts_y);
swap_xy(&d_ts_x, &d_ts_y);
swap_xy(&e_ts_x, &e_ts_y);
}
/* 确定公式的参数并保存 */
ts_s1 = b_ts_x - a_ts_x;
ts_s2 = c_ts_x - d_ts_x;
lcd_s = xres-50 - 50;
ts_d1 = d_ts_y - a_ts_y;
ts_d2 = c_ts_y - b_ts_y;
lcd_d = yres-50-50;
g_kx = ((double)(2*lcd_s)) / (ts_s1 + ts_s2);
g_ky = ((double)(2*lcd_d)) / (ts_d1 + ts_d2);
g_ts_xc = e_ts_x;
g_ts_yc = e_ts_y;
g_lcd_xc = xres/2;
g_lcd_yc = yres/2;
//打印ABCDE的坐标值
printf("A lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(a_ts_x), get_lcd_y_frm_ts_y(a_ts_y));
printf("B lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(b_ts_x), get_lcd_y_frm_ts_y(b_ts_y));
printf("C lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(c_ts_x), get_lcd_y_frm_ts_y(c_ts_y));
printf("D lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(d_ts_x), get_lcd_y_frm_ts_y(d_ts_y));
printf("E lcd_x = %08d, lcd_y = %08d\n\r", get_lcd_x_frm_ts_x(e_ts_x), get_lcd_y_frm_ts_y(e_ts_y));
}
- 我们转换出的XY坐标值不是特别稳定
/* 每10ms该函数被调用一次
*/
void touchscreen_timer_irq(void)
{
/* 如果触摸屏仍被按下, 进入"自动测量模式", 启动ADC */
if (get_status_of_ts_timer() == 0)
return;
if (ADCDAT0 & (1<<15)) /* 如果松开 */
{
ts_timer_disable();
enter_wait_pen_down_mode();
//report_ts_xy(0, 0, 0);
return;
}
else /* 按下状态 */
{
/* 进入"自动测量"模式 */
enter_auto_measure_mode();
/* 启动ADC */
ADCCON |= (1<<0);
}
}
- 修改touchscreen-test.c文件
void touchscreen_test(void)
{
unsigned int fb_base;
int xres, yres, bpp;
int x, y, pressure;
/* 获得LCD的参数: fb_base, xres, yres, bpp */
get_lcd_params(&fb_base, &xres, &yres, &bpp);
touchscreen_init();
/* 清屏 */
clear_screen(0);
/* 显示文字提示较准 */
fb_print_string(70, 70, "Touc cross to calibrate touchscreen", 0xffffff);
ts_calibrate();
/* 显示文字提示绘画 */
fb_print_string(70, yres - 70, "OK! To draw!", 0xffffff);
while (1)
{
//如果结果=0则继续执行下面操作
if (ts_read(&x, &y, &pressure) == 0)
{
printf(" x = %d, y = %d\n\r", x, y);
//如果是按下状态,才会描点
if (pressure)
{
fb_put_pixel(x, y, 0xff00);
}
}
}
}
把LCD的电压值,成功转化成屏幕的坐标 要点
- 对于触摸屏要多次测量,求平均值
- 要丢弃非法值(以LCD分辨率作为判断标准)
- 校准时一定要点准
参考tslib库,
相关推荐
- 点过的网页会变色?没错,这玩意把你的浏览记录漏光了
-
提起隐私泄露这事儿,托尼其实早就麻了。。。平时网购、换手机号、注册各种账号之类的都会咔咔泄露,根本就防不住。但托尼真是没想到,浏览器里会有一个看起来完全人畜无害的功能,也在偷偷泄露我们的个人隐私,而且...
- Axure教程:高保真数据可视化原型
-
本文将介绍如何制作Axure高保真数据可视化原型,供大家参考和学习。高保真数据可视化原型设计,称得上是Axure高阶水平。数据可视化在原型设计中是一个重要的分支,但是对于Axure使用者具有一定要求。...
- Flutter web开发中禁用浏览器后退按钮
-
路由采用的go-router路由框架:finalrootNavigatorKey=GlobalKey<NavigatorState>();finalGoRouterrouter...
- jQuery 控制属性和样式
-
标记的属性each()遍历元素:each(callback)方法主要用于对选择器进行遍历,它接受一个函数为参数,该函数接受一个参数,指代元素的序号。对于标记的属性而言,可以利用each()方法配合th...
- 微信小程序入门教程之二:页面样式
-
这个系列的上一篇教程,教大家写了一个最简单的Helloworld微信小程序。但是,那只是一个裸页面,并不好看。今天接着往下讲,如何为这个页面添加样式,使它看上去更美观,教大家写出实际可以使用的页...
- 如何在Windows11的任务栏中禁用和删除天气小部件图标?
-
微软该公司已在Windows11的任务栏中添加了一个天气小部件图标,作为小部件的入口点。这个功能与之前Win10上的新闻与资讯功能相同,但是有的用户不喜欢想要关闭,不知道如何操作,下面小编为大家带来...
- CSS伪类选择器大全:提升网页交互与样式的神奇工具
-
CSS伪类选择器是前端开发中不可或缺的强大工具,它们允许我们根据元素的状态、位置或用户行为动态地应用样式。本文将全面介绍常用的伪类选择器,并通过代码示例展示其实际应用场景。一、基础交互伪类1.超链接...
- 7个Axure使用小技巧
-
编辑导读:对于Axure原型工具,很少有产品经过系统学习,一般都是直接上手,边摸索边学习,这直接导致很多快捷操作被忽视。笔者在日常工作中总结出以下小技巧,希望对各位有帮助。之前整理了2期Axure的...
- JavaScript黑暗技巧:禁止浏览器点击“后退”按钮
-
浏览网页时,当从A页面点击跳转到B页面后,一般情况下,可以点击浏览器上的“后退”按钮返回A页面。如果进入B页面后,B页面想让访问者留下,禁止返回,是否可以实现呢?这简直是要控制浏览器的行为,虽然有些邪...
- 对齐PyTorch,一文详解OneFlow的DataLoader实现
-
撰文|赵露阳在最新的OneFlowv0.5.0版本中,我们增加了许多新特性,比如:新增动态图特性:OneFlow默认以动态图模式(eager)运行,与静态图模式(graph)相比,更容易搭建网...
- Python计算机视觉编程 第一章 基本的图像操作和处理
-
以下是使用Python进行基本图像操作和处理的示例代码:使用PIL库加载图像:fromPILimportImageimage=Image.open("image.jpg"...
- PyTorch 深度学习实战(31):可解释性AI与特征可视化
-
在上一篇文章中,我们探讨了模型压缩与量化部署技术。本文将深入可解释性AI与特征可视化领域,揭示深度学习模型的决策机制,帮助开发者理解和解释模型的内部工作原理。一、可解释性AI基础1.核心概念特征重要...
- 学习编程第177天 python编程 富文本框text控件的使用
-
今天学习的是刘金玉老师零基础Python教程第72期,主要内容是python编程富文本框text控件。一、知识点1.tag_config方法:利用某个别名作为标签,具体的对应标签的属性功能配置在后面参...
- 用Python讓電腦攝像頭實現掃二維碼
-
importsys#系統模組,用來存取命令列參數與系統功能importcv2#OpenCV,處理影像與相機操作importnumpyasnp#Numpy,用來處理數值與...
- 使用Transformer来做物体检测
-
作者:JacobBriones编译:ronghuaiyang导读这是一个Facebook的目标检测Transformer(DETR)的完整指南。介绍DEtectionTRansformer(D...
- 一周热门
- 最近发表
- 标签列表
-
- ps图案在哪里 (33)
- super().__init__ (33)
- python 获取日期 (34)
- 0xa (36)
- super().__init__()详解 (33)
- python安装包在哪里找 (33)
- linux查看python版本信息 (35)
- python怎么改成中文 (35)
- php文件怎么在浏览器运行 (33)
- eval在python中的意思 (33)
- python安装opencv库 (35)
- python div (34)
- sticky css (33)
- python中random.randint()函数 (34)
- python去掉字符串中的指定字符 (33)
- python入门经典100题 (34)
- anaconda安装路径 (34)
- yield和return的区别 (33)
- 1到10的阶乘之和是多少 (35)
- python安装sklearn库 (33)
- dom和bom区别 (33)
- js 替换指定位置的字符 (33)
- python判断元素是否存在 (33)
- sorted key (33)
- shutil.copy() (33)