打印
[Kinetis]

从零入手Kinetis系统开发之TSI模块

[复制链接]
743|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
energy1|  楼主 | 2015-3-22 23:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
(1)首先说说什么是TSI,我们该知道现在触控技术主要分两种,电阻式触控和电容式触控(当然还有红外式和表面超声波式,这两种卡拉OK点播电视上用的较多,呵呵,要善于观察哈,不过在其他领域应用相对少些),而电容式触控感应技术貌似是从乔大爷的IPOD开始兴盛起来的,以前当然有,不过还是乔大爷发扬光大了,所以说人家是change the world,而咱们就只能know the words了,哈哈。本篇要谈的TSI模块(Touch Sensing Interface)就是飞思卡尔为简化硬件设计人员开发而嵌入到Kinetis架构的电容触控驱动模块,简单的驱动接口,接到一定面积的覆铜(最好设计成圆形或者方形,减少电容特性,呵呵)就OK了,所以大多数硬件工作FSL给咱省了,咱就在软件驱动上多下些功夫吧,到现在也写了Kinetis一部分的驱动了,觉着TSI部分的驱动写起来还是比较顺手的,思路比较清晰,下面揭晓:

相关帖子

沙发
energy1|  楼主 | 2015-3-22 23:34 | 只看该作者

(2)背景说完了,再说说原理吧(咳咳,有点写论文的感觉了,呵呵),参考的datasheet部分图片,简单的介绍下电容触摸感应的原理,不多说,上图,呵呵:


使用特权

评论回复
板凳
energy1|  楼主 | 2015-3-22 23:34 | 只看该作者

(3)还是循循善诱的来,上面既然搞清了电容触摸的原理,即电容值增加了,那就需要测得这个电容值的变化以识别手指的按下,这就是本篇的主角TSI模块要干的活了,哈哈,目前来说我只了解两种方法测量这个电容值的变化,一种是利用电容数字转换,即把电容值的变化反应到AD转换值的变化(貌似Silicon Lab一款片子是这样的),然后第二种就是飞思卡尔的这种,利用三角波电压同时充放电外部电容(可变)和内部参考电容(固定),然后采样内部计数器的计数值来确定电容的变化,第一种就不介绍了可以自己去谷歌一下,本篇就主要介绍下FSL的TSI内部构造,以便于下步的软件编程,其中有几个图非常重要,利于我们脑中建立起一个清晰的编程架构,下面上图:


使用特权

评论回复
地板
energy1|  楼主 | 2015-3-22 23:35 | 只看该作者

(4)呵呵,到这里基本原理就该清晰了,如果还不清楚,那....咳咳赶紧恶补下模拟电路和数字电路吧,哈哈,没问题的话就可以喝口水歇歇,然后咱就接着来,呵呵,软件编程部分,也就是最后的收尾部分了,该一步步的操作寄存器初始化TSI和编写触控服务程序了,这里我没法拿出一个一个寄存器来分析了,以前有网友建议过这样,不过这样有点太细了,我精力的确跟不上了,呵呵,所以只能贴出代码来了,注释都有的(这回我换成中文的了,呵呵),根据注释和官方datasheet只要一步一步认真的来肯定没问题的,有问题的话可以下面留言,我解决不了还有广大网友的嘛,群众的力量是伟大的,哈哈。扯远了,下面贴出重要代码(完整代码见附件),也不贴出太多了,代码太多给人一种难以看下去的感觉,是吧,呵呵,每个函数都贴出声明了,估计理解应该没问题:


/********************************************************************************
**Routine: TSI_Start
**Description: TSI启动函数
**Notes:
********************************************************************************/
void TSI_Start(void)
{
  TSI_Init(); /* TSI初始化 */

  TSI_SelfCalibration();  /* TSI自校准 */

  START_SCANNING; /* 打开周期性扫描 */

  ENABLE_EOR_INT; /* Init TSI OUT of Range interrupts */

  ENABLE_TSI; /* 使能TSI模块 */
}

