来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)
作者:韦东山
本文字数:2725,阅读时长:3.5分钟
第018课 ADC和触摸屏 第006节_触摸屏编程_ADC中断
这节课我们加上ADC中断把触点的xy坐标读出来
查看touchscreen.c
写出这个自动测量的函数
void enter_auto_measure_mode(void)
{
//现在是自动测量,我们没有机会分别设置这些开关
设置AUTO_PST =1
XY_PST = 00
ADCTSC = AUTO_PST | NO_OPR_MODE;
}
现在是自动测量,我们没有机会分别设置这些开关
进入中断处理函数
void AdcTsIntHandle(int irq)
{
if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是触摸屏中断 */
Isr_Tc();
if (SUBSRCPND & (1<<ADC_INT_BIT)) /* ADC中断,则会进入Adc中断处理函数 */
Isr_Adc();
SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);
}
进入触摸屏中断处理函数
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();
}
else
{
/* 进入"自动测量"模式 */
enter_auto_measure_mode();
/* 启动ADC */
ENABLE_START = 1就可以了
ADCCON |= (1<<0);
}
}
启动ADC
Adc中断处理函数
void Isr_Adc(void)
{
进入adc中断后,等待触摸笔松开
int x = ADCDAT0 & 0x3ff;
int y = ADCDAT1 & 0x3ff;
printf("x = %08d, y = %08d\n\r", x, y);
//等待触摸笔松开模式
enter_wait_pen_up_mode();
}
烧写
实验发现打印一堆乱码
应该是printf函数出了问题打开my_printf.c文件,找到printf函数应该是处理第二个数据的时候,没有设置初始值
/*reference : int vprintf(const char *format, va_list ap); */
static int my_vprintf(const char *fmt, va_list ap)
{
char lead=' ';
int maxwidth=0;
for(; *fmt != '\0'; fmt++)
{
if (*fmt != '%') {
outc(*fmt);
continue;
}
//碰到 % 就重新处理, 初始值应该重新设置初始值上去
lead=' ';
maxwidth=0;
//format : %08d, %8d,%d,%u,%x,%f,%c,%s
fmt++;
if(*fmt == '0'){
lead = '0';
fmt++;
}
while(*fmt >= '0' && *fmt <= '9'){
maxwidth *=10;
maxwidth += (*fmt - '0');
fmt++;
}
switch (*fmt) {
case 'd': out_num(va_arg(ap, int), 10,lead,maxwidth); break;
case 'o': out_num(va_arg(ap, unsigned int), 8,lead,maxwidth); break;
case 'u': out_num(va_arg(ap, unsigned int), 10,lead,maxwidth); break;
case 'x': out_num(va_arg(ap, unsigned int), 16,lead,maxwidth); break;
case 'c': outc(va_arg(ap, int )); break;
case 's': outs(va_arg(ap, char *)); break;
default:
outc(*fmt);
break;
}
}
return 0;
}
重新烧写执行,发现数据变化幅度很大,但至少Adc已经有输出
我们需要解决输出值不线性的问题
到底是触摸屏质量问题,还是Adc转化精度问题,觉得应该是触摸屏电压不稳定之前不知道DELAY寄存器是用来干嘛的
等待中断模式时,当触摸笔按下时我们会产生中断,但是可以通过 DELAY来延时产生中断
在前面有一张图
按下触摸笔,延迟A才可以产生中断,你才可以测量X Y坐标A = D(晶振的周期)D就是 DELAY就是那个寄存器的值晶振周期时12M我们需要设置一下
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中断
* 10ms为120000
* 延时时间 = ADCDLY * 晶振周期 = ADCDLY * 1 / 12000000 = 5ms
*/
ADCDLY = 60000;
}
再次烧写,发现数据并不规律我们需要再次改进程序
我们按下触摸屏会产生触摸屏中断,启动自动测量,启动Adc,Adc成功后会进入Adc中断,在函数中打印数据
也许测量过程很长我们就需要判断
void Isr_Adc(void)
{
int x = ADCDAT0;
int y = ADCDAT1;
//松开的话打印也是错误的值,所以如果仍然按下才打印
if (!(x & (1<<15))) /* 如果仍然按下才打印 */
{
x &= 0x3ff;
y &= 0x3ff;
//打印10进制
printf("x = %08d, y = %08d\n\r", x, y);
}
enter_wait_pen_up_mode();
}
烧写执行
发现X Y轴输出有问题
厂家把X Y轴搞反了
电路图中TSYP TSXP接反TSYM TSXM接反
我们后面使用触摸屏时会使用软件处理这点,不会导致任何问题
有一个缺点我们按下触摸屏会输出一个数据,再按下触摸屏又输出一个数据我长按并没有输出数据,我滑动也没有输出数据我们需要使用定时器改进这个问题
各种方向的旋转都可以由软件转换
我们需要把触摸屏的坐标TS XY坐标转换成LCD的XY坐标需要用应用程序做我们常使用Tslib库来做,这些旋转倒置都没有问题