热度 17
2013-12-19 16:54
2049 次阅读|
0 个评论
电阻触屏因其使用简单,成本较低被广泛应用在消费市场,医疗,工业和汽车市场.其中,4线电阻触屏更是因为成本的原因,在市场中最为常见.本文将就4线电阻触屏与 Xinnova 32位XN12L系列MCU连接的一个低成本低功耗方案进行讨论. 电阻触屏原理 测量X坐标时: )在X+,X-两电极加上一个电压Vref,Y+接一个高阻抗的ADC。 )两电极间的电场呈均匀分布,方向为X+到X-。 )手触摸时,两个导电层在触摸点接触,触摸点X层的电位被导至 层所接的ADC,得到电压Vx。 )通过Lx/L=Vx/Vref,即可得到x点的坐标。 轴的坐标可同理将Y+,Y-接上电压Vref,然后X+电极接高阻抗ADC得到。 传统电阻触屏方案 在大多数应用中,一般通过外加专用的电阻触屏IC.该IC一方面检测X+,X-,Y+,Y-因用户触摸引起的电压的变化,另一方面通过I2C/SPI接口把检测到的XY坐标传输给系统MCU.该方案主要的问题是单独的触屏IC增加了系统成本.把对电阻触屏X+,X-,Y+,Y-的检测集成到系统MCU无疑是最好的选择. 由于在检测X/Y坐标位置需要用到ADC转换,并且要提供相应的信号源,一般的MCU控制比较麻烦,但幸运的是,Xinnova MCU的引脚具备多重模拟/数字复用功能,可以轻而易举的解决这个问题. Xinnova XN12L系列MCU简介 系列是基于ARM M0内核的通用MCU。该系列可以涵盖从低端到高端各种MCU应用,具有高性能,低成本,代码加密可靠等特点,是取代8位机16位理想的产品。与其它MCU相比,XN12L系列指令精简,内含用于增强运算的xDSP,主频更是可高达100MHz,外设丰富实用,支持在线调试,在目前MCU市场上表现非凡。主要特点有: • 高达100MHz ARM Cortex M0 CPU • 高达88KB用户Flash和16KB SRAM • xDSP 用于增强MCU运算功能 32位单周期除法器 CORDIC运算器 CRC校验 • 多种时钟系统供用户选择 1%精度的内部晶振 支持外部时钟和晶振 内部PLL 支持实时时钟(RTC) • 多达3个独立的ADC转换器更适合系统高速采样需求 12位,1MHz采样率 多达12路ADC通道 • 2个模拟比较器 • 10位DAC,1MHz转换率 • 4个增强型系统定时/计数器,支持正交编码信号 • 集成的片上温度传感器 • 支持各种通讯接口 个带波特率自动检测和IrDA功能UART 1个SPI 1个Quad SPI (支持Flash 4 IOs数据传输) 1个TWS(I2C兼容) • 支持内存,外设间的DMA大容量数据传输 • 支持故障诊断恢复功能(WDT/BOD) • 支持睡眠,深度睡眠和掉电三种低功耗模式 • 数据和程序的高可靠和保密性能 个128位密码的分区加密和保护技术,确保片内数据安全和防知识产权的克隆 加密模式下的应用二次开发,更好知识产权回报 • 单电源供电(3.3v) 硬件连接 与4线电阻触屏连接示意图 在该方案中,Y+,X+,Y-,X-直接与MCU引脚相连,无需任何外部器件。 软件实现方法 在该应用中,重点考量以下几个方面: 低功耗考虑 CPU时间占用考虑 AD检测点考虑 反应时间/灵敏度 位置校对 考虑到CPU时间占用和功耗,CPU不要时时刻刻对Y+,X+,Y-,X-进行检测。只有在用户触屏时才会做出反应。因此,我们考虑使用中断来对用户触屏进行检测。在平常,X+,X-设置为GPIO输出低电平,而Y+,Y-为GPIO带内部上拉输入,并允许下降沿中断。无触摸时,CPU没有任何动作且没有任何功耗在电阻触屏。当用户触屏时,Y+,Y-变为低并触发中断。在该中断处理程序中,我们需把X+端口置为高电平,同时把Y+,Y-设为ADC输入。在检测到Y+的电压值(该电压值对应触点X轴位置)后,把Y+,Y-设置为GPIO输出,且Y+为高,Y-为低,X+,X-设为ADC输入并对X+进行检测。检测到的电压值对应触点Y轴位置。在检测结束后,恢复X+,X-设置为GPIO输出低电平,而Y+,Y-为GPIO带内部上拉输入,并允许下降沿中断。 注意,在对X,Y进行位置ADC检测时,由于存在高低电平转换,需注意ADC检测必须在电压信号稳定后进行,所以相应的延迟是必须的。 另外,用户在使用电阻触屏时,需加入位置校对。 检测方法示意图 程序例程 本例程用到下列 Xinnova MCU库函数,请参看 Xinnova 网页和论坛。 Xn12lxxx.h: device description file Xn_adc.h: ADC h file Xn_adc.c: ADC driver file Xn_uart.h: UART h file Xn_UART: UART driver file /***************************************************************************** // PIO1_0 (AD2) - X- // PIO1_1 (AD3) - Y- // PIO1_2 (AD4) - X+ // PIO1_3 (AD5) - Y+ ** *****************************************************************************/ uint32_t x,y; void SetTouchIO(void) { //init Touch XN_IOCON-PIO1_0 = 0x91; //x- XN_IOCON-PIO1_1 = 0x91; //y- XN_IOCON-PIO1_2 = 0x90; //x+ XN_IOCON-PIO1_3 = 0x90; //y+ XN_GPIO1-DIR = 0x05; //set x-,x+ as output XN_GPIO1-OUT = 0; //x-,x+ set to low delayms(100); XN_GPIO1-IBE = 0x02; //沿触发中断 //XN_GPIO1-IC = 0x02; //清除中断 //XN_GPIO1-IE = 0x02; //NVIC_EnableIRQ(EINT1_IRQn); } uint32_t TouchPressed(void) { //verify if y is low if ((XN_GPIO1-PIN 0x2)==0) return 1; else return 0; } void ReadXY(uint32_t * x,uint32_t* y) { uint32_t temp; *x=0; *y=0; //Read x SetADCPin(AD3PIN|AD5PIN); XN_IOCON-PIO1_0 = 0x91; //x- XN_IOCON-PIO1_2 = 0x90; //x+ XN_GPIO1-MASK = 0xFFFFFFF0; XN_GPIO1-DIR = 0x05; XN_GPIO1-OUT = 0x04; //X+ 3.3v;X- GND //SetADCPin(AD3PIN|AD5PIN); ADCInit(XN_ADC0,10000,TRIGGERMODE,START_BY_SOFTWAER, 0); //?K conversion rate and software trigger ADCSelChannel(XN_ADC0,((AD5DR0SEL)|(AD5DR1SEL)|(AD5DR2SEL)|(AD5DR3SEL)|(AD5DR4SEL)|(AD5DR5SEL)|(AD5DR6SEL)|(AD5DR7SEL))); delayms(100); ADCSoftwareTrigger(XN_ADC0); do { temp=ADCValue(XN_ADC0,DR7); }while(temp==0xFFFFFFFF); *x =temp; //Read y SetADCPin(AD2|AD4); XN_IOCON-PIO1_1 = 0x91; //y- XN_IOCON-PIO1_3 = 0x90; //y+ XN_GPIO1-MASK = 0xFFFFFFF0; XN_GPIO1-DIR = 0x0A; XN_GPIO1-OUT = 0x02; //y+ 3.3v;y- GND //SetADCPin(AD2|AD4); ADCSelChannel(XN_ADC0,(AD2DR0SEL)|(AD2DR1SEL)|(AD2DR2SEL)|(AD2DR3SEL)|(AD2DR4SEL)|(AD2DR5SEL)|(AD2DR6SEL)|(AD2DR7SEL)); delayms(100); ADCSoftwareTrigger(XN_ADC0); do { temp=ADCValue(XN_ADC0,DR7); }while(temp==0xFFFFFFFF); *y =temp; } int main(void) { //disable watchdog XN_WDT-MOD = 0; //init Touch SetTouchIO(); XN_GPIO1-IC = 0x02; //清除中断 XN_GPIO1-IE = 0x02; //enable INT NVIC_EnableIRQ(EINT1_IRQn); while (1) { // Loop forever } } void EINT1_IRQHandler(void) { NVIC_DisableIRQ(EINT1_IRQn); XN_GPIO1-IE = 0x0; //屏蔽GPIO1 IO 中断 if (TouchPressed()) { ReadXY(touch_x,touch_y); SetTouchIO(); if (TouchPressed()) { touch_xy_new=1; UART0PutHex (touch_x); UART0Send(",",1); UART0PutHex (touch_y); UART0Send(" ",4); } } XN_GPIO1-IC = 0x02; //清除中断 XN_GPIO1-IE = 0x02; //enable INT NVIC_EnableIRQ(EINT1_IRQn); return; } 总结 Xinnova MCU 引脚复用,配置灵活。在应对4线电阻触屏应用中占用较少资源,使用简单。该方法在EBike显示屏被采用,表现稳定。