1. ADC中断产生流程
中断源:
这里是ADC和TSC共用一个中断源。
SRCPND表示哪个中断源产生了中断请求。
INTMODE:配置中断模式
配置中断屏蔽寄存器
中断挂起寄存器(用来显示当前优先级最高的、正在发生的中断, 需要清除对应位)
从SRCPND寄存器可以读到ADC和TSC复用的同一个中断源,那么如何区分呢?
可以从SUBSRCPND寄存器配置,如下:
当bit 9被置1时,表示TSC中断。那么我们需要打开subsrcmask寄存器
所以TSC中断的产生流程如下:
2. TSC编程实现
①初始化TSC,ADCTSC寄存器
②设定TSC处于“等待中断模式”
③使能TSC中断
INTSUBMSK
MSK/MODE
④按下,进入TSC中断
进入自动采集转换模式
启动ADC
⑤ADC中断
读数据
再次进入”等待中断模式“
启动定时器(为了处理长按或者滑动操作)
⑥定时器中断
若松开,结束
如任然按下,进入④步骤的启动ADC流程
2.1 初始化
void touchscreen_init(void) { /* 设置触摸屏接口:寄存器 */ adc_ts_reg_init(); /* 设置中断 */ adc_ts_int_init(); /* 让触摸屏控制器进入"等待中断模式" */ enter_wait_pen_down_mode(); }
2.1.1 tsc寄存器init
主要是设置预分频,产生ADC clk = 1MHz.
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); ADCDLY = 0xff; }
2.1.2 TSC interrupt init并且使能int
为了将中断源开启,这里设置SUBSRCPND 和INTSUBMSK让中断源开启。通过register_irq()注册中断号和中断服务程AdcTsIntHandle,查表得出中断号为31,这样当硬件产生中断后可以从INTOFFSET区分是哪个中断号。如下图:
void adc_ts_int_init(void) { SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);/*清中断*/ /* 注册中断处理函数 */ register_irq(31, AdcTsIntHandle); /*31号中断*/ /* 使能中断 */ INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT));//防止屏蔽(SUBMSK) //INTMSK &= ~(1<<INT_ADC_TC);//reg_irq已经使能了31中断号 }
2.1.3 进入"等待中断模式"
进入等待中断模式,YM闭合, YP, XP, XM断开,需要pull up,WAIT_PEN_DOWN表示要等待的是按下中断,当触摸屏按下时就会产生一个TSC irq,反之WAIT_PEN_UP表示要等待的是松开中断。
#define ADC_INT_BIT (10) #define TC_INT_BIT (9) #define INT_ADC_TC (31) /* ADCTSC's bits */ #define WAIT_PEN_DOWN (0<<8) /*触摸笔按下*/ #define WAIT_PEN_UP (1<<8) /*触摸笔松开*/ #define YM_ENABLE (1<<7) #define YM_DISABLE (0<<7) #define YP_ENABLE (0<<6) #define YP_DISABLE (1<<6) #define XM_ENABLE (1<<5) #define XM_DISABLE (0<<5) #define XP_ENABLE (0<<4) #define XP_DISABLE (1<<4) #define PULLUP_ENABLE (0<<3) #define PULLUP_DISABLE (1<<3) #define AUTO_PST (1<<2) /*自动转换*/ #define WAIT_INT_MODE (3) /*等待中断模式*/ #define NO_OPR_MODE (0) /*禁止模式*/ void enter_wait_pen_down_mode(void)/*等待按下模式*/ { ADCTSC = WAIT_PEN_DOWN | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE;} void enter_wait_pen_up_mode(void)/*等待松开模式*/ { ADCTSC = WAIT_PEN_UP | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE; }
2.2 TSC中断服务程序
SUBSRCPND的bit9, bit10可以区分是TC中断还是ADC中断。
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))//dat寄存器的第15位判断按下还是松开 { printf("pen up\n\r"); enter_wait_pen_down_mode(); } else { printf("pen down\n\r"); /* 进入"等待触摸笔松开的模式" */ enter_wait_pen_up_mode(); } } void AdcTsIntHandle(int irq) { if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是触摸屏中断 */ Isr_Tc(); // if (SUBSRCPND & (1<<ADC_INT_BIT)) /* ADC中断 */ // Isr_Adc(); SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);/*清中断*/
//SRCPND = 1<<31;/*在interrupt.c已经清中断了*/
}
AdcTsIntHandle函数: 这里先注解掉ADC中断,只检测单独的按下松开触摸屏操作。那当isr处理完后为了能够正常响应下一次中断,需要清中断,否则会一直触发interrupt。
Isr_Tc函数:ADCDAT0 寄存器的第15位判断按下还是松开。那么当按下后,要将控制器进入”等待松开模式“,当松开后,要将控制器配置进入”等待按下模式“。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App