打印

分享触摸按键Capacitive Touch BoosterPack的学习经验

[复制链接]
8849|41
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zoomone|  楼主 | 2012-6-27 21:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zoomone 于 2012-6-27 22:07 编辑

学习完msp430单片机后开始惦记那块随板带的BoosterPack触摸板。心想不就是个小键盘吗,应该不难。真是不学不知道,一学吓一跳。想正常使用真的没那么简单,现在我把我的经验分享一下,让和我一样的触摸按键新手少走些弯路。

一、电容触摸按键工作原理
我在网上找到一份别人的笔记,写的很好,如下:

电容触摸感应原理与应用(1)2)(3
通俗的讲,单片机驱动电容触摸键的方式主要分两种:
1、将电容值转化成脉冲,电容变大脉冲频率变低
2、向电容充电,在电压一样时,电容越大,需要的充电的时间越长

M430g2452单片机自带一个电容触摸键驱动功能Pin Oscillator,实质上采用第一种驱动方式。示意图如下:


二、Capacitive Touch BoosterPack介绍
BoosterPack的电路原理图如下:


按键分布图:


所谓的电容按键其实也只是一层普通的PCB铜箔。
下面是TI官网BoosterPack数据手册。
BoosterPack MAIN.pdf (3.76 MB)

三、官方编程指南
BoosterPack自带一个库,它将底层实现层层包裹,虽然使用起来很方便,但是从学习的角度出发是很难明白电容触摸键的工作原理。第四节将介绍一个没有用库实现驱动的例子。
下面三个附件分别是官方文档和库文件,介绍了怎么设置编程环境和使用库的API
Getting Started With Capacitive Touch Software Library.pdf (397.84 KB) Capacitive Touch Library.pdf (572.54 KB) touch lib.zip (206.93 KB)
其中,需要注意的地方是编程环境的设置。要打开language option->EnableSupportfor GCCextensions(--gcc)选项。因为官方文档用的老版本CCS,界面不太一样,所以我把新版设置界面截图如下:


官方库里面很多写好的例子,可以参考库的使用。


四、用例子示范电容触摸键的底层驱动
这个例子其实也是来自官方,但是官方例子不是针对m430g2452驱动Capacitive Touch BoosterPack的,所以,直接编译是不会正常工作。其中涉及很多的寄存器的设置,如果是新手很难知道怎样修改才能正常工作。我就是在这里花费了大量时间,我理解后把源码注释了一下,希望能给大家提供方便。
例子工作的现象是按下相应的电容按键后开发板上的两个led灯就会亮,松手灯灭。
修改后的源文件

example.zip (2.33 KB)
下面是未修改的官方文件,可以对比一下前后的变化。

msp430g2xx2_pinosc_01.zip (2.56 KB)
当时困扰我的主要是一下几行代码,希望新手们也思考一下。
 
46行 BCSCTL3 |= LFXT1S_2;
101行 TA0CTL = TASSEL_3+MC_2;
102行 TA0CCTL1 = CM_3+CCIS_2+CAP;
113行 __bis_SR_register(LPM0_bits+GIE);
114行 TA0CCTL1 ^= CCIS0;
135行 __bic_SR_register_on_exit(LPM3_bits);
评分
参与人数 2威望 +4 收起 理由
xkdlwj + 3 赞一个!
tianm + 1

相关帖子

沙发
zoomone|  楼主 | 2012-6-27 22:04 | 只看该作者
上面第四步中example.c源代码如下:
/* 单片机型号 m430g2452 */


#include  "msp430g2452.h"

/* Define User Configuration values */
/*----------------------------------*/
/* Defines WDT SMCLK interval for sensor measurements*/
#define WDT_meas_setting (DIV_SMCLK_512)
/* Defines WDT ACLK interval for delay between measurement cycles*/
#define WDT_delay_setting (DIV_ACLK_512)

/* Sensor settings*/
#define KEY_LVL     10                     //不能太大  Defines threshold for a key press
/*Set to ~ half the max delta expected*/

/* Definitions for use with the WDT settings*/
#define DIV_ACLK_32768  (WDT_ADLY_1000)     // ACLK/32768
#define DIV_ACLK_8192   (WDT_ADLY_250)      // ACLK/8192
#define DIV_ACLK_512    (WDT_ADLY_16)       // ACLK/512
#define DIV_ACLK_64     (WDT_ADLY_1_9)      // ACLK/64
#define DIV_SMCLK_32768 (WDT_MDLY_32)       // SMCLK/32768
#define DIV_SMCLK_8192  (WDT_MDLY_8)        // SMCLK/8192
#define DIV_SMCLK_512   (WDT_MDLY_0_5)      // SMCLK/512
#define DIV_SMCLK_64    (WDT_MDLY_0_064)    // SMCLK/64

#define LED_1   (0x01)                      // P1.0 LED output
#define LED_2   (0x40)                      // P1.6 LED output

// Global variables for sensing
unsigned int base_cnt, meas_cnt;          //base_cnt为没有按键时计算来的基准计数,通常不变   meas_cnt为实时测来的计数,没按键时和base_cnt接近,按键时要比和base_cnt大
int delta_cnt;                                           //base_cnt和meas_cnt之差,作为是否按键的依据
char key_pressed;                                         //是否按键的标志

/* System Routines*/
void measure_count(void);                   // Measures each capacitive sensor
void pulse_LED(void);                       // LED gradient routine

/* Main Function*/
void main(void)
{
  unsigned int i,j;
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1MHz
  DCOCTL =  CALDCO_1MHZ;
  BCSCTL3 |= LFXT1S_2;                    // ACLK通常由LFXT1作为时钟源,所以ACLK即VLO               LFXT1 = VLO

  IE1 |= WDTIE;                             // enable WDT interrupt

  P1DIR = LED_1 + LED_2;                    // P1.0 & P1.6 = LEDs
  P1OUT = 0x00;

   __bis_SR_register(GIE);                  // Enable interrupts 使能全局中断

  measure_count();                          // Establish baseline capacitance
    base_cnt = meas_cnt;

  for(i=15; i>0; i--)                       // 计算base_cnt的平均值
  {
    measure_count();
      base_cnt = (meas_cnt+base_cnt)/2;
  }


  /* Main loop starts here*/
  while (1)
  {
    j = KEY_LVL;
    key_pressed = 0;                        // Assume no keys are pressed

    measure_count();                        // Measure all sensors


      delta_cnt = base_cnt - meas_cnt;  // Calculate delta: c_change
_nop();//方便调试时设置断点,观察delta_cnt等的数值
      /* Handle baseline measurment for a base C decrease*/
      if (delta_cnt < 0)                    // If negative: result increased
      {                                     // beyond baseline, i.e. cap dec
          base_cnt = (base_cnt+meas_cnt) >> 1; // Re-average quickly
          delta_cnt = 0;                    // Zero out for pos determination
      }
      if (delta_cnt > j)                    // Determine if each key is pressed
      {                                     // per a preset threshold
        j = delta_cnt;
        key_pressed = 1;                    // key pressed
      }
      else
        key_pressed = 0;

     pulse_LED();                           // changes in sensor C

  }
}                                           // End Main

/* Measure count result (capacitance) of each sensor*/
/* Routine setup for four sensors, not dependent on NUM_SEN value!*/

void measure_count(void)
{

  TA0CTL = TASSEL_3+MC_2;                   // TASSEL_3目的是把PinOscillator作为时钟源
  TA0CCTL1 = CM_3+CCIS_2+CAP;               // CM_3上升下降沿都计数,CAP捕捉模式 ,  CCIS_2此时不进行捕捉


    /*决定哪个io口作为电容按键的输入接口*/
          P2DIR &= ~ BIT5;                        // P2.5 中键  P2.1左键 P2.2下键 P2.3右键 P2.4上键 P2.0外边沿
    P2SEL &= ~ BIT5;
    P2SEL2 |= BIT5;

    /*Setup Gate Timer*/
    WDTCTL = WDT_meas_setting;              // 启动看门狗 工作在计数器模式下       WDT, ACLK, interval timer
    TA0CTL |= TACLR;                        // 清零 TAR
    __bis_SR_register(LPM0_bits+GIE);       // 关闭cpu但计数器仍然工作,这样做的目的是确保下面的代码在看门狗中断发生后才执行
    TA0CCTL1 ^= CCIS0;                      // 捕捉一次计数器的计数值,即将此时的TAR复制到TACCR1
    meas_cnt = TACCR1;                      // 保存TACCR1,即在看门狗计数器启动到中断发生这段时间内发生的PinOscillator脉冲个数
    WDTCTL = WDTPW + WDTHOLD;               // 关闭看门狗


}

void pulse_LED(void)
{
  if(key_pressed)                                                          //按下时 led0、1亮
  {
    P1OUT |= LED_1 + LED_2;
  }else{
  P1OUT = 0;
  }
}
/* Watchdog Timer interrupt service routine*/
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{

  __bic_SR_register_on_exit(LPM3_bits);     // 重新启动cpu
}

使用特权

评论回复
板凳
chai1662| | 2012-7-4 15:28 | 只看该作者
楼主弄的不错,怎么没完全了

使用特权

评论回复
地板
Rancho13502| | 2012-7-8 07:45 | 只看该作者
好**,是要mark下

使用特权

评论回复
5
u880| | 2012-7-8 08:48 | 只看该作者
好东西,多谢分享

使用特权

评论回复
6
huigoushang| | 2012-7-8 09:04 | 只看该作者
太详细了 好贴

使用特权

评论回复
7
G21372| | 2012-7-8 09:24 | 只看该作者
学习学习

使用特权

评论回复
8
yangguangaisha| | 2012-7-8 09:35 | 只看该作者
强帖留名

使用特权

评论回复
9
gexingyouxian| | 2012-7-8 09:46 | 只看该作者
很有参考价值

使用特权

评论回复
10
zoomone|  楼主 | 2012-7-8 11:16 | 只看该作者
:lol 可算有人发现俺这帖的价值了

使用特权

评论回复
11
tianm| | 2012-7-8 13:19 | 只看该作者
希望能多交流多共享

使用特权

评论回复
12
zxcvb110| | 2012-7-8 20:25 | 只看该作者
非常不错额分享

使用特权

评论回复
13
shmilylo| | 2012-7-9 08:47 | 只看该作者
不错 学习了  等板子到了就可以大展身手了 谢谢

使用特权

评论回复
14
aliming| | 2012-7-9 17:03 | 只看该作者
楼主有没用它控制电脑视频播放啊。

使用特权

评论回复
15
zoomone|  楼主 | 2012-7-9 18:02 | 只看该作者
楼主有没用它控制电脑视频播放啊。
aliming 发表于 2012-7-9 17:03


没有 我想这个触摸键盘的价值在于学习触摸按键的驱动原理吧

使用特权

评论回复
16
gaochy1126| | 2012-7-9 18:51 | 只看该作者
楼主给分享一个触摸板的源码呗!

使用特权

评论回复
17
zoomone|  楼主 | 2012-7-9 22:43 | 只看该作者
楼主给分享一个触摸板的源码呗!
gaochy1126 发表于 2012-7-9 18:51


我1楼的附件就是源码啊  example.zip那个

使用特权

评论回复
18
yytpy2008| | 2012-7-17 17:02 | 只看该作者
楼主,能留下QQ吗?

使用特权

评论回复
19
vivilzb1985| | 2012-7-17 17:33 | 只看该作者
非常好的东西,学习

使用特权

评论回复
20
guiliang| | 2012-7-19 09:01 | 只看该作者
很有参考价值

使用特权

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

本版积分规则

3

主题

370

帖子

2

粉丝