/********************************************************************************
**Routine: TSI_Init
**Description: 初始化TSI模块,软件触发即写TSI_GENCS_SWTS
**Notes: 这里没有输入参数,所以具体使用哪一个通道可修改第二步及相关第三步的寄存器
********************************************************************************/
void TSI_Init(void)
{
  /* First step : Turn on clock to TSI module  */
  SIM_SCGC5 |= (SIM_SCGC5_TSI_MASK);
  /*******************************************************************/
  /* Second step :  */
  PORTA_PCR4 = PORT_PCR_MUX(0);       /* Enable ALT0 for portA4 */
  PORTB_PCR2 = PORT_PCR_MUX(0);       /* Enable ALT0 for portB2 */
  PORTB_PCR3 = PORT_PCR_MUX(0);       /* Enable ALT0 for portB3 */
  PORTB_PCR16 = PORT_PCR_MUX(0);      /* Enable ALT0 for portB16 */
  /*******************************************************************/
  /* Third step : setting the correspongding register */
  /*  每个电极连续扫描11次,prescaler分频8,软件触发 */
  TSI0_GENCS |= ((TSI_GENCS_NSCN(10))|(TSI_GENCS_PS(3)));
  /* 外部充电电流4uA,内部充电电流32uA,600mv delta电压, 连续扫描模式,输入时钟为Busclock/1 */
  TSI0_SCANC |= ((TSI_SCANC_EXTCHRG(3))|(TSI_SCANC_REFCHRG(31))|(TSI_SCANC_DELVOL(7))|(TSI_SCANC_SMOD(0))|(TSI_SCANC_AMPSC(0)));
  /* 使能5,8, 7,9 TSI通道 */
  TSI0_PEN = TSI_CH5_EN_MASK | TSI_CH8_EN_MASK | TSI_CH7_EN_MASK | TSI_CH9_EN_MASK;

  TSI0_GENCS |= TSI_GENCS_TSIEN_MASK;  /* Enables TSI */
}


使用特权

