ADC和触摸屏(2)-按下松开检测
- 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
- 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
- 参考资料:开发版原理图,S3C2440A datasheet
- 源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-1
目录
一、前言
在017 ADC和触摸屏(1)-硬件原理介绍这一篇博文中,介绍了相关的硬件操作,接下来开始编写程序。
二、相关寄存器
1、ADC和触摸屏硬件设置寄存器
1.1 ADCCON
/* [15] : ECFLG, 1 = End of A/D conversion
* [14] : PRSCEN, 1 = A/D converter prescaler enable
* [13:6]: PRSCVL, adc clk = PCLK / (PRSCVL + 1)
* [5:3] : SEL_MUX, 000 = AIN 0
* [2] : STDBM
* [0] : 1 = A/D conversion starts and this bit is cleared after the startup.
*/
ADCCON = (1 << 14) | (49 << 6) | (0 << 3);
ADCDLY = 0xff;
2.2 ADCTSC
这个是用来主要用来控制触摸屏电路中的开关闭合,这里我们先宏定义,供后面使用。
/* ADCTSC's bits */
#define PEN_UP_BIT (1 << 8)
#define PEN_DOWN_BIT (0 << 8)
#define YM_OUT_ENABLE (1 << 7)
#define YM_OUT_DISABLE (0 << 7)
#define YP_OUT_ENABLE (0 << 6)
#define YP_OUT_DISABLE (1 << 6)
#define XM_OUT_ENABLE (1 << 5)
#define XM_OUT_DISABLE (0 << 5)
#define XP_OUT_ENABLE (0 << 4)
#define XP_OUT_DISABLE (1 << 4)
#define XP_POLLUP_ENABLE (0 << 3)
#define XP_POLLUP_DISABLE (1 << 3)
#define NO_OPR_MODE (0 << 0)
#define WAIT_INTER_MODE (3 << 0)
#define AUTO_PST (1 << 2)
3.3 ADCDAT0
int x = ADCDAT0 & 0x3ff;
3.4 ADCDAT1
int y = ADCDAT1 & 0x3ff;
2、中断设置相关寄存器
关于ADC和触摸屏的大致中断流程图如下
2.1 SRCPND
2.2 INTMSK
2.3 SUBSRCPND
中断发生后需要清除对应标志位
/* 清中断 */
SUBSRCPND = (1 << INT_TC) | (1 << INT_ADC_S);
2.4 INTSUBMSK
/* 使能中断 */
INTSUBMSK &= ~((1 << ADC_INT_BIT) | (1 << TC_INT_BIT));
三、程序编写
1、程序流程图
这中,大致介绍了程序的逻辑如下:
- 按下触摸屏,产生触摸中断
- 在触摸中断中,启动ADC
- ADC初始化完成后,产生中断
- 在ADC中断中,读取(x, y)坐标
- 启动定时器中断
- 定时器中断发生时,判断触摸屏是否被持续按下
- 若是继续执行 2 步骤,若无则判断为无按下,结束整个流程
具体的程序编写过程如下图表示:
2、touchscreen.c文件编写
#include "../s3c2440_soc.h"
#define ADC_INT_BIT (10)
#define TC_INT_BIT (9)
#define INT_ADC_S (10)
#define INT_TC (9)
#define INT_ADC_TSC (31)
/* ADCTSC's bits */
#define PEN_UP_BIT (1 << 8)
#define PEN_DOWN_BIT (0 << 8)
#define YM_OUT_ENABLE (1 << 7)
#define YM_OUT_DISABLE (0 << 7)
#define YP_OUT_ENABLE (0 << 6)
#define YP_OUT_DISABLE (1 << 6)
#define XM_OUT_ENABLE (1 << 5)
#define XM_OUT_DISABLE (0 << 5)
#define XP_OUT_ENABLE (0 << 4)
#define XP_OUT_DISABLE (1 << 4)
#define XP_POLLUP_ENABLE (0 << 3)
#define XP_POLLUP_DISABLE (1 << 3)
#define NO_OPR_MODE (0 << 0)
#define WAIT_INTER_MODE (3 << 0)
#define AUTO_PST (1 << 2)
void enter_wait_pen_down(void)
{
/* 设置寄存器,控制开关,处于等待中断模式*/
ADCTSC = PEN_DOWN_BIT | YM_OUT_ENABLE | XP_POLLUP_ENABLE | XP_OUT_DISABLE | YP_OUT_DISABLE | XM_OUT_DISABLE | WAIT_INTER_MODE;
}
void enter_wait_pen_up(void)
{
/* 设置寄存器,控制开关,处于等待中断模式*/
ADCTSC = PEN_UP_BIT | YM_OUT_ENABLE | XP_POLLUP_ENABLE | XP_OUT_DISABLE | YP_OUT_DISABLE | XM_OUT_DISABLE | WAIT_INTER_MODE;
}
void enter_auto_measure_mode(void)
{
ADCTSC = AUTO_PST | NO_OPR_MODE;
}
void Isr_Adc(void)
{
int x, y;
/* 电容笔处于按下 */
if (!(ADCDAT0 & (1 << 15))) {
x = ADCDAT0 & 0x3ff;
y = ADCDAT1 & 0x3ff;
printf("x =%08d,y =%08d\n\r", x, y);
}
enter_wait_pen_up();
}
void Isr_Tc(void)
{
if (ADCDAT0 & (1 << 15)) {
enter_wait_pen_down();
}
else {
/* 进入自动测量模式 */
enter_auto_measure_mode();
/* 开启ADC */
ADCCON |= (1<<0);
}
}
/* 中断服务函数 */
void AdcTsIntHandle(void)
{
if (SUBSRCPND & (1 << INT_TC)) /* 触摸屏中断 */
Isr_Tc();
if (SUBSRCPND & (1 << INT_ADC_S)) /* ADC中断 */
Isr_Adc();
/* 清中断 */
SUBSRCPND = (1 << INT_TC) | (1 << INT_ADC_S);
}
void adc_ts_int_init(int irq)
{
/* 注册中断服务函数采用之前课上的函数 */
register_irq(irq, AdcTsIntHandle);
/* 使能中断 */
INTSUBMSK &= ~((1 << ADC_INT_BIT) | (1 << TC_INT_BIT));
}
void adc_ts_reg_init(void)
{
/* [15] : ECFLG, 1 = End of A/D conversion
* [14] : PRSCEN, 1 = A/D converter prescaler enable
* [13:6]: PRSCVL, adc clk = PCLK / (PRSCVL + 1)
* [5:3] : SEL_MUX, 000 = AIN 0
* [2] : STDBM
* [0] : 1 = A/D conversion starts and this bit is cleared after the startup.
*/
ADCCON = (1 << 14) | (49 << 6) | (0 << 3);
/* 按下触摸屏, 延时一会再发出TC中断
* 延时时间 = ADCDLY * 晶振周期 = ADCDLY * 1 / 12000000 = 5ms
*/
ADCDLY = 60000;
}
/* 触摸屏初始化 */
void touchsrceen_init(void)
{
/* 设置中断 */
adc_ts_int_init(INT_ADC_TSC);
/* 设置触摸屏接口:寄存器 */
adc_ts_reg_init();
/* 让触摸屏控制器进入"等待中断(等待触摸笔按下)模式" */
enter_wait_pen_down();
}
3、touchscreen_test.c文件编写
void touchscreen_test(void)
{
touchsrceen_init();
}
四、测试结果
从左往右,从上往下连续点击触摸屏,发现:可以检测到按下和松开,但是硬件上连接问题,使得触摸屏的xy对应LCD的显示屏的yx,后续通过软件解决这个问题。