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

[复制链接]
10777|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自带一个库,它将底层实现层层包裹,虽然使用起来很方便,但是从学习的角度出发是很难明白电容触摸键的工作原理。第四节将介绍一个没有用库实现驱动的例子。
下面三个附件分别是官方文档和库文件,介绍了怎么设置编程环境和使用库的API

其中,需要注意的地方是编程环境的设置。要打开language option->EnableSupportfor GCCextensions(--gcc)选项。因为官方文档用的老版本CCS,界面不太一样,所以我把新版设置界面截图如下:


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


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


下面是未修改的官方文件,可以对比一下前后的变化。


当时困扰我的主要是一下几行代码,希望新手们也思考一下。

  1. 46行 BCSCTL3 |= LFXT1S_2;
  2. 101行 TA0CTL = TASSEL_3+MC_2;
  3. 102行 TA0CCTL1 = CM_3+CCIS_2+CAP;
  4. 113行 __bis_SR_register(LPM0_bits+GIE);
  5. 114行 TA0CCTL1 ^= CCIS0;
  6. 135行 __bic_SR_register_on_exit(LPM3_bits);

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

参与人数 2威望 +4 收起 理由
xkdlwj + 3 赞一个!
tianm + 1

查看全部评分

 楼主| zoomone 发表于 2012-6-27 22:04 | 显示全部楼层
上面第四步中example.c源代码如下:
  1. /* 单片机型号 m430g2452 */


  2. #include  "msp430g2452.h"

  3. /* Define User Configuration values */
  4. /*----------------------------------*/
  5. /* Defines WDT SMCLK interval for sensor measurements*/
  6. #define WDT_meas_setting (DIV_SMCLK_512)
  7. /* Defines WDT ACLK interval for delay between measurement cycles*/
  8. #define WDT_delay_setting (DIV_ACLK_512)

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

  12. /* Definitions for use with the WDT settings*/
  13. #define DIV_ACLK_32768  (WDT_ADLY_1000)     // ACLK/32768
  14. #define DIV_ACLK_8192   (WDT_ADLY_250)      // ACLK/8192
  15. #define DIV_ACLK_512    (WDT_ADLY_16)       // ACLK/512
  16. #define DIV_ACLK_64     (WDT_ADLY_1_9)      // ACLK/64
  17. #define DIV_SMCLK_32768 (WDT_MDLY_32)       // SMCLK/32768
  18. #define DIV_SMCLK_8192  (WDT_MDLY_8)        // SMCLK/8192
  19. #define DIV_SMCLK_512   (WDT_MDLY_0_5)      // SMCLK/512
  20. #define DIV_SMCLK_64    (WDT_MDLY_0_064)    // SMCLK/64

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

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

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

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

  38.   IE1 |= WDTIE;                             // enable WDT interrupt

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

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

  42.   measure_count();                          // Establish baseline capacitance
  43.     base_cnt = meas_cnt;

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


  49.   /* Main loop starts here*/
  50.   while (1)
  51.   {
  52.     j = KEY_LVL;
  53.     key_pressed = 0;                        // Assume no keys are pressed

  54.     measure_count();                        // Measure all sensors


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

  70.      pulse_LED();                           // changes in sensor C

  71.   }
  72. }                                           // End Main

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

  75. void measure_count(void)
  76. {

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


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

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


  90. }

  91. void pulse_LED(void)
  92. {
  93.   if(key_pressed)                                                          //按下时 led0、1亮
  94.   {
  95.     P1OUT |= LED_1 + LED_2;
  96.   }else{
  97.   P1OUT = 0;
  98.   }
  99. }
  100. /* Watchdog Timer interrupt service routine*/
  101. #pragma vector=WDT_VECTOR
  102. __interrupt void watchdog_timer(void)
  103. {

  104.   __bic_SR_register_on_exit(LPM3_bits);     // 重新启动cpu
  105. }
chai1662 发表于 2012-7-4 15:28 | 显示全部楼层
楼主弄的不错,怎么没完全了
Rancho13502 发表于 2012-7-8 07:45 | 显示全部楼层
好**,是要mark下
u880 发表于 2012-7-8 08:48 | 显示全部楼层
好东西,多谢分享
huigoushang 发表于 2012-7-8 09:04 | 显示全部楼层
太详细了 好贴
G21372 发表于 2012-7-8 09:24 | 显示全部楼层
学习学习
yangguangaisha 发表于 2012-7-8 09:35 | 显示全部楼层
强帖留名
gexingyouxian 发表于 2012-7-8 09:46 | 显示全部楼层
很有参考价值
 楼主| zoomone 发表于 2012-7-8 11:16 | 显示全部楼层
:lol 可算有人发现俺这帖的价值了
tianm 发表于 2012-7-8 13:19 | 显示全部楼层
希望能多交流多共享
zxcvb110 发表于 2012-7-8 20:25 | 显示全部楼层
非常不错额分享
shmilylo 发表于 2012-7-9 08:47 | 显示全部楼层
不错 学习了  等板子到了就可以大展身手了 谢谢
aliming 发表于 2012-7-9 17:03 | 显示全部楼层
楼主有没用它控制电脑视频播放啊。
 楼主| zoomone 发表于 2012-7-9 18:02 | 显示全部楼层
楼主有没用它控制电脑视频播放啊。
aliming 发表于 2012-7-9 17:03


没有 我想这个触摸键盘的价值在于学习触摸按键的驱动原理吧
gaochy1126 发表于 2012-7-9 18:51 | 显示全部楼层
楼主给分享一个触摸板的源码呗!
 楼主| zoomone 发表于 2012-7-9 22:43 | 显示全部楼层
楼主给分享一个触摸板的源码呗!
gaochy1126 发表于 2012-7-9 18:51


我1楼的附件就是源码啊  example.zip那个
yytpy2008 发表于 2012-7-17 17:02 | 显示全部楼层
楼主,能留下QQ吗?
vivilzb1985 发表于 2012-7-17 17:33 | 显示全部楼层
非常好的东西,学习
guiliang 发表于 2012-7-19 09:01 | 显示全部楼层
很有参考价值
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

370

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部