评论回复
5
energy1|  楼主 | 2015-3-22 23:35 | 只看该作者
/********************************************************************************
**Routine: TSI_SelfCalibration
**Description: TSI模块自校准,采样无按键情况下的电容值(即相应的计数值)作为校准值。
**Notes: 注意下,执行这个函数的时候是采用软件触发的,自校准之后采用周期性扫描
********************************************************************************/
void TSI_SelfCalibration(void)
{
  uint16 counter_temp;

  TSI0_GENCS |= TSI_GENCS_SWTS_MASK;  /* 开启TSI周期扫描 */

  while(!(TSI0_GENCS&TSI_GENCS_EOSF_MASK)){}; /* 等待扫描结束 */

  for(uint16 i=0; i<5000;i++) /* 延时一段时间 */
  {
    asm ("NOP");
  }
  /********************以下为具体校验过程(有哪些通道根据实际情况)********************************/
  counter_temp = ELECTRODE5_COUNT;  /* 采样无按键情况下电容值 */
  if(counter_temp > ELECTRODE_Shake)  /* 限幅 */
    TSI0_THRESHLD5 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp - ELECTRODE_Shake);
  else
    TSI0_THRESHLD5 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp);

  counter_temp = ELECTRODE8_COUNT;  /* 采样无按键情况下电容值 */
  if(counter_temp > ELECTRODE_Shake)  /* 限幅 */
    TSI0_THRESHLD8 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp - ELECTRODE_Shake);
  else
    TSI0_THRESHLD8 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp);

  counter_temp = ELECTRODE7_COUNT;  /* 采样无按键情况下电容值 */
  if(counter_temp > ELECTRODE_Shake)  /* 限幅 */
    TSI0_THRESHLD7 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp - ELECTRODE_Shake);
  else
    TSI0_THRESHLD7 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp);

  counter_temp = ELECTRODE9_COUNT;  /* 采样无按键情况下电容值 */
  if(counter_temp > ELECTRODE_Shake)  /* 限幅 */
    TSI0_THRESHLD9 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp - ELECTRODE_Shake);
  else
    TSI0_THRESHLD9 = TSI_THRESHLD_HTHH(counter_temp + ELECTRODE_Shake) | TSI_THRESHLD_LTHH(counter_temp);

   DISABLE_TSI; /* 先禁止,等待在TSI_START里再使能 */
}
/********************************************************************************
**Routine: TSI_isr
**Description: TSI模块,out of Range 中断服务程序,中断服务号为99,IRQ为83
**Notes:
********************************************************************************/
void TSI_isr(void)
{
  uint16 Status = 0;

  TSI0_GENCS |= TSI_GENCS_OUTRGF_MASK;
  TSI0_GENCS |= TSI_GENCS_EOSF_MASK;

  Status = (uint16) (TSI0_STATUS & 0x0000FFFF);
  if(Status != 0xFFFF)  /* 确定是OUT OF Range中断(排除掉ERROR中断) */
    Debounce_Counter--;
  else
    Debounce_Counter = DBOUNCE_COUNTS;  /* 复位去抖动系数 */
  if(!Debounce_Counter)
  {
    Debounce_Counter = DBOUNCE_COUNTS;  /* 复位去抖动系数 */

    switch(Status)
    {
      case TSI_STATUS_ORNGF0_MASK:

                  break;
      case TSI_STATUS_ORNGF1_MASK:

                  break;
      case TSI_STATUS_ORNGF2_MASK:

                  break;
      case TSI_STATUS_ORNGF3_MASK:

                  break;
      case TSI_STATUS_ORNGF4_MASK:

                  break;
      case TSI_STATUS_ORNGF5_MASK:
                  GPIO_Toggle(PORTA,11);
                  break;
      case TSI_STATUS_ORNGF6_MASK:

                  break;
      case TSI_STATUS_ORNGF7_MASK:
                  GPIO_Toggle(PORTA,29);
                  break;
      case TSI_STATUS_ORNGF8_MASK:
                  GPIO_Toggle(PORTA,28);
                  break;
      case TSI_STATUS_ORNGF9_MASK:
                  GPIO_Toggle(PORTA,10);
                  break;
      case TSI_STATUS_ORNGF10_MASK:

                  break;
      case TSI_STATUS_ORNGF11_MASK:

                  break;
      case TSI_STATUS_ORNGF12_MASK:

                  break;
      case TSI_STATUS_ORNGF13_MASK:

                  break;
      case TSI_STATUS_ORNGF14_MASK:

                  break;
      case TSI_STATUS_ORNGF15_MASK:

                  break;   
      default:
                  break;

    }
  }
  TSI0_STATUS = 0xFFFFFFFF; /* 清零标志 */
}
上面是TSI的驱动部分,具体调用可能有些人不是很明白,这里就再贴出主函数的调用方法,汗,没办法,我是担心不全说明白,估计我又该被问的忙不过来了,呵呵


使用特权

评论回复
6
energy1|  楼主 | 2015-3-22 23:35 | 只看该作者
/**********************************************************************************
**File Name: test.c
**Description: project test file, used to test some modules function of k60
**Editor: jicheng at Shandong University, all copyrights are reserved.
**Date: 2012.3.x
**History: V1.0
***********************************************************************************/
#include "system.h"
#include "common.h"
#include "gpio.h"
#include "tsi.h"

void main(void)
{
  //---------------insert your code in the following--------------
  GPIO_Init(PORTA,11,1,1);
  GPIO_Init(PORTA,28,1,0);
  GPIO_Init(PORTA,29,1,1);
  GPIO_Init(PORTA,10,1,0);

  TSI_Start();

  enable_irq(INT_TSI0-16);  /* 使能TSI的IRQ中断 */

  EnableInterrupts;

  while(1)
  {

  }
}

使用特权

评论回复
7
FSL_TICS_ZJJ| | 2015-4-10 14:48 | 只看该作者
非常感谢你关于Kinetis的经验分享 !

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

422

帖子

10

粉丝