原创 低成本低功耗4线电阻触屏MCU实现方案

2013-12-19 16:54 2049 17 17 分类: MCU/ 嵌入式

电阻触屏因其使用简单,成本较低被广泛应用在消费市场,医疗,工业和汽车市场.其中,4线电阻触屏更是因为成本的原因,在市场中最为常见.本文将就4线电阻触屏与Xinnova 32位XN12L系列MCU连接的一个低成本低功耗方案进行讨论.

 

  1. 电阻触屏原理
dzp1.gif

 

dzp2.gif

 

测量X坐标时:

  1. )在X+,X-两电极加上一个电压Vref,Y+接一个高阻抗的ADC。
  2. )两电极间的电场呈均匀分布,方向为X+到X-。
  3. )手触摸时,两个导电层在触摸点接触,触摸点X层的电位被导至
  4. 层所接的ADC,得到电压Vx。
  5. )通过Lx/L=Vx/Vref,即可得到x点的坐标。
  6. 轴的坐标可同理将Y+,Y-接上电压Vref,然后X+电极接高阻抗ADC得到。

 

  1. 传统电阻触屏方案

在大多数应用中,一般通过外加专用的电阻触屏IC.该IC一方面检测X+,X-,Y+,Y-因用户触摸引起的电压的变化,另一方面通过I2C/SPI接口把检测到的XY坐标传输给系统MCU.该方案主要的问题是单独的触屏IC增加了系统成本.把对电阻触屏X+,X-,Y+,Y-的检测集成到系统MCU无疑是最好的选择.

由于在检测X/Y坐标位置需要用到ADC转换,并且要提供相应的信号源,一般的MCU控制比较麻烦,但幸运的是,Xinnova MCU的引脚具备多重模拟/数字复用功能,可以轻而易举的解决这个问题.

 

  1. Xinnova XN12L系列MCU简介
  2. 系列是基于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个增强型系统定时/计数器,支持正交编码信号

•        集成的片上温度传感器

•        支持各种通讯接口

  1. 个带波特率自动检测和IrDA功能UART

                      1个SPI

                       1个Quad SPI (支持Flash 4 IOs数据传输)

                       1个TWS(I2C兼容)

•        支持内存,外设间的DMA大容量数据传输

•        支持故障诊断恢复功能(WDT/BOD)

•        支持睡眠,深度睡眠和掉电三种低功耗模式

•        数据和程序的高可靠和保密性能

  1. 个128位密码的分区加密和保护技术,确保片内数据安全和防知识产权的克隆

        加密模式下的应用二次开发,更好知识产权回报

•          单电源供电(3.3v)

 

  1. 硬件连接
dzp3.gif

 

  1. 与4线电阻触屏连接示意图

 

在该方案中,Y+,X+,Y-,X-直接与MCU引脚相连,无需任何外部器件。

 

  1. 软件实现方法

在该应用中,重点考量以下几个方面:

  1. 低功耗考虑
  2. CPU时间占用考虑
  3. AD检测点考虑
  4. 反应时间/灵敏度
  5. 位置校对

考虑到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检测必须在电压信号稳定后进行,所以相应的延迟是必须的。

另外,用户在使用电阻触屏时,需加入位置校对。

dzp4.gif

 

检测方法示意图

 

 

程序例程

本例程用到下列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,((AD5<<DR0SEL)|(AD5<<DR1SEL)|(AD5<<DR2SEL)|(AD5<<DR3SEL)|(AD5<<DR4SEL)|(AD5<<DR5SEL)|(AD5<<DR6SEL)|(AD5<<DR7SEL)));

         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,(AD2<<DR0SEL)|(AD2<<DR1SEL)|(AD2<<DR2SEL)|(AD2<<DR3SEL)|(AD2<<DR4SEL)|(AD2<<DR5SEL)|(AD2<<DR6SEL)|(AD2<<DR7SEL));

         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显示屏被采用,表现稳定。

文章评论0条评论)

登录后参与讨论
我要评论
0
17
关闭 站长推荐上一条 /2 下一条